summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/gpu.tmpl60
-rw-r--r--Documentation/devicetree/bindings/sound/ak4613.txt10
-rw-r--r--Documentation/devicetree/bindings/sound/atmel-pdmic.txt55
-rw-r--r--Documentation/devicetree/bindings/sound/da7218.txt104
-rw-r--r--Documentation/devicetree/bindings/sound/da7219.txt8
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,asrc.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,esai.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,spdif.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/img,i2s-in.txt47
-rw-r--r--Documentation/devicetree/bindings/sound/img,i2s-out.txt51
-rw-r--r--Documentation/devicetree/bindings/sound/img,parallel-out.txt44
-rw-r--r--Documentation/devicetree/bindings/sound/img,pistachio-internal-dac.txt18
-rw-r--r--Documentation/devicetree/bindings/sound/img,spdif-in.txt41
-rw-r--r--Documentation/devicetree/bindings/sound/img,spdif-out.txt44
-rw-r--r--Documentation/devicetree/bindings/sound/inno-rk3036.txt20
-rw-r--r--Documentation/devicetree/bindings/sound/pcm179x.txt (renamed from Documentation/devicetree/bindings/sound/pcm1792a.txt)2
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsnd.txt82
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt4
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-i2s.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/rt5616.txt26
-rw-r--r--Documentation/devicetree/bindings/sound/rt5651.txt41
-rw-r--r--Documentation/devicetree/bindings/sound/rt5659.txt75
-rw-r--r--Documentation/devicetree/bindings/sound/rt5677.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/sun4i-codec.txt3
-rw-r--r--Documentation/devicetree/bindings/sound/ti,pcm3168a.txt48
-rw-r--r--Documentation/devicetree/bindings/sound/wlf,wm8974.txt15
-rw-r--r--Documentation/sound/alsa/img,spdif-in.txt49
-rw-r--r--arch/arm/mach-s3c64xx/dev-audio.c47
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/dma.h52
-rw-r--r--arch/arm/plat-samsung/devs.c23
-rw-r--r--arch/x86/include/asm/platform_sst_audio.h1
-rw-r--r--arch/x86/kernel/early-quirks.c1
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h2
-rw-r--r--drivers/gpu/drm/armada/armada_fb.c4
-rw-r--r--drivers/gpu/drm/armada/armada_fb.h2
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h3
-rw-r--r--drivers/gpu/drm/ast/ast_fb.c2
-rw-r--r--drivers/gpu/drm/ast/ast_main.c4
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c2
-rw-r--r--drivers/gpu/drm/bochs/bochs.h2
-rw-r--r--drivers/gpu/drm/bochs/bochs_fbdev.c2
-rw-r--r--drivers/gpu/drm/bochs/bochs_mm.c4
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.h3
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_fbdev.c2
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_main.c4
-rw-r--r--drivers/gpu/drm/drm_atomic.c18
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c252
-rw-r--r--drivers/gpu/drm/drm_crtc.c4
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c8
-rw-r--r--drivers/gpu/drm/drm_edid.c62
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c4
-rw-r--r--drivers/gpu/drm/drm_fops.c58
-rw-r--r--drivers/gpu/drm/drm_gem.c35
-rw-r--r--drivers/gpu/drm/drm_modes.c35
-rw-r--r--drivers/gpu/drm/drm_modeset_lock.c89
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c4
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c47
-rw-r--r--drivers/gpu/drm/drm_rect.c7
-rw-r--r--drivers/gpu/drm/drm_sysfs.c54
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.h2
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c18
-rw-r--r--drivers/gpu/drm/gma500/gem.c19
-rw-r--r--drivers/gpu/drm/gma500/gma_display.c13
-rw-r--r--drivers/gpu/drm/gma500/gtt.c1
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h2
-rw-r--r--drivers/gpu/drm/i915/Kconfig1
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/dvo.h3
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c37
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c244
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c26
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c170
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h188
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c73
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c12
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c4
-rw-r--r--drivers/gpu/drm/i915/i915_gem_fence.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c58
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.h7
-rw-r--r--drivers/gpu/drm/i915/i915_gem_stolen.c3
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c4
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c40
-rw-r--r--drivers/gpu/drm/i915/i915_guc_reg.h53
-rw-r--r--drivers/gpu/drm/i915/i915_guc_submission.c16
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c117
-rw-r--r--drivers/gpu/drm/i915/i915_params.c10
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h2742
-rw-r--r--drivers/gpu/drm/i915/i915_sysfs.c3
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h4
-rw-r--r--drivers/gpu/drm/i915/i915_vgpu.c6
-rw-r--r--drivers/gpu/drm/i915/i915_vgpu.h14
-rw-r--r--drivers/gpu/drm/i915/intel_atomic.c3
-rw-r--r--drivers/gpu/drm/i915/intel_atomic_plane.c2
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c102
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c14
-rw-r--r--drivers/gpu/drm/i915/intel_csr.c284
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c142
-rw-r--r--drivers/gpu/drm/i915/intel_display.c798
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c1040
-rw-r--r--drivers/gpu/drm/i915/intel_dp_link_training.c323
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c18
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h159
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.c45
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.h2
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c27
-rw-r--r--drivers/gpu/drm/i915/intel_fbc.c196
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c50
-rw-r--r--drivers/gpu/drm/i915/intel_fifo_underrun.c127
-rw-r--r--drivers/gpu/drm/i915/intel_guc.h8
-rw-r--r--drivers/gpu/drm/i915/intel_guc_fwif.h72
-rw-r--r--drivers/gpu/drm/i915/intel_guc_loader.c105
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c77
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c31
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c148
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.h19
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c11
-rw-r--r--drivers/gpu/drm/i915/intel_mocs.c61
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c2
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c630
-rw-r--r--drivers/gpu/drm/i915/intel_psr.c77
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c156
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h9
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c492
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c61
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c28
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c261
-rw-r--r--drivers/gpu/drm/imx/Kconfig9
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c12
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_fb.c2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_main.c4
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h4
-rw-r--r--drivers/gpu/drm/msm/msm_fb.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.h1
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c4
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c4
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h2
-rw-r--r--drivers/gpu/drm/qxl/qxl_fb.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.c6
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.h2
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_kms.c2
-rw-r--r--drivers/gpu/drm/tegra/Kconfig12
-rw-r--r--drivers/gpu/drm/tegra/drm.c4
-rw-r--r--drivers/gpu/drm/tegra/drm.h8
-rw-r--r--drivers/gpu/drm/tegra/fb.c16
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c2
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h2
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c5
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c4
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_fb.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c2
-rw-r--r--drivers/pci/quirks.c4
-rw-r--r--include/drm/drmP.h5
-rw-r--r--include/drm/drm_atomic.h6
-rw-r--r--include/drm/drm_atomic_helper.h8
-rw-r--r--include/drm/drm_crtc.h12
-rw-r--r--include/drm/drm_crtc_helper.h2
-rw-r--r--include/drm/drm_dp_helper.h36
-rw-r--r--include/drm/drm_fb_cma_helper.h2
-rw-r--r--include/drm/drm_gem.h106
-rw-r--r--include/drm/drm_mm.h26
-rw-r--r--include/drm/drm_modes.h2
-rw-r--r--include/drm/drm_modeset_lock.h4
-rw-r--r--include/drm/drm_rect.h3
-rw-r--r--include/drm/i915_component.h83
-rw-r--r--include/drm/i915_pciids.h36
-rw-r--r--include/linux/platform_data/asoc-s3c.h8
-rw-r--r--include/sound/ac97_codec.h3
-rw-r--r--include/sound/compress_driver.h7
-rw-r--r--include/sound/core.h1
-rw-r--r--include/sound/da7218.h109
-rw-r--r--include/sound/da7219.h14
-rw-r--r--include/sound/designware_i2s.h6
-rw-r--r--include/sound/hda_i915.h14
-rw-r--r--include/sound/hda_register.h9
-rw-r--r--include/sound/hdaudio_ext.h21
-rw-r--r--include/sound/i2c.h2
-rw-r--r--include/sound/rawmidi.h2
-rw-r--r--include/sound/rt5659.h49
-rw-r--r--include/sound/soc-dai.h1
-rw-r--r--include/sound/soc-dapm.h4
-rw-r--r--include/sound/soc-topology.h6
-rw-r--r--include/sound/soc.h53
-rw-r--r--include/uapi/drm/i915_drm.h11
-rw-r--r--include/uapi/sound/asoc.h2
-rw-r--r--include/uapi/sound/compress_params.h5
-rw-r--r--kernel/async.c1
-rw-r--r--sound/core/compress_offload.c99
-rw-r--r--sound/core/init.c3
-rw-r--r--sound/core/oss/mixer_oss.c8
-rw-r--r--sound/core/oss/pcm_oss.c10
-rw-r--r--sound/core/pcm_native.c26
-rw-r--r--sound/core/seq/oss/seq_oss.c7
-rw-r--r--sound/core/seq/seq_clientmgr.c2
-rw-r--r--sound/core/seq/seq_queue.c2
-rw-r--r--sound/core/seq/seq_virmidi.c2
-rw-r--r--sound/core/timer.c76
-rw-r--r--sound/drivers/dummy.c4
-rw-r--r--sound/firewire/Kconfig12
-rw-r--r--sound/firewire/Makefile2
-rw-r--r--sound/firewire/dice/dice-transaction.c123
-rw-r--r--sound/firewire/dice/dice.c227
-rw-r--r--sound/firewire/dice/dice.h3
-rw-r--r--sound/firewire/fireworks/fireworks.h4
-rw-r--r--sound/firewire/fireworks/fireworks_midi.c16
-rw-r--r--sound/firewire/fireworks/fireworks_pcm.c28
-rw-r--r--sound/firewire/fireworks/fireworks_stream.c32
-rw-r--r--sound/firewire/oxfw/Makefile4
-rw-r--r--sound/firewire/oxfw/oxfw-scs1x.c406
-rw-r--r--sound/firewire/oxfw/oxfw-spkr.c (renamed from sound/firewire/oxfw/oxfw-control.c)142
-rw-r--r--sound/firewire/oxfw/oxfw.c110
-rw-r--r--sound/firewire/oxfw/oxfw.h23
-rw-r--r--sound/firewire/scs1x.c530
-rw-r--r--sound/hda/ext/hdac_ext_controller.c29
-rw-r--r--sound/hda/ext/hdac_ext_stream.c72
-rw-r--r--sound/hda/hdac_i915.c66
-rw-r--r--sound/i2c/i2c.c2
-rw-r--r--sound/oss/Kconfig2
-rw-r--r--sound/pci/atiixp.c6
-rw-r--r--sound/pci/atiixp_modem.c4
-rw-r--r--sound/pci/azt3328.c2
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c4
-rw-r--r--sound/pci/fm801.c145
-rw-r--r--sound/pci/hda/hda_controller.c10
-rw-r--r--sound/pci/hda/hda_controller.h14
-rw-r--r--sound/pci/hda/hda_eld.c1
-rw-r--r--sound/pci/hda/hda_generic.c108
-rw-r--r--sound/pci/hda/hda_generic.h5
-rw-r--r--sound/pci/hda/hda_intel.c78
-rw-r--r--sound/pci/hda/hda_tegra.c5
-rw-r--r--sound/pci/hda/patch_conexant.c3
-rw-r--r--sound/pci/hda/patch_hdmi.c245
-rw-r--r--sound/pci/hda/patch_realtek.c14
-rw-r--r--sound/pci/ice1712/delta.c2
-rw-r--r--sound/soc/Kconfig2
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/amd/Kconfig4
-rw-r--r--sound/soc/amd/Makefile3
-rw-r--r--sound/soc/amd/acp-pcm-dma.c1043
-rw-r--r--sound/soc/amd/acp.h118
-rw-r--r--sound/soc/amd/include/acp_2_2_d.h609
-rw-r--r--sound/soc/amd/include/acp_2_2_enum.h1068
-rw-r--r--sound/soc/amd/include/acp_2_2_sh_mask.h2292
-rw-r--r--sound/soc/atmel/Kconfig9
-rw-r--r--sound/soc/atmel/Makefile2
-rw-r--r--sound/soc/atmel/atmel-classd.c26
-rw-r--r--sound/soc/atmel/atmel-pdmic.c738
-rw-r--r--sound/soc/atmel/atmel-pdmic.h80
-rw-r--r--sound/soc/atmel/atmel_wm8904.c1
-rw-r--r--sound/soc/bcm/bcm2835-i2s.c12
-rw-r--r--sound/soc/codecs/Kconfig62
-rw-r--r--sound/soc/codecs/Makefile22
-rw-r--r--sound/soc/codecs/ak4613.c118
-rw-r--r--sound/soc/codecs/arizona.c146
-rw-r--r--sound/soc/codecs/arizona.h17
-rw-r--r--sound/soc/codecs/cs47l24.c1148
-rw-r--r--sound/soc/codecs/cs47l24.h23
-rw-r--r--sound/soc/codecs/da7218.c3341
-rw-r--r--sound/soc/codecs/da7218.h1414
-rw-r--r--sound/soc/codecs/da7219.c163
-rw-r--r--sound/soc/codecs/da7219.h9
-rw-r--r--sound/soc/codecs/hdac_hdmi.c697
-rw-r--r--sound/soc/codecs/inno_rk3036.c490
-rw-r--r--sound/soc/codecs/inno_rk3036.h123
-rw-r--r--sound/soc/codecs/max98357a.c10
-rw-r--r--sound/soc/codecs/pcm1792a.c271
-rw-r--r--sound/soc/codecs/pcm179x.c271
-rw-r--r--sound/soc/codecs/pcm179x.h (renamed from sound/soc/codecs/pcm1792a.h)6
-rw-r--r--sound/soc/codecs/pcm3168a-i2c.c66
-rw-r--r--sound/soc/codecs/pcm3168a-spi.c65
-rw-r--r--sound/soc/codecs/pcm3168a.c767
-rw-r--r--sound/soc/codecs/pcm3168a.h100
-rw-r--r--sound/soc/codecs/rt286.c6
-rw-r--r--sound/soc/codecs/rt298.c2
-rw-r--r--sound/soc/codecs/rt5616.c1381
-rw-r--r--sound/soc/codecs/rt5616.h1819
-rw-r--r--sound/soc/codecs/rt5640.c103
-rw-r--r--sound/soc/codecs/rt5640.h17
-rw-r--r--sound/soc/codecs/rt5645.c322
-rw-r--r--sound/soc/codecs/rt5651.c31
-rw-r--r--sound/soc/codecs/rt5659.c4223
-rw-r--r--sound/soc/codecs/rt5659.h1819
-rw-r--r--sound/soc/codecs/rt5677.c13
-rw-r--r--sound/soc/codecs/ssm2518.c2
-rw-r--r--sound/soc/codecs/twl6040.c3
-rw-r--r--sound/soc/codecs/wm5110.c252
-rw-r--r--sound/soc/codecs/wm8903.c2
-rw-r--r--sound/soc/codecs/wm8904.c2
-rw-r--r--sound/soc/codecs/wm8960.c24
-rw-r--r--sound/soc/codecs/wm8962.c3
-rw-r--r--sound/soc/codecs/wm8974.c7
-rw-r--r--sound/soc/codecs/wm8998.c46
-rw-r--r--sound/soc/codecs/wm9713.c296
-rw-r--r--sound/soc/codecs/wm_adsp.c1095
-rw-r--r--sound/soc/codecs/wm_adsp.h28
-rw-r--r--sound/soc/dwc/designware_i2s.c117
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c21
-rw-r--r--sound/soc/fsl/fsl_asrc.c62
-rw-r--r--sound/soc/fsl/fsl_asrc.h9
-rw-r--r--sound/soc/fsl/fsl_esai.c63
-rw-r--r--sound/soc/fsl/fsl_sai.c98
-rw-r--r--sound/soc/fsl/fsl_sai.h3
-rw-r--r--sound/soc/fsl/fsl_spdif.c35
-rw-r--r--sound/soc/fsl/fsl_ssi.c49
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c2
-rw-r--r--sound/soc/fsl/imx-pcm-fiq.c4
-rw-r--r--sound/soc/fsl/imx-wm8962.c10
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c3
-rw-r--r--sound/soc/fsl/p1022_ds.c3
-rw-r--r--sound/soc/fsl/p1022_rdk.c3
-rw-r--r--sound/soc/generic/simple-card.c12
-rw-r--r--sound/soc/img/Kconfig52
-rw-r--r--sound/soc/img/Makefile7
-rw-r--r--sound/soc/img/img-i2s-in.c516
-rw-r--r--sound/soc/img/img-i2s-out.c565
-rw-r--r--sound/soc/img/img-parallel-out.c327
-rw-r--r--sound/soc/img/img-spdif-in.c806
-rw-r--r--sound/soc/img/img-spdif-out.c441
-rw-r--r--sound/soc/img/pistachio-internal-dac.c287
-rw-r--r--sound/soc/intel/Kconfig58
-rw-r--r--sound/soc/intel/atom/sst-atom-controls.c5
-rw-r--r--sound/soc/intel/atom/sst-atom-controls.h1
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c32
-rw-r--r--sound/soc/intel/atom/sst/sst_acpi.c82
-rw-r--r--sound/soc/intel/atom/sst/sst_stream.c2
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-pcm.c2
-rw-r--r--sound/soc/intel/boards/Makefile6
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c266
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c332
-rw-r--r--sound/soc/intel/boards/cht_bsw_max98090_ti.c19
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c19
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c19
-rw-r--r--sound/soc/intel/boards/skl_nau88l25_max98357a.c485
-rw-r--r--sound/soc/intel/boards/skl_nau88l25_ssm4567.c536
-rw-r--r--sound/soc/intel/boards/skl_rt286.c128
-rw-r--r--sound/soc/intel/common/Makefile12
-rw-r--r--sound/soc/intel/common/sst-acpi.c41
-rw-r--r--sound/soc/intel/common/sst-acpi.h33
-rw-r--r--sound/soc/intel/common/sst-dsp-priv.h8
-rw-r--r--sound/soc/intel/common/sst-dsp.c2
-rw-r--r--sound/soc/intel/common/sst-dsp.h2
-rw-r--r--sound/soc/intel/common/sst-firmware.c20
-rw-r--r--sound/soc/intel/common/sst-match-acpi.c43
-rw-r--r--sound/soc/intel/haswell/sst-haswell-dsp.c2
-rw-r--r--sound/soc/intel/haswell/sst-haswell-ipc.c31
-rw-r--r--sound/soc/intel/skylake/skl-messages.c280
-rw-r--r--sound/soc/intel/skylake/skl-nhlt.c19
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c310
-rw-r--r--sound/soc/intel/skylake/skl-sst-cldma.c97
-rw-r--r--sound/soc/intel/skylake/skl-sst-dsp.h21
-rw-r--r--sound/soc/intel/skylake/skl-sst-ipc.c123
-rw-r--r--sound/soc/intel/skylake/skl-sst-ipc.h14
-rw-r--r--sound/soc/intel/skylake/skl-sst.c217
-rw-r--r--sound/soc/intel/skylake/skl-topology.c658
-rw-r--r--sound/soc/intel/skylake/skl-topology.h63
-rw-r--r--sound/soc/intel/skylake/skl-tplg-interface.h105
-rw-r--r--sound/soc/intel/skylake/skl.c213
-rw-r--r--sound/soc/intel/skylake/skl.h8
-rw-r--r--sound/soc/mediatek/mtk-afe-common.h1
-rw-r--r--sound/soc/mediatek/mtk-afe-pcm.c59
-rw-r--r--sound/soc/omap/omap-hdmi-audio.c2
-rw-r--r--sound/soc/pxa/brownstone.c3
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c6
-rw-r--r--sound/soc/qcom/lpass-cpu.c1
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c139
-rw-r--r--sound/soc/rockchip/rockchip_max98090.c6
-rw-r--r--sound/soc/rockchip/rockchip_rt5645.c6
-rw-r--r--sound/soc/samsung/Kconfig2
-rw-r--r--sound/soc/samsung/ac97.c29
-rw-r--r--sound/soc/samsung/bells.c40
-rw-r--r--sound/soc/samsung/dma.h6
-rw-r--r--sound/soc/samsung/dmaengine.c20
-rw-r--r--sound/soc/samsung/i2s.c31
-rw-r--r--sound/soc/samsung/littlemill.c32
-rw-r--r--sound/soc/samsung/odroidx2_max98090.c9
-rw-r--r--sound/soc/samsung/pcm.c25
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c16
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c16
-rw-r--r--sound/soc/samsung/snow.c9
-rw-r--r--sound/soc/samsung/spdif.c17
-rw-r--r--sound/soc/samsung/speyside.c12
-rw-r--r--sound/soc/samsung/tobermory.c21
-rw-r--r--sound/soc/sh/Kconfig1
-rw-r--r--sound/soc/sh/fsi.c11
-rw-r--r--sound/soc/sh/rcar/Makefile2
-rw-r--r--sound/soc/sh/rcar/adg.c118
-rw-r--r--sound/soc/sh/rcar/cmd.c171
-rw-r--r--sound/soc/sh/rcar/core.c586
-rw-r--r--sound/soc/sh/rcar/ctu.c99
-rw-r--r--sound/soc/sh/rcar/dma.c245
-rw-r--r--sound/soc/sh/rcar/dvc.c273
-rw-r--r--sound/soc/sh/rcar/gen.c133
-rw-r--r--sound/soc/sh/rcar/mix.c158
-rw-r--r--sound/soc/sh/rcar/rcar_snd.h117
-rw-r--r--sound/soc/sh/rcar/rsnd.h335
-rw-r--r--sound/soc/sh/rcar/rsrc-card.c129
-rw-r--r--sound/soc/sh/rcar/src.c898
-rw-r--r--sound/soc/sh/rcar/ssi.c755
-rw-r--r--sound/soc/sh/rcar/ssiu.c225
-rw-r--r--sound/soc/soc-ac97.c125
-rw-r--r--sound/soc/soc-compress.c31
-rw-r--r--sound/soc/soc-core.c866
-rw-r--r--sound/soc/soc-dapm.c14
-rw-r--r--sound/soc/soc-ops.c4
-rw-r--r--sound/soc/soc-pcm.c110
-rw-r--r--sound/soc/sti/uniperif_player.c3
-rw-r--r--sound/soc/sunxi/sun4i-codec.c279
-rw-r--r--sound/soc/tegra/tegra_alc5632.c12
-rw-r--r--sound/soc/tegra/tegra_wm8903.c3
-rw-r--r--sound/synth/emux/emux_nrpn.c9
-rw-r--r--sound/usb/card.c2
-rw-r--r--sound/usb/midi.c27
-rw-r--r--sound/usb/misc/ua101.c4
-rw-r--r--sound/usb/mixer_quirks.c2
-rw-r--r--sound/usb/quirks.c1
-rw-r--r--sound/usb/stream.c6
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c2
430 files changed, 45195 insertions, 10422 deletions
diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl
index 201dcd3c2e9d..03f01e76add7 100644
--- a/Documentation/DocBook/gpu.tmpl
+++ b/Documentation/DocBook/gpu.tmpl
@@ -615,18 +615,6 @@ char *date;</synopsis>
<function>drm_gem_object_init</function>. Storage for private GEM
objects must be managed by drivers.
</para>
- <para>
- Drivers that do not need to extend GEM objects with private information
- can call the <function>drm_gem_object_alloc</function> function to
- allocate and initialize a struct <structname>drm_gem_object</structname>
- instance. The GEM core will call the optional driver
- <methodname>gem_init_object</methodname> operation after initializing
- the GEM object with <function>drm_gem_object_init</function>.
- <synopsis>int (*gem_init_object) (struct drm_gem_object *obj);</synopsis>
- </para>
- <para>
- No alloc-and-init function exists for private GEM objects.
- </para>
</sect3>
<sect3>
<title>GEM Objects Lifetime</title>
@@ -635,10 +623,10 @@ char *date;</synopsis>
acquired and release by <function>calling drm_gem_object_reference</function>
and <function>drm_gem_object_unreference</function> respectively. The
caller must hold the <structname>drm_device</structname>
- <structfield>struct_mutex</structfield> lock. As a convenience, GEM
- provides the <function>drm_gem_object_reference_unlocked</function> and
- <function>drm_gem_object_unreference_unlocked</function> functions that
- can be called without holding the lock.
+ <structfield>struct_mutex</structfield> lock when calling
+ <function>drm_gem_object_reference</function>. As a convenience, GEM
+ provides <function>drm_gem_object_unreference_unlocked</function>
+ functions that can be called without holding the lock.
</para>
<para>
When the last reference to a GEM object is released the GEM core calls
@@ -649,15 +637,9 @@ char *date;</synopsis>
</para>
<para>
<synopsis>void (*gem_free_object) (struct drm_gem_object *obj);</synopsis>
- Drivers are responsible for freeing all GEM object resources, including
- the resources created by the GEM core. If an mmap offset has been
- created for the object (in which case
- <structname>drm_gem_object</structname>::<structfield>map_list</structfield>::<structfield>map</structfield>
- is not NULL) it must be freed by a call to
- <function>drm_gem_free_mmap_offset</function>. The shmfs backing store
- must be released by calling <function>drm_gem_object_release</function>
- (that function can safely be called if no shmfs backing store has been
- created).
+ Drivers are responsible for freeing all GEM object resources. This includes
+ the resources created by the GEM core, which need to be released with
+ <function>drm_gem_object_release</function>.
</para>
</sect3>
<sect3>
@@ -740,17 +722,10 @@ char *date;</synopsis>
DRM identifies the GEM object to be mapped by a fake offset passed
through the mmap offset argument. Prior to being mapped, a GEM object
must thus be associated with a fake offset. To do so, drivers must call
- <function>drm_gem_create_mmap_offset</function> on the object. The
- function allocates a fake offset range from a pool and stores the
- offset divided by PAGE_SIZE in
- <literal>obj-&gt;map_list.hash.key</literal>. Care must be taken not to
- call <function>drm_gem_create_mmap_offset</function> if a fake offset
- has already been allocated for the object. This can be tested by
- <literal>obj-&gt;map_list.map</literal> being non-NULL.
+ <function>drm_gem_create_mmap_offset</function> on the object.
</para>
<para>
Once allocated, the fake offset value
- (<literal>obj-&gt;map_list.hash.key &lt;&lt; PAGE_SHIFT</literal>)
must be passed to the application in a driver-specific way and can then
be used as the mmap offset argument.
</para>
@@ -836,10 +811,11 @@ char *date;</synopsis>
abstracted from the client in libdrm.
</para>
</sect3>
- <sect3>
- <title>GEM Function Reference</title>
+ </sect2>
+ <sect2>
+ <title>GEM Function Reference</title>
!Edrivers/gpu/drm/drm_gem.c
- </sect3>
+!Iinclude/drm/drm_gem.h
</sect2>
<sect2>
<title>VMA Offset Manager</title>
@@ -4201,17 +4177,21 @@ int num_ioctls;</synopsis>
</sect2>
</sect1>
<sect1>
- <title>GuC-based Command Submission</title>
+ <title>GuC</title>
<sect2>
- <title>GuC</title>
+ <title>GuC-specific firmware loader</title>
!Pdrivers/gpu/drm/i915/intel_guc_loader.c GuC-specific firmware loader
!Idrivers/gpu/drm/i915/intel_guc_loader.c
</sect2>
<sect2>
- <title>GuC Client</title>
-!Pdrivers/gpu/drm/i915/i915_guc_submission.c GuC-based command submissison
+ <title>GuC-based command submission</title>
+!Pdrivers/gpu/drm/i915/i915_guc_submission.c GuC-based command submission
!Idrivers/gpu/drm/i915/i915_guc_submission.c
</sect2>
+ <sect2>
+ <title>GuC Firmware Layout</title>
+!Pdrivers/gpu/drm/i915/intel_guc_fwif.h GuC Firmware Layout
+ </sect2>
</sect1>
<sect1>
diff --git a/Documentation/devicetree/bindings/sound/ak4613.txt b/Documentation/devicetree/bindings/sound/ak4613.txt
index 15a919522b42..1783f9ef0930 100644
--- a/Documentation/devicetree/bindings/sound/ak4613.txt
+++ b/Documentation/devicetree/bindings/sound/ak4613.txt
@@ -7,6 +7,16 @@ Required properties:
- compatible : "asahi-kasei,ak4613"
- reg : The chip select number on the I2C bus
+Optional properties:
+- asahi-kasei,in1-single-end : Boolean. Indicate input / output pins are single-ended.
+- asahi-kasei,in2-single-end rather than differential.
+- asahi-kasei,out1-single-end
+- asahi-kasei,out2-single-end
+- asahi-kasei,out3-single-end
+- asahi-kasei,out4-single-end
+- asahi-kasei,out5-single-end
+- asahi-kasei,out6-single-end
+
Example:
&i2c {
diff --git a/Documentation/devicetree/bindings/sound/atmel-pdmic.txt b/Documentation/devicetree/bindings/sound/atmel-pdmic.txt
new file mode 100644
index 000000000000..e0875f17c229
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-pdmic.txt
@@ -0,0 +1,55 @@
+* Atmel PDMIC driver under ALSA SoC architecture
+
+Required properties:
+- compatible
+ Should be "atmel,sama5d2-pdmic".
+- reg
+ Should contain PDMIC registers location and length.
+- interrupts
+ Should contain the IRQ line for the PDMIC.
+- dmas
+ One DMA specifiers as described in atmel-dma.txt and dma.txt files.
+- dma-names
+ Must be "rx".
+- clock-names
+ Required elements:
+ - "pclk" peripheral clock
+ - "gclk" generated clock
+- clocks
+ Must contain an entry for each required entry in clock-names.
+ Please refer to clock-bindings.txt.
+- atmel,mic-min-freq
+ The minimal frequency that the micphone supports.
+- atmel,mic-max-freq
+ The maximal frequency that the micphone supports.
+
+Optional properties:
+- pinctrl-names, pinctrl-0
+ Please refer to pinctrl-bindings.txt.
+- atmel,model
+ The user-visible name of this sound card.
+ The default value is "PDMIC".
+- atmel,mic-offset
+ The offset that should be added.
+ The range is from -32768 to 32767.
+ The default value is 0.
+
+Example:
+ pdmic@f8018000 {
+ compatible = "atmel,sama5d2-pdmic";
+ reg = <0xf8018000 0x124>;
+ interrupts = <48 IRQ_TYPE_LEVEL_HIGH 7>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
+ | AT91_XDMAC_DT_PERID(50))>;
+ dma-names = "rx";
+ clocks = <&pdmic_clk>, <&pdmic_gclk>;
+ clock-names = "pclk", "gclk";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pdmic_default>;
+ atmel,model = "PDMIC @ sama5d2_xplained";
+ atmel,mic-min-freq = <1000000>;
+ atmel,mic-max-freq = <3246000>;
+ atmel,mic-offset = <0x0>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/da7218.txt b/Documentation/devicetree/bindings/sound/da7218.txt
new file mode 100644
index 000000000000..5ca5a709b6aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/da7218.txt
@@ -0,0 +1,104 @@
+Dialog Semiconductor DA7218 Audio Codec bindings
+
+DA7218 is an audio codec with HP detect feature.
+
+======
+
+Required properties:
+- compatible : Should be "dlg,da7217" or "dlg,da7218"
+- reg: Specifies the I2C slave address
+
+- VDD-supply: VDD power supply for the device
+- VDDMIC-supply: VDDMIC power supply for the device
+- VDDIO-supply: VDDIO power supply for the device
+ (See Documentation/devicetree/bindings/regulator/regulator.txt for further
+ information relating to regulators)
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+ the IRQs from DA7218 are delivered to.
+- interrupts: IRQ line info for DA7218 chip.
+ (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
+ further information relating to interrupt properties)
+- interrupt-names : Name associated with interrupt line. Should be "wakeup" if
+ interrupt is to be used to wake system, otherwise "irq" should be used.
+- wakeup-source: Flag to indicate this device can wake system (suspend/resume).
+
+- clocks : phandle and clock specifier for codec MCLK.
+- clock-names : Clock name string for 'clocks' attribute, should be "mclk".
+
+- dlg,micbias1-lvl-millivolt : Voltage (mV) for Mic Bias 1
+ [<1200>, <1600>, <1800>, <2000>, <2200>, <2400>, <2600>, <2800>, <3000>]
+- dlg,micbias2-lvl-millivolt : Voltage (mV) for Mic Bias 2
+ [<1200>, <1600>, <1800>, <2000>, <2200>, <2400>, <2600>, <2800>, <3000>]
+- dlg,mic1-amp-in-sel : Mic1 input source type
+ ["diff", "se_p", "se_n"]
+- dlg,mic2-amp-in-sel : Mic2 input source type
+ ["diff", "se_p", "se_n"]
+- dlg,dmic1-data-sel : DMIC1 channel select based on clock edge.
+ ["lrise_rfall", "lfall_rrise"]
+- dlg,dmic1-samplephase : When to sample audio from DMIC1.
+ ["on_clkedge", "between_clkedge"]
+- dlg,dmic1-clkrate-hz : DMic1 clock frequency (Hz).
+ [<1500000>, <3000000>]
+- dlg,dmic2-data-sel : DMic2 channel select based on clock edge.
+ ["lrise_rfall", "lfall_rrise"]
+- dlg,dmic2-samplephase : When to sample audio from DMic2.
+ ["on_clkedge", "between_clkedge"]
+- dlg,dmic2-clkrate-hz : DMic2 clock frequency (Hz).
+ [<1500000>, <3000000>]
+- dlg,hp-diff-single-supply : Boolean flag, use single supply for HP
+ (DA7217 only)
+
+======
+
+Optional Child node - 'da7218_hpldet' (DA7218 only):
+
+Optional properties:
+- dlg,jack-rate-us : Time between jack detect measurements (us)
+ [<5>, <10>, <20>, <40>, <80>, <160>, <320>, <640>]
+- dlg,jack-debounce : Number of debounce measurements taken for jack detect
+ [<0>, <2>, <3>, <4>]
+- dlg,jack-threshold-pct : Threshold level for jack detection (% of VDD)
+ [<84>, <88>, <92>, <96>]
+- dlg,comp-inv : Boolean flag, invert comparator output
+- dlg,hyst : Boolean flag, enable hysteresis
+- dlg,discharge : Boolean flag, auto discharge of Mic Bias on jack removal
+
+======
+
+Example:
+
+ codec: da7218@1a {
+ compatible = "dlg,da7218";
+ reg = <0x1a>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <11 IRQ_TYPE_LEVEL_HIGH>;
+ wakeup-source;
+
+ VDD-supply = <&reg_audio>;
+ VDDMIC-supply = <&reg_audio>;
+ VDDIO-supply = <&reg_audio>;
+
+ clocks = <&clks 201>;
+ clock-names = "mclk";
+
+ dlg,micbias1-lvl-millivolt = <2600>;
+ dlg,micbias2-lvl-millivolt = <2600>;
+ dlg,mic1-amp-in-sel = "diff";
+ dlg,mic2-amp-in-sel = "diff";
+
+ dlg,dmic1-data-sel = "lrise_rfall";
+ dlg,dmic1-samplephase = "on_clkedge";
+ dlg,dmic1-clkrate-hz = <3000000>;
+ dlg,dmic2-data-sel = "lrise_rfall";
+ dlg,dmic2-samplephase = "on_clkedge";
+ dlg,dmic2-clkrate-hz = <3000000>;
+
+ da7218_hpldet {
+ dlg,jack-rate-us = <40>;
+ dlg,jack-debounce = <2>;
+ dlg,jack-threshold-pct = <84>;
+ dlg,hyst;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/da7219.txt b/Documentation/devicetree/bindings/sound/da7219.txt
index 1b7030911a3b..cf61681826b6 100644
--- a/Documentation/devicetree/bindings/sound/da7219.txt
+++ b/Documentation/devicetree/bindings/sound/da7219.txt
@@ -28,13 +28,15 @@ Optional properties:
- clocks : phandle and clock specifier for codec MCLK.
- clock-names : Clock name string for 'clocks' attribute, should be "mclk".
-- dlg,ldo-lvl : Required internal LDO voltage (mV) level for digital engine
- [<1050>, <1100>, <1200>, <1400>]
- dlg,micbias-lvl : Voltage (mV) for Mic Bias
- [<1800>, <2000>, <2200>, <2400>, <2600>]
+ [<1600>, <1800>, <2000>, <2200>, <2400>, <2600>]
- dlg,mic-amp-in-sel : Mic input source type
["diff", "se_p", "se_n"]
+Deprecated properties:
+- dlg,ldo-lvl : Required internal LDO voltage (mV) level for digital engine
+ (LDO unavailable in production HW so property no longer required).
+
======
Child node - 'da7219_aad':
diff --git a/Documentation/devicetree/bindings/sound/fsl,asrc.txt b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
index b93362a570be..3e26a9478e57 100644
--- a/Documentation/devicetree/bindings/sound/fsl,asrc.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
@@ -25,6 +25,11 @@ Required properties:
"mem" Peripheral access clock to access registers.
"ipg" Peripheral clock to driver module.
"asrck_<0-f>" Clock sources for input and output clock.
+ "spba" The spba clock is required when ASRC is placed as a
+ bus slave of the Shared Peripheral Bus and when two
+ or more bus masters (CPU, DMA or DSP) try to access
+ it. This property is optional depending on the SoC
+ design.
- big-endian : If this property is absent, the little endian mode
will be in use as default. Otherwise, the big endian
diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt
index d3b6b5f48010..cd3ee5d84f03 100644
--- a/Documentation/devicetree/bindings/sound/fsl,esai.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt
@@ -27,6 +27,11 @@ Required properties:
derive HCK, SCK and FS.
"fsys" The system clock derived from ahb clock used to
derive HCK, SCK and FS.
+ "spba" The spba clock is required when ESAI is placed as a
+ bus slave of the Shared Peripheral Bus and when two
+ or more bus masters (CPU, DMA or DSP) try to access
+ it. This property is optional depending on the SoC
+ design.
- fsl,fifo-depth : The number of elements in the transmit and receive
FIFOs. This number is the maximum allowed value for
diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
index b5ee32ee3706..4ca39ddc0417 100644
--- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
@@ -27,6 +27,11 @@ Required properties:
Transceiver Clock Diagram" of SoC reference manual.
It can also be referred to TxClk_Source bit of
register SPDIF_STC.
+ "spba" The spba clock is required when SPDIF is placed as a
+ bus slave of the Shared Peripheral Bus and when two
+ or more bus masters (CPU, DMA or DSP) try to access
+ it. This property is optional depending on the SoC
+ design.
- big-endian : If this property is absent, the native endian mode
will be in use as default, or the big endian mode
diff --git a/Documentation/devicetree/bindings/sound/img,i2s-in.txt b/Documentation/devicetree/bindings/sound/img,i2s-in.txt
new file mode 100644
index 000000000000..423265cfc3d6
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/img,i2s-in.txt
@@ -0,0 +1,47 @@
+Imagination Technologies I2S Input Controller
+
+Required Properties:
+
+ - compatible : Compatible list, must contain "img,i2s-in"
+
+ - #sound-dai-cells : Must be equal to 0
+
+ - reg : Offset and length of the register set for the device
+
+ - clocks : Contains an entry for each entry in clock-names
+
+ - clock-names : Must include the following entry:
+ "sys" The system clock
+
+ - dmas: Contains an entry for each entry in dma-names.
+
+ - dma-names: Must include the following entry:
+ "rx" Single DMA channel used by all active I2S channels
+
+ - img,i2s-channels : Number of I2S channels instantiated in the I2S in block
+
+Optional Properties:
+
+ - interrupts : Contains the I2S in interrupts. Depending on
+ the configuration, there may be no interrupts, one interrupt,
+ or an interrupt per I2S channel. For the case where there is
+ one interrupt per channel, the interrupts should be listed
+ in ascending channel order
+
+ - resets: Contains a phandle to the I2S in reset signal
+
+ - reset-names: Contains the reset signal name "rst"
+
+Example:
+
+i2s_in: i2s-in@18100800 {
+ compatible = "img,i2s-in";
+ reg = <0x18100800 0x200>;
+ interrupts = <GIC_SHARED 7 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdc 30 0xffffffff 0>;
+ dma-names = "rx";
+ clocks = <&cr_periph SYS_CLK_I2S_IN>;
+ clock-names = "sys";
+ img,i2s-channels = <6>;
+ #sound-dai-cells = <0>;
+};
diff --git a/Documentation/devicetree/bindings/sound/img,i2s-out.txt b/Documentation/devicetree/bindings/sound/img,i2s-out.txt
new file mode 100644
index 000000000000..0159415b3338
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/img,i2s-out.txt
@@ -0,0 +1,51 @@
+Imagination Technologies I2S Output Controller
+
+Required Properties:
+
+ - compatible : Compatible list, must contain "img,i2s-out"
+
+ - #sound-dai-cells : Must be equal to 0
+
+ - reg : Offset and length of the register set for the device
+
+ - clocks : Contains an entry for each entry in clock-names
+
+ - clock-names : Must include the following entries:
+ "sys" The system clock
+ "ref" The reference clock
+
+ - dmas: Contains an entry for each entry in dma-names.
+
+ - dma-names: Must include the following entry:
+ "tx" Single DMA channel used by all active I2S channels
+
+ - img,i2s-channels : Number of I2S channels instantiated in the I2S out block
+
+ - resets: Contains a phandle to the I2S out reset signal
+
+ - reset-names: Contains the reset signal name "rst"
+
+Optional Properties:
+
+ - interrupts : Contains the I2S out interrupts. Depending on
+ the configuration, there may be no interrupts, one interrupt,
+ or an interrupt per I2S channel. For the case where there is
+ one interrupt per channel, the interrupts should be listed
+ in ascending channel order
+
+Example:
+
+i2s_out: i2s-out@18100A00 {
+ compatible = "img,i2s-out";
+ reg = <0x18100A00 0x200>;
+ interrupts = <GIC_SHARED 13 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdc 23 0xffffffff 0>;
+ dma-names = "tx";
+ clocks = <&cr_periph SYS_CLK_I2S_OUT>,
+ <&clk_core CLK_I2S>;
+ clock-names = "sys", "ref";
+ img,i2s-channels = <6>;
+ resets = <&pistachio_reset PISTACHIO_RESET_I2S_OUT>;
+ reset-names = "rst";
+ #sound-dai-cells = <0>;
+};
diff --git a/Documentation/devicetree/bindings/sound/img,parallel-out.txt b/Documentation/devicetree/bindings/sound/img,parallel-out.txt
new file mode 100644
index 000000000000..a3015d2a06e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/img,parallel-out.txt
@@ -0,0 +1,44 @@
+Imagination Technologies Parallel Output Controller
+
+Required Properties:
+
+ - compatible : Compatible list, must contain "img,parallel-out".
+
+ - #sound-dai-cells : Must be equal to 0
+
+ - reg : Offset and length of the register set for the device.
+
+ - dmas: Contains an entry for each entry in dma-names.
+
+ - dma-names: Must include the following entry:
+ "tx"
+
+ - clocks : Contains an entry for each entry in clock-names.
+
+ - clock-names : Includes the following entries:
+ "sys" The system clock
+ "ref" The reference clock
+
+ - resets: Contains a phandle to the parallel out reset signal
+
+ - reset-names: Contains the reset signal name "rst"
+
+Optional Properties:
+
+ - interrupts : Contains the parallel out interrupt, if present
+
+Example:
+
+parallel_out: parallel-out@18100C00 {
+ compatible = "img,parallel-out";
+ reg = <0x18100C00 0x100>;
+ interrupts = <GIC_SHARED 19 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdc 16 0xffffffff 0>;
+ dma-names = "tx";
+ clocks = <&cr_periph SYS_CLK_PAUD_OUT>,
+ <&clk_core CLK_AUDIO_DAC>;
+ clock-names = "sys", "ref";
+ resets = <&pistachio_reset PISTACHIO_RESET_PRL_OUT>;
+ reset-names = "rst";
+ #sound-dai-cells = <0>;
+};
diff --git a/Documentation/devicetree/bindings/sound/img,pistachio-internal-dac.txt b/Documentation/devicetree/bindings/sound/img,pistachio-internal-dac.txt
new file mode 100644
index 000000000000..4cc18fc0477e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/img,pistachio-internal-dac.txt
@@ -0,0 +1,18 @@
+Pistachio internal DAC DT bindings
+
+Required properties:
+
+ - compatible: "img,pistachio-internal-dac"
+
+ - img,cr-top : Must contain a phandle to the top level control syscon
+ node which contains the internal dac control registers
+
+ - VDD-supply : Digital power supply regulator (+1.8V or +3.3V)
+
+Examples:
+
+internal_dac: internal-dac {
+ compatible = "img,pistachio-internal-dac";
+ img,cr-top = <&cr_top>;
+ VDD-supply = <&supply3v3>;
+};
diff --git a/Documentation/devicetree/bindings/sound/img,spdif-in.txt b/Documentation/devicetree/bindings/sound/img,spdif-in.txt
new file mode 100644
index 000000000000..aab9a81f7e13
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/img,spdif-in.txt
@@ -0,0 +1,41 @@
+Imagination Technologies SPDIF Input Controller
+
+Required Properties:
+
+ - compatible : Compatible list, must contain "img,spdif-in"
+
+ - #sound-dai-cells : Must be equal to 0
+
+ - reg : Offset and length of the register set for the device
+
+ - dmas: Contains an entry for each entry in dma-names.
+
+ - dma-names: Must include the following entry:
+ "rx"
+
+ - clocks : Contains an entry for each entry in clock-names
+
+ - clock-names : Includes the following entries:
+ "sys" The system clock
+
+Optional Properties:
+
+ - resets: Should contain a phandle to the spdif in reset signal, if any
+
+ - reset-names: Should contain the reset signal name "rst", if a
+ reset phandle is given
+
+ - interrupts : Contains the spdif in interrupt, if present
+
+Example:
+
+spdif_in: spdif-in@18100E00 {
+ compatible = "img,spdif-in";
+ reg = <0x18100E00 0x100>;
+ interrupts = <GIC_SHARED 20 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdc 15 0xffffffff 0>;
+ dma-names = "rx";
+ clocks = <&cr_periph SYS_CLK_SPDIF_IN>;
+ clock-names = "sys";
+ #sound-dai-cells = <0>;
+};
diff --git a/Documentation/devicetree/bindings/sound/img,spdif-out.txt b/Documentation/devicetree/bindings/sound/img,spdif-out.txt
new file mode 100644
index 000000000000..470a5191e101
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/img,spdif-out.txt
@@ -0,0 +1,44 @@
+Imagination Technologies SPDIF Output Controller
+
+Required Properties:
+
+ - compatible : Compatible list, must contain "img,spdif-out"
+
+ - #sound-dai-cells : Must be equal to 0
+
+ - reg : Offset and length of the register set for the device
+
+ - dmas: Contains an entry for each entry in dma-names.
+
+ - dma-names: Must include the following entry:
+ "tx"
+
+ - clocks : Contains an entry for each entry in clock-names.
+
+ - clock-names : Includes the following entries:
+ "sys" The system clock
+ "ref" The reference clock
+
+ - resets: Contains a phandle to the spdif out reset signal
+
+ - reset-names: Contains the reset signal name "rst"
+
+Optional Properties:
+
+ - interrupts : Contains the parallel out interrupt, if present
+
+Example:
+
+spdif_out: spdif-out@18100D00 {
+ compatible = "img,spdif-out";
+ reg = <0x18100D00 0x100>;
+ interrupts = <GIC_SHARED 21 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdc 14 0xffffffff 0>;
+ dma-names = "tx";
+ clocks = <&cr_periph SYS_CLK_SPDIF_OUT>,
+ <&clk_core CLK_SPDIF>;
+ clock-names = "sys", "ref";
+ resets = <&pistachio_reset PISTACHIO_RESET_SPDIF_OUT>;
+ reset-names = "rst";
+ #sound-dai-cells = <0>;
+};
diff --git a/Documentation/devicetree/bindings/sound/inno-rk3036.txt b/Documentation/devicetree/bindings/sound/inno-rk3036.txt
new file mode 100644
index 000000000000..758de8e27561
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/inno-rk3036.txt
@@ -0,0 +1,20 @@
+Inno audio codec for RK3036
+
+Inno audio codec is integrated inside RK3036 SoC.
+
+Required properties:
+- compatible : Should be "rockchip,rk3036-codec".
+- reg : The registers of codec.
+- clock-names : Should be "acodec_pclk".
+- clocks : The clock of codec.
+- rockchip,grf : The phandle of grf device node.
+
+Example:
+
+ acodec: acodec-ana@20030000 {
+ compatible = "rk3036-codec";
+ reg = <0x20030000 0x4000>;
+ rockchip,grf = <&grf>;
+ clock-names = "acodec_pclk";
+ clocks = <&cru ACLK_VCODEC>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/pcm1792a.txt b/Documentation/devicetree/bindings/sound/pcm179x.txt
index 970ba1ed576f..4ae70d3462d6 100644
--- a/Documentation/devicetree/bindings/sound/pcm1792a.txt
+++ b/Documentation/devicetree/bindings/sound/pcm179x.txt
@@ -1,4 +1,4 @@
-Texas Instruments pcm1792a DT bindings
+Texas Instruments pcm179x DT bindings
This driver supports the SPI bus.
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
index c57cbd65736c..8ee0fa91e4a0 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
@@ -7,8 +7,11 @@ Required properties:
"renesas,rcar_sound-gen3" if generation3
Examples with soctypes are:
- "renesas,rcar_sound-r8a7778" (R-Car M1A)
+ - "renesas,rcar_sound-r8a7779" (R-Car H1)
- "renesas,rcar_sound-r8a7790" (R-Car H2)
- "renesas,rcar_sound-r8a7791" (R-Car M2-W)
+ - "renesas,rcar_sound-r8a7793" (R-Car M2-N)
+ - "renesas,rcar_sound-r8a7794" (R-Car E2)
- "renesas,rcar_sound-r8a7795" (R-Car H3)
- reg : Should contain the register physical address.
required register is
@@ -34,6 +37,8 @@ Required properties:
see below for detail.
- #sound-dai-cells : it must be 0 if your system is using single DAI
it must be 1 if your system is using multi DAI
+
+Optional properties:
- #clock-cells : it must be 0 if your system has audio_clkout
it must be 1 if your system has audio_clkout0/1/2/3
- clock-frequency : for all audio_clkout0/1/2/3
@@ -244,3 +249,80 @@ rcar_sound: sound@ec500000 {
};
};
};
+
+Example: simple sound card
+
+ rsnd_ak4643: sound {
+ compatible = "simple-audio-card";
+
+ simple-audio-card,format = "left_j";
+ simple-audio-card,bitclock-master = <&sndcodec>;
+ simple-audio-card,frame-master = <&sndcodec>;
+
+ sndcpu: simple-audio-card,cpu {
+ sound-dai = <&rcar_sound>;
+ };
+
+ sndcodec: simple-audio-card,codec {
+ sound-dai = <&ak4643>;
+ clocks = <&audio_clock>;
+ };
+ };
+
+&rcar_sound {
+ pinctrl-0 = <&sound_pins &sound_clk_pins>;
+ pinctrl-names = "default";
+
+ /* Single DAI */
+ #sound-dai-cells = <0>;
+
+ status = "okay";
+
+ rcar_sound,dai {
+ dai0 {
+ playback = <&ssi0 &src2 &dvc0>;
+ capture = <&ssi1 &src3 &dvc1>;
+ };
+ };
+};
+
+&ssi1 {
+ shared-pin;
+};
+
+Example: simple sound card for TDM
+
+ rsnd_tdm: sound {
+ compatible = "simple-audio-card";
+
+ simple-audio-card,format = "left_j";
+ simple-audio-card,bitclock-master = <&sndcodec>;
+ simple-audio-card,frame-master = <&sndcodec>;
+
+ sndcpu: simple-audio-card,cpu {
+ sound-dai = <&rcar_sound>;
+ dai-tdm-slot-num = <6>;
+ };
+
+ sndcodec: simple-audio-card,codec {
+ sound-dai = <&xxx>;
+ };
+ };
+
+Example: simple sound card for Multi channel
+
+&rcar_sound {
+ pinctrl-0 = <&sound_pins &sound_clk_pins>;
+ pinctrl-names = "default";
+
+ /* Single DAI */
+ #sound-dai-cells = <0>;
+
+ status = "okay";
+
+ rcar_sound,dai {
+ dai0 {
+ playback = <&ssi0 &ssi1 &ssi2 &src0 &dvc0>;
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt
index 962748a8d919..2b2caa281ce3 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt
+++ b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt
@@ -4,8 +4,8 @@ Renesas Sampling Rate Convert Sound Card specifies audio DAI connections of SoC
Required properties:
-- compatible : "renesas,rsrc-card,<board>"
- Examples with soctypes are:
+- compatible : "renesas,rsrc-card{,<board>}"
+ Examples with boards are:
- "renesas,rsrc-card"
- "renesas,rsrc-card,lager"
- "renesas,rsrc-card,koelsch"
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
index 2267d249ca0e..b7f3a9325ebd 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -19,6 +19,7 @@ Required properties:
- clock-names: should contain followings:
- "i2s_hclk": clock for I2S BUS
- "i2s_clk" : clock for I2S controller
+- rockchip,playback-channels: max playback channels, if not set, 8 channels default.
- rockchip,capture-channels: max capture channels, if not set, 2 channels default.
Example for rk3288 I2S controller:
@@ -31,5 +32,6 @@ i2s@ff890000 {
dma-names = "tx", "rx";
clock-names = "i2s_hclk", "i2s_clk";
clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+ rockchip,playback-channels = <8>;
rockchip,capture-channels = <2>;
};
diff --git a/Documentation/devicetree/bindings/sound/rt5616.txt b/Documentation/devicetree/bindings/sound/rt5616.txt
new file mode 100644
index 000000000000..efc48c65198d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rt5616.txt
@@ -0,0 +1,26 @@
+RT5616 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+- compatible : "realtek,rt5616".
+
+- reg : The I2C address of the device.
+
+Pins on the device (for linking into audio routes) for RT5616:
+
+ * IN1P
+ * IN2P
+ * IN2N
+ * LOUTL
+ * LOUTR
+ * HPOL
+ * HPOR
+
+Example:
+
+codec: rt5616@1b {
+ compatible = "realtek,rt5616";
+ reg = <0x1b>;
+};
diff --git a/Documentation/devicetree/bindings/sound/rt5651.txt b/Documentation/devicetree/bindings/sound/rt5651.txt
new file mode 100644
index 000000000000..3875233095f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rt5651.txt
@@ -0,0 +1,41 @@
+RT5651 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+- compatible : "realtek,rt5651".
+
+- reg : The I2C address of the device.
+
+Optional properties:
+
+- realtek,in2-differential
+ Boolean. Indicate MIC2 input are differential, rather than single-ended.
+
+- realtek,dmic-en
+ Boolean. true if dmic is used.
+
+Pins on the device (for linking into audio routes) for RT5651:
+
+ * DMIC L1
+ * DMIC R1
+ * IN1P
+ * IN2P
+ * IN2N
+ * IN3P
+ * HPOL
+ * HPOR
+ * LOUTL
+ * LOUTR
+ * PDML
+ * PDMR
+
+Example:
+
+codec: rt5651@1a {
+ compatible = "realtek,rt5651";
+ reg = <0x1a>;
+ realtek,dmic-en = "true";
+ realtek,in2-diff = "false";
+};
diff --git a/Documentation/devicetree/bindings/sound/rt5659.txt b/Documentation/devicetree/bindings/sound/rt5659.txt
new file mode 100644
index 000000000000..5f79e7fde032
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rt5659.txt
@@ -0,0 +1,75 @@
+RT5659/RT5658 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+- compatible : One of "realtek,rt5659" or "realtek,rt5658".
+
+- reg : The I2C address of the device.
+
+- interrupts : The CODEC's interrupt output.
+
+Optional properties:
+
+- realtek,in1-differential
+- realtek,in3-differential
+- realtek,in4-differential
+ Boolean. Indicate MIC1/3/4 input are differential, rather than single-ended.
+
+- realtek,dmic1-data-pin
+ 0: dmic1 is not used
+ 1: using IN2N pin as dmic1 data pin
+ 2: using GPIO5 pin as dmic1 data pin
+ 3: using GPIO9 pin as dmic1 data pin
+ 4: using GPIO11 pin as dmic1 data pin
+
+- realtek,dmic2-data-pin
+ 0: dmic2 is not used
+ 1: using IN2P pin as dmic2 data pin
+ 2: using GPIO6 pin as dmic2 data pin
+ 3: using GPIO10 pin as dmic2 data pin
+ 4: using GPIO12 pin as dmic2 data pin
+
+- realtek,jd-src
+ 0: No JD is used
+ 1: using JD3 as JD source
+
+- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
+- realtek,reset-gpios : The GPIO that controls the CODEC's RESET pin.
+
+Pins on the device (for linking into audio routes) for RT5659/RT5658:
+
+ * DMIC L1
+ * DMIC R1
+ * DMIC L2
+ * DMIC R2
+ * IN1P
+ * IN1N
+ * IN2P
+ * IN2N
+ * IN3P
+ * IN3N
+ * IN4P
+ * IN4N
+ * HPOL
+ * HPOR
+ * SPOL
+ * SPOR
+ * LOUTL
+ * LOUTR
+ * MONOOUT
+ * PDML
+ * PDMR
+ * SPDIF
+
+Example:
+
+rt5659 {
+ compatible = "realtek,rt5659";
+ reg = <0x1b>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>;
+ realtek,ldo1-en-gpios =
+ <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
+};
diff --git a/Documentation/devicetree/bindings/sound/rt5677.txt b/Documentation/devicetree/bindings/sound/rt5677.txt
index f07078997f87..1b3c13d206ff 100644
--- a/Documentation/devicetree/bindings/sound/rt5677.txt
+++ b/Documentation/devicetree/bindings/sound/rt5677.txt
@@ -18,7 +18,7 @@ Required properties:
Optional properties:
- realtek,pow-ldo2-gpio : The GPIO that controls the CODEC's POW_LDO2 pin.
-- realtek,reset-gpio : The GPIO that controls the CODEC's RESET pin.
+- realtek,reset-gpio : The GPIO that controls the CODEC's RESET pin. Active low.
- realtek,in1-differential
- realtek,in2-differential
diff --git a/Documentation/devicetree/bindings/sound/sun4i-codec.txt b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
index c92966bd5488..0dce690f78f5 100644
--- a/Documentation/devicetree/bindings/sound/sun4i-codec.txt
+++ b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
@@ -14,6 +14,9 @@ Required properties:
- "apb": the parent APB clock for this controller
- "codec": the parent module clock
+Optional properties:
+- allwinner,pa-gpios: gpio to enable external amplifier
+
Example:
codec: codec@01c22c00 {
#sound-dai-cells = <0>;
diff --git a/Documentation/devicetree/bindings/sound/ti,pcm3168a.txt b/Documentation/devicetree/bindings/sound/ti,pcm3168a.txt
new file mode 100644
index 000000000000..5d9cb84c661d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ti,pcm3168a.txt
@@ -0,0 +1,48 @@
+Texas Instruments pcm3168a DT bindings
+
+This driver supports both SPI and I2C bus access for this codec
+
+Required properties:
+
+ - compatible: "ti,pcm3168a"
+
+ - clocks : Contains an entry for each entry in clock-names
+
+ - clock-names : Includes the following entries:
+ "scki" The system clock
+
+ - VDD1-supply : Digital power supply regulator 1 (+3.3V)
+
+ - VDD2-supply : Digital power supply regulator 2 (+3.3V)
+
+ - VCCAD1-supply : ADC power supply regulator 1 (+5V)
+
+ - VCCAD2-supply : ADC power supply regulator 2 (+5V)
+
+ - VCCDA1-supply : DAC power supply regulator 1 (+5V)
+
+ - VCCDA2-supply : DAC power supply regulator 2 (+5V)
+
+For required properties on SPI/I2C, consult SPI/I2C device tree documentation
+
+Examples:
+
+i2c0: i2c0@0 {
+
+ ...
+
+ pcm3168a: audio-codec@44 {
+ compatible = "ti,pcm3168a";
+ reg = <0x44>;
+ clocks = <&clk_core CLK_AUDIO>;
+ clock-names = "scki";
+ VDD1-supply = <&supply3v3>;
+ VDD2-supply = <&supply3v3>;
+ VCCAD1-supply = <&supply5v0>;
+ VCCAD2-supply = <&supply5v0>;
+ VCCDA1-supply = <&supply5v0>;
+ VCCDA2-supply = <&supply5v0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dac_clk_pin>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8974.txt b/Documentation/devicetree/bindings/sound/wlf,wm8974.txt
new file mode 100644
index 000000000000..01d3a7c83419
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wlf,wm8974.txt
@@ -0,0 +1,15 @@
+WM8974 audio CODEC
+
+This device supports both I2C and SPI (configured with pin strapping
+on the board).
+
+Required properties:
+ - compatible: "wlf,wm8974"
+ - reg: the I2C address or SPI chip select number of the device
+
+Examples:
+
+codec: wm8974@1a {
+ compatible = "wlf,wm8974";
+ reg = <0x1a>;
+};
diff --git a/Documentation/sound/alsa/img,spdif-in.txt b/Documentation/sound/alsa/img,spdif-in.txt
new file mode 100644
index 000000000000..8b7505785fa6
--- /dev/null
+++ b/Documentation/sound/alsa/img,spdif-in.txt
@@ -0,0 +1,49 @@
+The Imagination Technologies SPDIF Input controller contains the following
+controls:
+
+name='IEC958 Capture Mask',index=0
+
+This control returns a mask that shows which of the IEC958 status bits
+can be read using the 'IEC958 Capture Default' control.
+
+name='IEC958 Capture Default',index=0
+
+This control returns the status bits contained within the SPDIF stream that
+is being received. The 'IEC958 Capture Mask' shows which bits can be read
+from this control.
+
+name='SPDIF In Multi Frequency Acquire',index=0
+name='SPDIF In Multi Frequency Acquire',index=1
+name='SPDIF In Multi Frequency Acquire',index=2
+name='SPDIF In Multi Frequency Acquire',index=3
+
+This control is used to attempt acquisition of up to four different sample
+rates. The active rate can be obtained by reading the 'SPDIF In Lock Frequency'
+control.
+
+When the value of this control is set to {0,0,0,0}, the rate given to hw_params
+will determine the single rate the block will capture. Else, the rate given to
+hw_params will be ignored, and the block will attempt capture for each of the
+four sample rates set here.
+
+If less than four rates are required, the same rate can be specified more than
+once
+
+name='SPDIF In Lock Frequency',index=0
+
+This control returns the active capture rate, or 0 if a lock has not been
+acquired
+
+name='SPDIF In Lock TRK',index=0
+
+This control is used to modify the locking/jitter rejection characteristics
+of the block. Larger values increase the locking range, but reduce jitter
+rejection.
+
+name='SPDIF In Lock Acquire Threshold',index=0
+
+This control is used to change the threshold at which a lock is acquired.
+
+name='SPDIF In Lock Release Threshold',index=0
+
+This control is used to change the threshold at which a lock is released.
diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c
index ff780a8d8366..b57783371d52 100644
--- a/arch/arm/mach-s3c64xx/dev-audio.c
+++ b/arch/arm/mach-s3c64xx/dev-audio.c
@@ -54,12 +54,13 @@ static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev)
static struct resource s3c64xx_iis0_resource[] = {
[0] = DEFINE_RES_MEM(S3C64XX_PA_IIS0, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S0_OUT),
- [2] = DEFINE_RES_DMA(DMACH_I2S0_IN),
};
-static struct s3c_audio_pdata i2sv3_pdata = {
+static struct s3c_audio_pdata i2s0_pdata = {
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
+ .dma_filter = pl08x_filter_id,
+ .dma_playback = DMACH_I2S0_OUT,
+ .dma_capture = DMACH_I2S0_IN,
};
struct platform_device s3c64xx_device_iis0 = {
@@ -68,15 +69,20 @@ struct platform_device s3c64xx_device_iis0 = {
.num_resources = ARRAY_SIZE(s3c64xx_iis0_resource),
.resource = s3c64xx_iis0_resource,
.dev = {
- .platform_data = &i2sv3_pdata,
+ .platform_data = &i2s0_pdata,
},
};
EXPORT_SYMBOL(s3c64xx_device_iis0);
static struct resource s3c64xx_iis1_resource[] = {
[0] = DEFINE_RES_MEM(S3C64XX_PA_IIS1, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S1_OUT),
- [2] = DEFINE_RES_DMA(DMACH_I2S1_IN),
+};
+
+static struct s3c_audio_pdata i2s1_pdata = {
+ .cfg_gpio = s3c64xx_i2s_cfg_gpio,
+ .dma_filter = pl08x_filter_id,
+ .dma_playback = DMACH_I2S1_OUT,
+ .dma_capture = DMACH_I2S1_IN,
};
struct platform_device s3c64xx_device_iis1 = {
@@ -85,19 +91,20 @@ struct platform_device s3c64xx_device_iis1 = {
.num_resources = ARRAY_SIZE(s3c64xx_iis1_resource),
.resource = s3c64xx_iis1_resource,
.dev = {
- .platform_data = &i2sv3_pdata,
+ .platform_data = &i2s1_pdata,
},
};
EXPORT_SYMBOL(s3c64xx_device_iis1);
static struct resource s3c64xx_iisv4_resource[] = {
[0] = DEFINE_RES_MEM(S3C64XX_PA_IISV4, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_TX),
- [2] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_RX),
};
static struct s3c_audio_pdata i2sv4_pdata = {
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
+ .dma_filter = pl08x_filter_id,
+ .dma_playback = DMACH_HSI_I2SV40_TX,
+ .dma_capture = DMACH_HSI_I2SV40_RX,
.type = {
.i2s = {
.quirks = QUIRK_PRI_6CHAN,
@@ -142,12 +149,13 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
static struct resource s3c64xx_pcm0_resource[] = {
[0] = DEFINE_RES_MEM(S3C64XX_PA_PCM0, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
- [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
};
static struct s3c_audio_pdata s3c_pcm0_pdata = {
.cfg_gpio = s3c64xx_pcm_cfg_gpio,
+ .dma_filter = pl08x_filter_id,
+ .dma_capture = DMACH_PCM0_RX,
+ .dma_playback = DMACH_PCM0_TX,
};
struct platform_device s3c64xx_device_pcm0 = {
@@ -163,12 +171,13 @@ EXPORT_SYMBOL(s3c64xx_device_pcm0);
static struct resource s3c64xx_pcm1_resource[] = {
[0] = DEFINE_RES_MEM(S3C64XX_PA_PCM1, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
- [2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
};
static struct s3c_audio_pdata s3c_pcm1_pdata = {
.cfg_gpio = s3c64xx_pcm_cfg_gpio,
+ .dma_filter = pl08x_filter_id,
+ .dma_playback = DMACH_PCM1_TX,
+ .dma_capture = DMACH_PCM1_RX,
};
struct platform_device s3c64xx_device_pcm1 = {
@@ -196,13 +205,15 @@ static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev)
static struct resource s3c64xx_ac97_resource[] = {
[0] = DEFINE_RES_MEM(S3C64XX_PA_AC97, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
- [2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
- [3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
- [4] = DEFINE_RES_IRQ(IRQ_AC97),
+ [1] = DEFINE_RES_IRQ(IRQ_AC97),
};
-static struct s3c_audio_pdata s3c_ac97_pdata;
+static struct s3c_audio_pdata s3c_ac97_pdata = {
+ .dma_playback = DMACH_AC97_PCMOUT,
+ .dma_filter = pl08x_filter_id,
+ .dma_capture = DMACH_AC97_PCMIN,
+ .dma_capture_mic = DMACH_AC97_MICIN,
+};
static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32);
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index 096e14073bd9..9c739eafe95c 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -14,38 +14,38 @@
#define S3C64XX_DMA_CHAN(name) ((unsigned long)(name))
/* DMA0/SDMA0 */
-#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx")
-#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx")
-#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx")
-#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx")
-#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx")
-#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx")
-#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx")
-#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx")
-#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx")
-#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx")
-#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx")
-#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx")
+#define DMACH_UART0 "uart0_tx"
+#define DMACH_UART0_SRC2 "uart0_rx"
+#define DMACH_UART1 "uart1_tx"
+#define DMACH_UART1_SRC2 "uart1_rx"
+#define DMACH_UART2 "uart2_tx"
+#define DMACH_UART2_SRC2 "uart2_rx"
+#define DMACH_UART3 "uart3_tx"
+#define DMACH_UART3_SRC2 "uart3_rx"
+#define DMACH_PCM0_TX "pcm0_tx"
+#define DMACH_PCM0_RX "pcm0_rx"
+#define DMACH_I2S0_OUT "i2s0_tx"
+#define DMACH_I2S0_IN "i2s0_rx"
#define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx")
#define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx")
-#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx")
-#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx")
+#define DMACH_HSI_I2SV40_TX "i2s2_tx"
+#define DMACH_HSI_I2SV40_RX "i2s2_rx"
/* DMA1/SDMA1 */
-#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx")
-#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx")
-#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx")
-#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx")
+#define DMACH_PCM1_TX "pcm1_tx"
+#define DMACH_PCM1_RX "pcm1_rx"
+#define DMACH_I2S1_OUT "i2s1_tx"
+#define DMACH_I2S1_IN "i2s1_rx"
#define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx")
#define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx")
-#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out")
-#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in")
-#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic")
-#define DMACH_PWM S3C64XX_DMA_CHAN("pwm")
-#define DMACH_IRDA S3C64XX_DMA_CHAN("irda")
-#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external")
-#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx")
-#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx")
+#define DMACH_AC97_PCMOUT "ac97_out"
+#define DMACH_AC97_PCMIN "ac97_in"
+#define DMACH_AC97_MICIN "ac97_mic"
+#define DMACH_PWM "pwm"
+#define DMACH_IRDA "irda"
+#define DMACH_EXTERNAL "external"
+#define DMACH_SECURITY_RX "sec_rx"
+#define DMACH_SECURITY_TX "sec_tx"
enum dma_ch {
DMACH_MAX = 32
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 42f6f9cd844c..f39938fa9ef6 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -65,6 +65,7 @@
#include <linux/platform_data/usb-ohci-s3c2410.h>
#include <plat/usb-phy.h>
#include <plat/regs-spi.h>
+#include <linux/platform_data/asoc-s3c.h>
#include <linux/platform_data/spi-s3c64xx.h>
static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
@@ -74,9 +75,15 @@ static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
static struct resource s3c_ac97_resource[] = {
[0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97),
[1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97),
- [2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"),
- [3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"),
- [4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"),
+};
+
+static struct s3c_audio_pdata s3c_ac97_pdata = {
+#ifdef CONFIG_S3C24XX_DMAC
+ .dma_filter = s3c24xx_dma_filter,
+#endif
+ .dma_playback = (void *)DMACH_PCM_OUT,
+ .dma_capture = (void *)DMACH_PCM_IN,
+ .dma_capture_mic = (void *)DMACH_MIC_IN,
};
struct platform_device s3c_device_ac97 = {
@@ -87,6 +94,7 @@ struct platform_device s3c_device_ac97 = {
.dev = {
.dma_mask = &samsung_device_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &s3c_ac97_pdata,
}
};
#endif /* CONFIG_CPU_S3C2440 */
@@ -566,6 +574,14 @@ static struct resource s3c_iis_resource[] = {
[0] = DEFINE_RES_MEM(S3C24XX_PA_IIS, S3C24XX_SZ_IIS),
};
+static struct s3c_audio_pdata s3c_iis_platdata = {
+#ifdef CONFIG_S3C24XX_DMAC
+ .dma_filter = s3c24xx_dma_filter,
+#endif
+ .dma_playback = (void *)DMACH_I2S_OUT,
+ .dma_capture = (void *)DMACH_I2S_IN,
+};
+
struct platform_device s3c_device_iis = {
.name = "s3c24xx-iis",
.id = -1,
@@ -574,6 +590,7 @@ struct platform_device s3c_device_iis = {
.dev = {
.dma_mask = &samsung_device_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &s3c_iis_platdata,
}
};
#endif /* CONFIG_PLAT_S3C24XX */
diff --git a/arch/x86/include/asm/platform_sst_audio.h b/arch/x86/include/asm/platform_sst_audio.h
index 7249e6d0902d..5973a2f3db3d 100644
--- a/arch/x86/include/asm/platform_sst_audio.h
+++ b/arch/x86/include/asm/platform_sst_audio.h
@@ -55,6 +55,7 @@ enum sst_audio_device_id_mrfld {
PIPE_MEDIA0_IN = 0x8F,
PIPE_MEDIA1_IN = 0x90,
PIPE_MEDIA2_IN = 0x91,
+ PIPE_MEDIA3_IN = 0x9C,
PIPE_RSVD = 0xFF,
};
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index db9a675e751b..bca14c899137 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -547,6 +547,7 @@ static const struct pci_device_id intel_stolen_ids[] __initconst = {
INTEL_CHV_IDS(&chv_stolen_funcs),
INTEL_SKL_IDS(&gen9_stolen_funcs),
INTEL_BXT_IDS(&gen9_stolen_funcs),
+ INTEL_KBL_IDS(&gen9_stolen_funcs),
};
static void __init intel_graphics_stolen(int num, int slot, int func)
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 3a8ce67910c2..79b1390f2016 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -444,7 +444,7 @@ config STM32_DMA
here.
config S3C24XX_DMAC
- tristate "Samsung S3C24XX DMA support"
+ bool "Samsung S3C24XX DMA support"
depends on ARCH_S3C24XX
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 5580d3420c3a..acd066d0a805 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -518,7 +518,7 @@ static const struct drm_framebuffer_funcs amdgpu_fb_funcs = {
int
amdgpu_framebuffer_init(struct drm_device *dev,
struct amdgpu_framebuffer *rfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
@@ -535,7 +535,7 @@ amdgpu_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
amdgpu_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct amdgpu_framebuffer *amdgpu_fb;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 093a8c618931..6fcbbcc2e99e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -45,7 +45,6 @@
struct amdgpu_fbdev {
struct drm_fb_helper helper;
struct amdgpu_framebuffer rfb;
- struct list_head fbdev_list;
struct amdgpu_device *adev;
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 064ebb347074..a53d756672fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -556,7 +556,7 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
int amdgpu_framebuffer_init(struct drm_device *dev,
struct amdgpu_framebuffer *rfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
int amdgpufb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c
index 1c90969def3e..5fa4bf20b232 100644
--- a/drivers/gpu/drm/armada/armada_fb.c
+++ b/drivers/gpu/drm/armada/armada_fb.c
@@ -35,7 +35,7 @@ static const struct drm_framebuffer_funcs armada_fb_funcs = {
};
struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode, struct armada_gem_object *obj)
+ const struct drm_mode_fb_cmd2 *mode, struct armada_gem_object *obj)
{
struct armada_framebuffer *dfb;
uint8_t format, config;
@@ -101,7 +101,7 @@ struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
}
static struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
- struct drm_file *dfile, struct drm_mode_fb_cmd2 *mode)
+ struct drm_file *dfile, const struct drm_mode_fb_cmd2 *mode)
{
struct armada_gem_object *obj;
struct armada_framebuffer *dfb;
diff --git a/drivers/gpu/drm/armada/armada_fb.h b/drivers/gpu/drm/armada/armada_fb.h
index ce3f12ebfc53..48073c4f54d8 100644
--- a/drivers/gpu/drm/armada/armada_fb.h
+++ b/drivers/gpu/drm/armada/armada_fb.h
@@ -19,6 +19,6 @@ struct armada_framebuffer {
#define drm_fb_obj(fb) drm_fb_to_armada_fb(fb)->obj
struct armada_framebuffer *armada_framebuffer_create(struct drm_device *,
- struct drm_mode_fb_cmd2 *, struct armada_gem_object *);
+ const struct drm_mode_fb_cmd2 *, struct armada_gem_object *);
#endif
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 05f6522c0457..eb5715994ac2 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -256,7 +256,6 @@ struct ast_framebuffer {
struct ast_fbdev {
struct drm_fb_helper helper;
struct ast_framebuffer afb;
- struct list_head fbdev_list;
void *sysram;
int size;
struct ttm_bo_kmap_obj mapping;
@@ -309,7 +308,7 @@ extern void ast_mode_fini(struct drm_device *dev);
int ast_framebuffer_init(struct drm_device *dev,
struct ast_framebuffer *ast_fb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
int ast_fbdev_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
index a37e7ea4a00c..5320f8c57884 100644
--- a/drivers/gpu/drm/ast/ast_fb.c
+++ b/drivers/gpu/drm/ast/ast_fb.c
@@ -163,7 +163,7 @@ static struct fb_ops astfb_ops = {
};
static int astfb_create_object(struct ast_fbdev *afbdev,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
struct drm_device *dev = afbdev->helper.dev;
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 541a610667ad..9759009d1da3 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -309,7 +309,7 @@ static const struct drm_framebuffer_funcs ast_fb_funcs = {
int ast_framebuffer_init(struct drm_device *dev,
struct ast_framebuffer *ast_fb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
@@ -327,7 +327,7 @@ int ast_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
ast_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct ast_framebuffer *ast_fb;
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 244df0a440b7..816895447155 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -402,7 +402,7 @@ static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data)
}
static struct drm_framebuffer *atmel_hlcdc_fb_create(struct drm_device *dev,
- struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
+ struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd)
{
return drm_fb_cma_create(dev, file_priv, mode_cmd);
}
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
index 71f2687fc3cc..19b5adaebe24 100644
--- a/drivers/gpu/drm/bochs/bochs.h
+++ b/drivers/gpu/drm/bochs/bochs.h
@@ -149,7 +149,7 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
int bochs_framebuffer_init(struct drm_device *dev,
struct bochs_framebuffer *gfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr);
int bochs_bo_unpin(struct bochs_bo *bo);
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index 09a0637aab3e..7520bf81fc25 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -34,7 +34,7 @@ static struct fb_ops bochsfb_ops = {
};
static int bochsfb_create_object(struct bochs_device *bochs,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
struct drm_device *dev = bochs->dev;
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
index f69e6bf9bb0e..d812ad014da5 100644
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ b/drivers/gpu/drm/bochs/bochs_mm.c
@@ -484,7 +484,7 @@ static const struct drm_framebuffer_funcs bochs_fb_funcs = {
int bochs_framebuffer_init(struct drm_device *dev,
struct bochs_framebuffer *gfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
@@ -502,7 +502,7 @@ int bochs_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
bochs_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct bochs_framebuffer *bochs_fb;
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
index 705061537a27..b774d637a00f 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -153,7 +153,6 @@ struct cirrus_device {
struct cirrus_fbdev {
struct drm_fb_helper helper;
struct cirrus_framebuffer gfb;
- struct list_head fbdev_list;
void *sysram;
int size;
int x1, y1, x2, y2; /* dirty rect */
@@ -207,7 +206,7 @@ int cirrus_dumb_create(struct drm_file *file,
int cirrus_framebuffer_init(struct drm_device *dev,
struct cirrus_framebuffer *gfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
index 589103bcc06c..3b5be7272357 100644
--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
@@ -135,7 +135,7 @@ static struct fb_ops cirrusfb_ops = {
};
static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
struct drm_device *dev = afbdev->helper.dev;
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
index 055fd86ba717..0907715e90fd 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -29,7 +29,7 @@ static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
int cirrus_framebuffer_init(struct drm_device *dev,
struct cirrus_framebuffer *gfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
@@ -47,7 +47,7 @@ int cirrus_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
cirrus_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct cirrus_device *cdev = dev->dev_private;
struct drm_gem_object *obj;
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index aeee083c7f95..ef5f7663a718 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -316,8 +316,7 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
return 0;
- if (state->mode_blob)
- drm_property_unreference_blob(state->mode_blob);
+ drm_property_unreference_blob(state->mode_blob);
state->mode_blob = NULL;
if (mode) {
@@ -363,8 +362,7 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
if (blob == state->mode_blob)
return 0;
- if (state->mode_blob)
- drm_property_unreference_blob(state->mode_blob);
+ drm_property_unreference_blob(state->mode_blob);
state->mode_blob = NULL;
if (blob) {
@@ -419,8 +417,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
struct drm_property_blob *mode =
drm_property_lookup_blob(dev, val);
ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
- if (mode)
- drm_property_unreference_blob(mode);
+ drm_property_unreference_blob(mode);
return ret;
}
else if (crtc->funcs->atomic_set_property)
@@ -1191,12 +1188,7 @@ void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
retry:
drm_modeset_backoff(state->acquire_ctx);
- ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
- state->acquire_ctx);
- if (ret)
- goto retry;
- ret = drm_modeset_lock_all_crtcs(state->dev,
- state->acquire_ctx);
+ ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx);
if (ret)
goto retry;
}
@@ -1433,7 +1425,7 @@ static int atomic_set_prop(struct drm_atomic_state *state,
}
/**
- * drm_atomic_update_old_fb -- Unset old_fb pointers and set plane->fb pointers.
+ * drm_atomic_clean_old_fb -- Unset old_fb pointers and set plane->fb pointers.
*
* @dev: drm device to check.
* @plane_mask: plane mask for planes that were updated.
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index e5aec45bf985..74a5fc4deef6 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -80,6 +80,27 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
}
}
+static bool
+check_pending_encoder_assignment(struct drm_atomic_state *state,
+ struct drm_encoder *new_encoder,
+ struct drm_connector *new_connector)
+{
+ struct drm_connector *connector;
+ struct drm_connector_state *conn_state;
+ int i;
+
+ for_each_connector_in_state(state, connector, conn_state, i) {
+ if (conn_state->best_encoder != new_encoder)
+ continue;
+
+ /* encoder already assigned and we're trying to re-steal it! */
+ if (connector->state->best_encoder != conn_state->best_encoder)
+ return false;
+ }
+
+ return true;
+}
+
static struct drm_crtc *
get_current_crtc_for_encoder(struct drm_device *dev,
struct drm_encoder *encoder)
@@ -229,6 +250,13 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
return 0;
}
+ if (!check_pending_encoder_assignment(state, new_encoder, connector)) {
+ DRM_DEBUG_ATOMIC("Encoder for [CONNECTOR:%d:%s] already assigned\n",
+ connector->base.id,
+ connector->name);
+ return -EINVAL;
+ }
+
encoder_crtc = get_current_crtc_for_encoder(state->dev,
new_encoder);
@@ -1342,6 +1370,49 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)
EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc);
/**
+ * drm_atomic_helper_disable_planes_on_crtc - helper to disable CRTC's planes
+ * @crtc: CRTC
+ * @atomic: if set, synchronize with CRTC's atomic_begin/flush hooks
+ *
+ * Disables all planes associated with the given CRTC. This can be
+ * used for instance in the CRTC helper disable callback to disable
+ * all planes before shutting down the display pipeline.
+ *
+ * If the atomic-parameter is set the function calls the CRTC's
+ * atomic_begin hook before and atomic_flush hook after disabling the
+ * planes.
+ *
+ * It is a bug to call this function without having implemented the
+ * ->atomic_disable() plane hook.
+ */
+void drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc *crtc,
+ bool atomic)
+{
+ const struct drm_crtc_helper_funcs *crtc_funcs =
+ crtc->helper_private;
+ struct drm_plane *plane;
+
+ if (atomic && crtc_funcs && crtc_funcs->atomic_begin)
+ crtc_funcs->atomic_begin(crtc, NULL);
+
+ drm_for_each_plane(plane, crtc->dev) {
+ const struct drm_plane_helper_funcs *plane_funcs =
+ plane->helper_private;
+
+ if (plane->state->crtc != crtc || !plane_funcs)
+ continue;
+
+ WARN_ON(!plane_funcs->atomic_disable);
+ if (plane_funcs->atomic_disable)
+ plane_funcs->atomic_disable(plane, NULL);
+ }
+
+ if (atomic && crtc_funcs && crtc_funcs->atomic_flush)
+ crtc_funcs->atomic_flush(crtc, NULL);
+}
+EXPORT_SYMBOL(drm_atomic_helper_disable_planes_on_crtc);
+
+/**
* drm_atomic_helper_cleanup_planes - cleanup plane resources after commit
* @dev: DRM device
* @old_state: atomic state object with old state structures
@@ -1485,12 +1556,12 @@ retry:
drm_atomic_set_fb_for_plane(plane_state, fb);
plane_state->crtc_x = crtc_x;
plane_state->crtc_y = crtc_y;
- plane_state->crtc_h = crtc_h;
plane_state->crtc_w = crtc_w;
+ plane_state->crtc_h = crtc_h;
plane_state->src_x = src_x;
plane_state->src_y = src_y;
- plane_state->src_h = src_h;
plane_state->src_w = src_w;
+ plane_state->src_h = src_h;
if (plane == crtc->cursor)
state->legacy_cursor_update = true;
@@ -1609,12 +1680,12 @@ int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
drm_atomic_set_fb_for_plane(plane_state, NULL);
plane_state->crtc_x = 0;
plane_state->crtc_y = 0;
- plane_state->crtc_h = 0;
plane_state->crtc_w = 0;
+ plane_state->crtc_h = 0;
plane_state->src_x = 0;
plane_state->src_y = 0;
- plane_state->src_h = 0;
plane_state->src_w = 0;
+ plane_state->src_h = 0;
return 0;
}
@@ -1797,16 +1868,16 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
drm_atomic_set_fb_for_plane(primary_state, set->fb);
primary_state->crtc_x = 0;
primary_state->crtc_y = 0;
- primary_state->crtc_h = vdisplay;
primary_state->crtc_w = hdisplay;
+ primary_state->crtc_h = vdisplay;
primary_state->src_x = set->x << 16;
primary_state->src_y = set->y << 16;
if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) {
- primary_state->src_h = hdisplay << 16;
primary_state->src_w = vdisplay << 16;
+ primary_state->src_h = hdisplay << 16;
} else {
- primary_state->src_h = vdisplay << 16;
primary_state->src_w = hdisplay << 16;
+ primary_state->src_h = vdisplay << 16;
}
commit:
@@ -1818,6 +1889,161 @@ commit:
}
/**
+ * drm_atomic_helper_disable_all - disable all currently active outputs
+ * @dev: DRM device
+ * @ctx: lock acquisition context
+ *
+ * Loops through all connectors, finding those that aren't turned off and then
+ * turns them off by setting their DPMS mode to OFF and deactivating the CRTC
+ * that they are connected to.
+ *
+ * This is used for example in suspend/resume to disable all currently active
+ * functions when suspending.
+ *
+ * Note that if callers haven't already acquired all modeset locks this might
+ * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ *
+ * See also:
+ * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
+ */
+int drm_atomic_helper_disable_all(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct drm_atomic_state *state;
+ struct drm_connector *conn;
+ int err;
+
+ state = drm_atomic_state_alloc(dev);
+ if (!state)
+ return -ENOMEM;
+
+ state->acquire_ctx = ctx;
+
+ drm_for_each_connector(conn, dev) {
+ struct drm_crtc *crtc = conn->state->crtc;
+ struct drm_crtc_state *crtc_state;
+
+ if (!crtc || conn->dpms != DRM_MODE_DPMS_ON)
+ continue;
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state)) {
+ err = PTR_ERR(crtc_state);
+ goto free;
+ }
+
+ crtc_state->active = false;
+ }
+
+ err = drm_atomic_commit(state);
+
+free:
+ if (err < 0)
+ drm_atomic_state_free(state);
+
+ return err;
+}
+EXPORT_SYMBOL(drm_atomic_helper_disable_all);
+
+/**
+ * drm_atomic_helper_suspend - subsystem-level suspend helper
+ * @dev: DRM device
+ *
+ * Duplicates the current atomic state, disables all active outputs and then
+ * returns a pointer to the original atomic state to the caller. Drivers can
+ * pass this pointer to the drm_atomic_helper_resume() helper upon resume to
+ * restore the output configuration that was active at the time the system
+ * entered suspend.
+ *
+ * Note that it is potentially unsafe to use this. The atomic state object
+ * returned by this function is assumed to be persistent. Drivers must ensure
+ * that this holds true. Before calling this function, drivers must make sure
+ * to suspend fbdev emulation so that nothing can be using the device.
+ *
+ * Returns:
+ * A pointer to a copy of the state before suspend on success or an ERR_PTR()-
+ * encoded error code on failure. Drivers should store the returned atomic
+ * state object and pass it to the drm_atomic_helper_resume() helper upon
+ * resume.
+ *
+ * See also:
+ * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(),
+ * drm_atomic_helper_resume()
+ */
+struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
+{
+ struct drm_modeset_acquire_ctx ctx;
+ struct drm_atomic_state *state;
+ int err;
+
+ drm_modeset_acquire_init(&ctx, 0);
+
+retry:
+ err = drm_modeset_lock_all_ctx(dev, &ctx);
+ if (err < 0) {
+ state = ERR_PTR(err);
+ goto unlock;
+ }
+
+ state = drm_atomic_helper_duplicate_state(dev, &ctx);
+ if (IS_ERR(state))
+ goto unlock;
+
+ err = drm_atomic_helper_disable_all(dev, &ctx);
+ if (err < 0) {
+ drm_atomic_state_free(state);
+ state = ERR_PTR(err);
+ goto unlock;
+ }
+
+unlock:
+ if (PTR_ERR(state) == -EDEADLK) {
+ drm_modeset_backoff(&ctx);
+ goto retry;
+ }
+
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+ return state;
+}
+EXPORT_SYMBOL(drm_atomic_helper_suspend);
+
+/**
+ * drm_atomic_helper_resume - subsystem-level resume helper
+ * @dev: DRM device
+ * @state: atomic state to resume to
+ *
+ * Calls drm_mode_config_reset() to synchronize hardware and software states,
+ * grabs all modeset locks and commits the atomic state object. This can be
+ * used in conjunction with the drm_atomic_helper_suspend() helper to
+ * implement suspend/resume for drivers that support atomic mode-setting.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ *
+ * See also:
+ * drm_atomic_helper_suspend()
+ */
+int drm_atomic_helper_resume(struct drm_device *dev,
+ struct drm_atomic_state *state)
+{
+ struct drm_mode_config *config = &dev->mode_config;
+ int err;
+
+ drm_mode_config_reset(dev);
+ drm_modeset_lock_all(dev);
+ state->acquire_ctx = config->acquire_ctx;
+ err = drm_atomic_commit(state);
+ drm_modeset_unlock_all(dev);
+
+ return err;
+}
+EXPORT_SYMBOL(drm_atomic_helper_resume);
+
+/**
* drm_atomic_helper_crtc_set_property - helper for crtc properties
* @crtc: DRM crtc
* @property: DRM property
@@ -2184,7 +2410,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
*/
void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
{
- if (crtc->state && crtc->state->mode_blob)
+ if (crtc->state)
drm_property_unreference_blob(crtc->state->mode_blob);
kfree(crtc->state);
crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
@@ -2252,8 +2478,7 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
- if (state->mode_blob)
- drm_property_unreference_blob(state->mode_blob);
+ drm_property_unreference_blob(state->mode_blob);
}
EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
@@ -2430,7 +2655,9 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
* @ctx: lock acquisition context
*
* Makes a copy of the current atomic state by looping over all objects and
- * duplicating their respective states.
+ * duplicating their respective states. This is used for example by suspend/
+ * resume support code to save the state prior to suspend such that it can
+ * be restored upon resume.
*
* Note that this treats atomic state as persistent between save and restore.
* Drivers must make sure that this is possible and won't result in confusion
@@ -2442,6 +2669,9 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
* Returns:
* A pointer to the copy of the atomic state object on success or an
* ERR_PTR()-encoded error code on failure.
+ *
+ * See also:
+ * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
*/
struct drm_atomic_state *
drm_atomic_helper_duplicate_state(struct drm_device *dev,
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 24c5434abd1c..32dd134700bd 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -45,7 +45,7 @@
static struct drm_framebuffer *
internal_framebuffer_create(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *r,
+ const struct drm_mode_fb_cmd2 *r,
struct drm_file *file_priv);
/* Avoid boilerplate. I'm tired of typing. */
@@ -3235,7 +3235,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
static struct drm_framebuffer *
internal_framebuffer_create(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *r,
+ const struct drm_mode_fb_cmd2 *r,
struct drm_file *file_priv)
{
struct drm_mode_config *config = &dev->mode_config;
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index ef534758a02c..10d0989db273 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -818,7 +818,7 @@ EXPORT_SYMBOL(drm_helper_connector_dpms);
* metadata fields.
*/
void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
int i;
@@ -855,6 +855,12 @@ EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
* due to slight differences in allocating shared resources when the
* configuration is restored in a different order than when userspace set it up)
* need to use their own restore logic.
+ *
+ * This function is deprecated. New drivers should implement atomic mode-
+ * setting and use the atomic suspend/resume helpers.
+ *
+ * See also:
+ * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
*/
void drm_helper_resume_force_mode(struct drm_device *dev)
{
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index d5d2c03fd136..c214f1246cb4 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2545,6 +2545,33 @@ cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
return clock;
}
+static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_match,
+ unsigned int clock_tolerance)
+{
+ u8 mode;
+
+ if (!to_match->clock)
+ return 0;
+
+ for (mode = 0; mode < ARRAY_SIZE(edid_cea_modes); mode++) {
+ const struct drm_display_mode *cea_mode = &edid_cea_modes[mode];
+ unsigned int clock1, clock2;
+
+ /* Check both 60Hz and 59.94Hz */
+ clock1 = cea_mode->clock;
+ clock2 = cea_mode_alternate_clock(cea_mode);
+
+ if (abs(to_match->clock - clock1) > clock_tolerance &&
+ abs(to_match->clock - clock2) > clock_tolerance)
+ continue;
+
+ if (drm_mode_equal_no_clocks(to_match, cea_mode))
+ return mode + 1;
+ }
+
+ return 0;
+}
+
/**
* drm_match_cea_mode - look for a CEA mode matching given mode
* @to_match: display mode
@@ -2609,6 +2636,33 @@ hdmi_mode_alternate_clock(const struct drm_display_mode *hdmi_mode)
return cea_mode_alternate_clock(hdmi_mode);
}
+static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode *to_match,
+ unsigned int clock_tolerance)
+{
+ u8 mode;
+
+ if (!to_match->clock)
+ return 0;
+
+ for (mode = 0; mode < ARRAY_SIZE(edid_4k_modes); mode++) {
+ const struct drm_display_mode *hdmi_mode = &edid_4k_modes[mode];
+ unsigned int clock1, clock2;
+
+ /* Make sure to also match alternate clocks */
+ clock1 = hdmi_mode->clock;
+ clock2 = hdmi_mode_alternate_clock(hdmi_mode);
+
+ if (abs(to_match->clock - clock1) > clock_tolerance &&
+ abs(to_match->clock - clock2) > clock_tolerance)
+ continue;
+
+ if (drm_mode_equal_no_clocks(to_match, hdmi_mode))
+ return mode + 1;
+ }
+
+ return 0;
+}
+
/*
* drm_match_hdmi_mode - look for a HDMI mode matching given mode
* @to_match: display mode
@@ -3119,14 +3173,18 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
u8 mode_idx;
const char *type;
- mode_idx = drm_match_cea_mode(mode) - 1;
+ /*
+ * allow 5kHz clock difference either way to account for
+ * the 10kHz clock resolution limit of detailed timings.
+ */
+ mode_idx = drm_match_cea_mode_clock_tolerance(mode, 5) - 1;
if (mode_idx < ARRAY_SIZE(edid_cea_modes)) {
type = "CEA";
cea_mode = &edid_cea_modes[mode_idx];
clock1 = cea_mode->clock;
clock2 = cea_mode_alternate_clock(cea_mode);
} else {
- mode_idx = drm_match_hdmi_mode(mode) - 1;
+ mode_idx = drm_match_hdmi_mode_clock_tolerance(mode, 5) - 1;
if (mode_idx < ARRAY_SIZE(edid_4k_modes)) {
type = "HDMI";
cea_mode = &edid_4k_modes[mode_idx];
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index c19a62561183..b7d5b848d2f8 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -74,7 +74,7 @@ static struct drm_framebuffer_funcs drm_fb_cma_funcs = {
};
static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_cma_object **obj,
+ const const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_cma_object **obj,
unsigned int num_planes)
{
struct drm_fb_cma *fb_cma;
@@ -107,7 +107,7 @@ static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev,
* checked before calling this function.
*/
struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
- struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
+ struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_fb_cma *fb_cma;
struct drm_gem_cma_object *objs[4];
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 6b5625e66119..1ea8790e5090 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -226,6 +226,8 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
init_waitqueue_head(&priv->event_wait);
priv->event_space = 4096; /* set aside 4k for event buffer */
+ mutex_init(&priv->event_read_lock);
+
if (drm_core_check_feature(dev, DRIVER_GEM))
drm_gem_open(dev, priv);
@@ -511,14 +513,28 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
{
struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev;
- ssize_t ret = 0;
+ ssize_t ret;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
- spin_lock_irq(&dev->event_lock);
+ ret = mutex_lock_interruptible(&file_priv->event_read_lock);
+ if (ret)
+ return ret;
+
for (;;) {
- if (list_empty(&file_priv->event_list)) {
+ struct drm_pending_event *e = NULL;
+
+ spin_lock_irq(&dev->event_lock);
+ if (!list_empty(&file_priv->event_list)) {
+ e = list_first_entry(&file_priv->event_list,
+ struct drm_pending_event, link);
+ file_priv->event_space += e->event->length;
+ list_del(&e->link);
+ }
+ spin_unlock_irq(&dev->event_lock);
+
+ if (e == NULL) {
if (ret)
break;
@@ -527,36 +543,36 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
break;
}
- spin_unlock_irq(&dev->event_lock);
+ mutex_unlock(&file_priv->event_read_lock);
ret = wait_event_interruptible(file_priv->event_wait,
!list_empty(&file_priv->event_list));
- spin_lock_irq(&dev->event_lock);
- if (ret < 0)
- break;
-
- ret = 0;
+ if (ret >= 0)
+ ret = mutex_lock_interruptible(&file_priv->event_read_lock);
+ if (ret)
+ return ret;
} else {
- struct drm_pending_event *e;
-
- e = list_first_entry(&file_priv->event_list,
- struct drm_pending_event, link);
- if (e->event->length + ret > count)
+ unsigned length = e->event->length;
+
+ if (length > count - ret) {
+put_back_event:
+ spin_lock_irq(&dev->event_lock);
+ file_priv->event_space -= length;
+ list_add(&e->link, &file_priv->event_list);
+ spin_unlock_irq(&dev->event_lock);
break;
+ }
- if (__copy_to_user_inatomic(buffer + ret,
- e->event, e->event->length)) {
+ if (copy_to_user(buffer + ret, e->event, length)) {
if (ret == 0)
ret = -EFAULT;
- break;
+ goto put_back_event;
}
- file_priv->event_space += e->event->length;
- ret += e->event->length;
- list_del(&e->link);
+ ret += length;
e->destroy(e);
}
}
- spin_unlock_irq(&dev->event_lock);
+ mutex_unlock(&file_priv->event_read_lock);
return ret;
}
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index c7de454e8e88..2e10bba4468b 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -244,8 +244,9 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
* @filp: drm file-private structure to use for the handle look up
* @handle: userspace handle to delete
*
- * Removes the GEM handle from the @filp lookup table and if this is the last
- * handle also cleans up linked resources like GEM names.
+ * Removes the GEM handle from the @filp lookup table which has been added with
+ * drm_gem_handle_create(). If this is the last handle also cleans up linked
+ * resources like GEM names.
*/
int
drm_gem_handle_delete(struct drm_file *filp, u32 handle)
@@ -314,6 +315,10 @@ EXPORT_SYMBOL(drm_gem_dumb_destroy);
* This expects the dev->object_name_lock to be held already and will drop it
* before returning. Used to avoid races in establishing new handles when
* importing an object from either an flink name or a dma-buf.
+ *
+ * Handles must be release again through drm_gem_handle_delete(). This is done
+ * when userspace closes @file_priv for all attached handles, or through the
+ * GEM_CLOSE ioctl for individual handles.
*/
int
drm_gem_handle_create_tail(struct drm_file *file_priv,
@@ -541,7 +546,17 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
}
EXPORT_SYMBOL(drm_gem_put_pages);
-/** Returns a reference to the object named by the handle. */
+/**
+ * drm_gem_object_lookup - look up a GEM object from it's handle
+ * @dev: DRM device
+ * @filp: DRM file private date
+ * @handle: userspace handle
+ *
+ * Returns:
+ *
+ * A reference to the object named by the handle if such exists on @filp, NULL
+ * otherwise.
+ */
struct drm_gem_object *
drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
u32 handle)
@@ -774,6 +789,13 @@ drm_gem_object_free(struct kref *kref)
}
EXPORT_SYMBOL(drm_gem_object_free);
+/**
+ * drm_gem_vm_open - vma->ops->open implementation for GEM
+ * @vma: VM area structure
+ *
+ * This function implements the #vm_operations_struct open() callback for GEM
+ * drivers. This must be used together with drm_gem_vm_close().
+ */
void drm_gem_vm_open(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
@@ -782,6 +804,13 @@ void drm_gem_vm_open(struct vm_area_struct *vma)
}
EXPORT_SYMBOL(drm_gem_vm_open);
+/**
+ * drm_gem_vm_close - vma->ops->close implementation for GEM
+ * @vma: VM area structure
+ *
+ * This function implements the #vm_operations_struct close() callback for GEM
+ * drivers. This must be used together with drm_gem_vm_open().
+ */
void drm_gem_vm_close(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index cd74a0953f42..ef6bd3656548 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -917,13 +917,30 @@ bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_displ
} else if (mode1->clock != mode2->clock)
return false;
+ return drm_mode_equal_no_clocks(mode1, mode2);
+}
+EXPORT_SYMBOL(drm_mode_equal);
+
+/**
+ * drm_mode_equal_no_clocks - test modes for equality
+ * @mode1: first mode
+ * @mode2: second mode
+ *
+ * Check to see if @mode1 and @mode2 are equivalent, but
+ * don't check the pixel clocks.
+ *
+ * Returns:
+ * True if the modes are equal, false otherwise.
+ */
+bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
+{
if ((mode1->flags & DRM_MODE_FLAG_3D_MASK) !=
(mode2->flags & DRM_MODE_FLAG_3D_MASK))
return false;
return drm_mode_equal_no_clocks_no_stereo(mode1, mode2);
}
-EXPORT_SYMBOL(drm_mode_equal);
+EXPORT_SYMBOL(drm_mode_equal_no_clocks);
/**
* drm_mode_equal_no_clocks_no_stereo - test modes for equality
@@ -1230,7 +1247,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
bool yres_specified = false, cvt = false, rb = false;
bool interlace = false, margins = false, was_digit = false;
- int i;
+ int i, err;
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
#ifdef CONFIG_FB
@@ -1250,7 +1267,9 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
case '@':
if (!refresh_specified && !bpp_specified &&
!yres_specified && !cvt && !rb && was_digit) {
- refresh = simple_strtol(&name[i+1], NULL, 10);
+ err = kstrtouint(&name[i + 1], 10, &refresh);
+ if (err)
+ return false;
refresh_specified = true;
was_digit = false;
} else
@@ -1259,7 +1278,9 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
case '-':
if (!bpp_specified && !yres_specified && !cvt &&
!rb && was_digit) {
- bpp = simple_strtol(&name[i+1], NULL, 10);
+ err = kstrtouint(&name[i + 1], 10, &bpp);
+ if (err)
+ return false;
bpp_specified = true;
was_digit = false;
} else
@@ -1267,7 +1288,9 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
break;
case 'x':
if (!yres_specified && was_digit) {
- yres = simple_strtol(&name[i+1], NULL, 10);
+ err = kstrtouint(&name[i + 1], 10, &yres);
+ if (err)
+ return false;
yres_specified = true;
was_digit = false;
} else
@@ -1491,4 +1514,4 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
out:
return ret;
-} \ No newline at end of file
+}
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index 6675b1428410..c2f5971146ba 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -57,11 +57,18 @@
/**
* drm_modeset_lock_all - take all modeset locks
- * @dev: drm device
+ * @dev: DRM device
*
* This function takes all modeset locks, suitable where a more fine-grained
- * scheme isn't (yet) implemented. Locks must be dropped with
- * drm_modeset_unlock_all.
+ * scheme isn't (yet) implemented. Locks must be dropped by calling the
+ * drm_modeset_unlock_all() function.
+ *
+ * This function is deprecated. It allocates a lock acquisition context and
+ * stores it in the DRM device's ->mode_config. This facilitate conversion of
+ * existing code because it removes the need to manually deal with the
+ * acquisition context, but it is also brittle because the context is global
+ * and care must be taken not to nest calls. New code should use the
+ * drm_modeset_lock_all_ctx() function and pass in the context explicitly.
*/
void drm_modeset_lock_all(struct drm_device *dev)
{
@@ -78,39 +85,43 @@ void drm_modeset_lock_all(struct drm_device *dev)
drm_modeset_acquire_init(ctx, 0);
retry:
- ret = drm_modeset_lock(&config->connection_mutex, ctx);
- if (ret)
- goto fail;
- ret = drm_modeset_lock_all_crtcs(dev, ctx);
- if (ret)
- goto fail;
+ ret = drm_modeset_lock_all_ctx(dev, ctx);
+ if (ret < 0) {
+ if (ret == -EDEADLK) {
+ drm_modeset_backoff(ctx);
+ goto retry;
+ }
+
+ drm_modeset_acquire_fini(ctx);
+ kfree(ctx);
+ return;
+ }
WARN_ON(config->acquire_ctx);
- /* now we hold the locks, so now that it is safe, stash the
- * ctx for drm_modeset_unlock_all():
+ /*
+ * We hold the locks now, so it is safe to stash the acquisition
+ * context for drm_modeset_unlock_all().
*/
config->acquire_ctx = ctx;
drm_warn_on_modeset_not_all_locked(dev);
-
- return;
-
-fail:
- if (ret == -EDEADLK) {
- drm_modeset_backoff(ctx);
- goto retry;
- }
-
- kfree(ctx);
}
EXPORT_SYMBOL(drm_modeset_lock_all);
/**
* drm_modeset_unlock_all - drop all modeset locks
- * @dev: device
+ * @dev: DRM device
*
- * This function drop all modeset locks taken by drm_modeset_lock_all.
+ * This function drops all modeset locks taken by a previous call to the
+ * drm_modeset_lock_all() function.
+ *
+ * This function is deprecated. It uses the lock acquisition context stored
+ * in the DRM device's ->mode_config. This facilitates conversion of existing
+ * code because it removes the need to manually deal with the acquisition
+ * context, but it is also brittle because the context is global and care must
+ * be taken not to nest calls. New code should pass the acquisition context
+ * directly to the drm_modeset_drop_locks() function.
*/
void drm_modeset_unlock_all(struct drm_device *dev)
{
@@ -431,14 +442,34 @@ void drm_modeset_unlock(struct drm_modeset_lock *lock)
}
EXPORT_SYMBOL(drm_modeset_unlock);
-/* In some legacy codepaths it's convenient to just grab all the crtc and plane
- * related locks. */
-int drm_modeset_lock_all_crtcs(struct drm_device *dev,
- struct drm_modeset_acquire_ctx *ctx)
+/**
+ * drm_modeset_lock_all_ctx - take all modeset locks
+ * @dev: DRM device
+ * @ctx: lock acquisition context
+ *
+ * This function takes all modeset locks, suitable where a more fine-grained
+ * scheme isn't (yet) implemented.
+ *
+ * Unlike drm_modeset_lock_all(), it doesn't take the dev->mode_config.mutex
+ * since that lock isn't required for modeset state changes. Callers which
+ * need to grab that lock too need to do so outside of the acquire context
+ * @ctx.
+ *
+ * Locks acquired with this function should be released by calling the
+ * drm_modeset_drop_locks() function on @ctx.
+ *
+ * Returns: 0 on success or a negative error-code on failure.
+ */
+int drm_modeset_lock_all_ctx(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct drm_crtc *crtc;
struct drm_plane *plane;
- int ret = 0;
+ int ret;
+
+ ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
+ if (ret)
+ return ret;
drm_for_each_crtc(crtc, dev) {
ret = drm_modeset_lock(&crtc->mutex, ctx);
@@ -454,4 +485,4 @@ int drm_modeset_lock_all_crtcs(struct drm_device *dev,
return 0;
}
-EXPORT_SYMBOL(drm_modeset_lock_all_crtcs);
+EXPORT_SYMBOL(drm_modeset_lock_all_ctx);
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index d384ebcf0aaf..a6983d41920d 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -164,6 +164,8 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
vscale = drm_rect_calc_vscale(src, dest, min_scale, max_scale);
if (hscale < 0 || vscale < 0) {
DRM_DEBUG_KMS("Invalid scaling of plane\n");
+ drm_rect_debug_print("src: ", src, true);
+ drm_rect_debug_print("dst: ", dest, false);
return -ERANGE;
}
@@ -180,6 +182,8 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
if (!can_position && !drm_rect_equals(dest, clip)) {
DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
+ drm_rect_debug_print("dst: ", dest, false);
+ drm_rect_debug_print("clip: ", clip, false);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index f8b5fcfa91a2..bfdf5bb223b9 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -147,6 +147,8 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
list_for_each_entry(mode, &connector->modes, head)
mode->status = MODE_UNVERIFIED;
+ old_status = connector->status;
+
if (connector->force) {
if (connector->force == DRM_FORCE_ON ||
connector->force == DRM_FORCE_ON_DIGITAL)
@@ -156,33 +158,32 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
if (connector->funcs->force)
connector->funcs->force(connector);
} else {
- old_status = connector->status;
-
connector->status = connector->funcs->detect(connector, true);
+ }
+
+ /*
+ * Normally either the driver's hpd code or the poll loop should
+ * pick up any changes and fire the hotplug event. But if
+ * userspace sneaks in a probe, we might miss a change. Hence
+ * check here, and if anything changed start the hotplug code.
+ */
+ if (old_status != connector->status) {
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
+ connector->base.id,
+ connector->name,
+ drm_get_connector_status_name(old_status),
+ drm_get_connector_status_name(connector->status));
/*
- * Normally either the driver's hpd code or the poll loop should
- * pick up any changes and fire the hotplug event. But if
- * userspace sneaks in a probe, we might miss a change. Hence
- * check here, and if anything changed start the hotplug code.
+ * The hotplug event code might call into the fb
+ * helpers, and so expects that we do not hold any
+ * locks. Fire up the poll struct instead, it will
+ * disable itself again.
*/
- if (old_status != connector->status) {
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
- connector->base.id,
- connector->name,
- old_status, connector->status);
-
- /*
- * The hotplug event code might call into the fb
- * helpers, and so expects that we do not hold any
- * locks. Fire up the poll struct instead, it will
- * disable itself again.
- */
- dev->mode_config.delayed_event = true;
- if (dev->mode_config.poll_enabled)
- schedule_delayed_work(&dev->mode_config.output_poll_work,
- 0);
- }
+ dev->mode_config.delayed_event = true;
+ if (dev->mode_config.poll_enabled)
+ schedule_delayed_work(&dev->mode_config.output_poll_work,
+ 0);
}
/* Re-enable polling in case the global poll config changed. */
diff --git a/drivers/gpu/drm/drm_rect.c b/drivers/gpu/drm/drm_rect.c
index 531ac4cc9756..a8e2c8603945 100644
--- a/drivers/gpu/drm/drm_rect.c
+++ b/drivers/gpu/drm/drm_rect.c
@@ -275,22 +275,23 @@ EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed);
/**
* drm_rect_debug_print - print the rectangle information
+ * @prefix: prefix string
* @r: rectangle to print
* @fixed_point: rectangle is in 16.16 fixed point format
*/
-void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point)
+void drm_rect_debug_print(const char *prefix, const struct drm_rect *r, bool fixed_point)
{
int w = drm_rect_width(r);
int h = drm_rect_height(r);
if (fixed_point)
- DRM_DEBUG_KMS("%d.%06ux%d.%06u%+d.%06u%+d.%06u\n",
+ DRM_DEBUG_KMS("%s%d.%06ux%d.%06u%+d.%06u%+d.%06u\n", prefix,
w >> 16, ((w & 0xffff) * 15625) >> 10,
h >> 16, ((h & 0xffff) * 15625) >> 10,
r->x1 >> 16, ((r->x1 & 0xffff) * 15625) >> 10,
r->y1 >> 16, ((r->y1 & 0xffff) * 15625) >> 10);
else
- DRM_DEBUG_KMS("%dx%d%+d%+d\n", w, h, r->x1, r->y1);
+ DRM_DEBUG_KMS("%s%dx%d%+d%+d\n", prefix, w, h, r->x1, r->y1);
}
EXPORT_SYMBOL(drm_rect_debug_print);
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 615b7e667320..0ca64106a97b 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -167,47 +167,35 @@ static ssize_t status_store(struct device *device,
{
struct drm_connector *connector = to_drm_connector(device);
struct drm_device *dev = connector->dev;
- enum drm_connector_status old_status;
+ enum drm_connector_force old_force;
int ret;
ret = mutex_lock_interruptible(&dev->mode_config.mutex);
if (ret)
return ret;
- old_status = connector->status;
+ old_force = connector->force;
- if (sysfs_streq(buf, "detect")) {
+ if (sysfs_streq(buf, "detect"))
connector->force = 0;
- connector->status = connector->funcs->detect(connector, true);
- } else if (sysfs_streq(buf, "on")) {
+ else if (sysfs_streq(buf, "on"))
connector->force = DRM_FORCE_ON;
- } else if (sysfs_streq(buf, "on-digital")) {
+ else if (sysfs_streq(buf, "on-digital"))
connector->force = DRM_FORCE_ON_DIGITAL;
- } else if (sysfs_streq(buf, "off")) {
+ else if (sysfs_streq(buf, "off"))
connector->force = DRM_FORCE_OFF;
- } else
+ else
ret = -EINVAL;
- if (ret == 0 && connector->force) {
- if (connector->force == DRM_FORCE_ON ||
- connector->force == DRM_FORCE_ON_DIGITAL)
- connector->status = connector_status_connected;
- else
- connector->status = connector_status_disconnected;
- if (connector->funcs->force)
- connector->funcs->force(connector);
- }
-
- if (old_status != connector->status) {
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
+ if (old_force != connector->force || !connector->force) {
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force updated from %d to %d or reprobing\n",
connector->base.id,
connector->name,
- old_status, connector->status);
+ old_force, connector->force);
- dev->mode_config.delayed_event = true;
- if (dev->mode_config.poll_enabled)
- schedule_delayed_work(&dev->mode_config.output_poll_work,
- 0);
+ connector->funcs->fill_modes(connector,
+ dev->mode_config.max_width,
+ dev->mode_config.max_height);
}
mutex_unlock(&dev->mode_config.mutex);
@@ -256,23 +244,29 @@ static ssize_t edid_show(struct file *filp, struct kobject *kobj,
struct drm_connector *connector = to_drm_connector(connector_dev);
unsigned char *edid;
size_t size;
+ ssize_t ret = 0;
+ mutex_lock(&connector->dev->mode_config.mutex);
if (!connector->edid_blob_ptr)
- return 0;
+ goto unlock;
edid = connector->edid_blob_ptr->data;
size = connector->edid_blob_ptr->length;
if (!edid)
- return 0;
+ goto unlock;
if (off >= size)
- return 0;
+ goto unlock;
if (off + count > size)
count = size - off;
memcpy(buf, edid + off, count);
- return count;
+ ret = count;
+unlock:
+ mutex_unlock(&connector->dev->mode_config.mutex);
+
+ return ret;
}
static ssize_t modes_show(struct device *device,
@@ -283,10 +277,12 @@ static ssize_t modes_show(struct device *device,
struct drm_display_mode *mode;
int written = 0;
+ mutex_lock(&connector->dev->mode_config.mutex);
list_for_each_entry(mode, &connector->modes, head) {
written += snprintf(buf + written, PAGE_SIZE - written, "%s\n",
mode->name);
}
+ mutex_unlock(&connector->dev->mode_config.mutex);
return written;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index fcea28bdbc42..49b9bc302e87 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -117,7 +117,7 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
struct drm_framebuffer *
exynos_drm_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct exynos_drm_gem **exynos_gem,
int count)
{
@@ -154,7 +154,7 @@ err:
static struct drm_framebuffer *
exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
struct drm_gem_object *obj;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h
index cf39f9816a87..6fa0e47a1415 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h
@@ -18,7 +18,7 @@
struct drm_framebuffer *
exynos_drm_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct exynos_drm_gem **exynos_gem,
int count);
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 2eaf1b31c7bd..ee95c03a8c54 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -241,7 +241,7 @@ static struct fb_ops psbfb_unaccel_ops = {
*/
static int psb_framebuffer_init(struct drm_device *dev,
struct psb_framebuffer *fb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct gtt_range *gt)
{
u32 bpp, depth;
@@ -284,7 +284,7 @@ static int psb_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *psb_framebuffer_create
(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct gtt_range *gt)
{
struct psb_framebuffer *fb;
@@ -406,8 +406,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
memset(dev_priv->vram_addr + backing->offset, 0, size);
- mutex_lock(&dev->struct_mutex);
-
info = drm_fb_helper_alloc_fbi(&fbdev->psb_fb_helper);
if (IS_ERR(info)) {
ret = PTR_ERR(info);
@@ -463,17 +461,15 @@ static int psbfb_create(struct psb_fbdev *fbdev,
dev_dbg(dev->dev, "allocated %dx%d fb\n",
psbfb->base.width, psbfb->base.height);
- mutex_unlock(&dev->struct_mutex);
return 0;
out_unref:
if (backing->stolen)
psb_gtt_free_range(dev, backing);
else
- drm_gem_object_unreference(&backing->gem);
+ drm_gem_object_unreference_unlocked(&backing->gem);
drm_fb_helper_release_fbi(&fbdev->psb_fb_helper);
out_err1:
- mutex_unlock(&dev->struct_mutex);
psb_gtt_free_range(dev, backing);
return ret;
}
@@ -488,7 +484,7 @@ out_err1:
*/
static struct drm_framebuffer *psb_user_framebuffer_create
(struct drm_device *dev, struct drm_file *filp,
- struct drm_mode_fb_cmd2 *cmd)
+ const struct drm_mode_fb_cmd2 *cmd)
{
struct gtt_range *r;
struct drm_gem_object *obj;
@@ -569,7 +565,7 @@ static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
drm_framebuffer_cleanup(&psbfb->base);
if (psbfb->gtt)
- drm_gem_object_unreference(&psbfb->gtt->gem);
+ drm_gem_object_unreference_unlocked(&psbfb->gtt->gem);
return 0;
}
@@ -784,12 +780,8 @@ void psb_modeset_cleanup(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
if (dev_priv->modeset) {
- mutex_lock(&dev->struct_mutex);
-
drm_kms_helper_poll_fini(dev);
psb_fbdev_fini(dev);
drm_mode_config_cleanup(dev);
-
- mutex_unlock(&dev->struct_mutex);
}
}
diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c
index c707fa6fca85..506224b3a0ad 100644
--- a/drivers/gpu/drm/gma500/gem.c
+++ b/drivers/gpu/drm/gma500/gem.c
@@ -62,15 +62,10 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
int ret = 0;
struct drm_gem_object *obj;
- mutex_lock(&dev->struct_mutex);
-
/* GEM does all our handle to object mapping */
obj = drm_gem_object_lookup(dev, file, handle);
- if (obj == NULL) {
- ret = -ENOENT;
- goto unlock;
- }
- /* What validation is needed here ? */
+ if (obj == NULL)
+ return -ENOENT;
/* Make it mmapable */
ret = drm_gem_create_mmap_offset(obj);
@@ -78,9 +73,7 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
goto out;
*offset = drm_vma_node_offset_addr(&obj->vma_node);
out:
- drm_gem_object_unreference(obj);
-unlock:
- mutex_unlock(&dev->struct_mutex);
+ drm_gem_object_unreference_unlocked(obj);
return ret;
}
@@ -130,7 +123,7 @@ int psb_gem_create(struct drm_file *file, struct drm_device *dev, u64 size,
return ret;
}
/* We have the initial and handle reference but need only one now */
- drm_gem_object_unreference(&r->gem);
+ drm_gem_object_unreference_unlocked(&r->gem);
*handlep = handle;
return 0;
}
@@ -189,7 +182,7 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
/* Make sure we don't parallel update on a fault, nor move or remove
something from beneath our feet */
- mutex_lock(&dev->struct_mutex);
+ mutex_lock(&dev_priv->mmap_mutex);
/* For now the mmap pins the object and it stays pinned. As things
stand that will do us no harm */
@@ -215,7 +208,7 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
fail:
- mutex_unlock(&dev->struct_mutex);
+ mutex_unlock(&dev_priv->mmap_mutex);
switch (ret) {
case 0:
case -ERESTARTSYS:
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
index 001b450b27b3..ff17af4cfc64 100644
--- a/drivers/gpu/drm/gma500/gma_display.c
+++ b/drivers/gpu/drm/gma500/gma_display.c
@@ -349,8 +349,6 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
/* If we didn't get a handle then turn the cursor off */
if (!handle) {
temp = CURSOR_MODE_DISABLE;
- mutex_lock(&dev->struct_mutex);
-
if (gma_power_begin(dev, false)) {
REG_WRITE(control, temp);
REG_WRITE(base, 0);
@@ -362,11 +360,9 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
gt = container_of(gma_crtc->cursor_obj,
struct gtt_range, gem);
psb_gtt_unpin(gt);
- drm_gem_object_unreference(gma_crtc->cursor_obj);
+ drm_gem_object_unreference_unlocked(gma_crtc->cursor_obj);
gma_crtc->cursor_obj = NULL;
}
-
- mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -376,7 +372,6 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
return -EINVAL;
}
- mutex_lock(&dev->struct_mutex);
obj = drm_gem_object_lookup(dev, file_priv, handle);
if (!obj) {
ret = -ENOENT;
@@ -441,17 +436,15 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
if (gma_crtc->cursor_obj) {
gt = container_of(gma_crtc->cursor_obj, struct gtt_range, gem);
psb_gtt_unpin(gt);
- drm_gem_object_unreference(gma_crtc->cursor_obj);
+ drm_gem_object_unreference_unlocked(gma_crtc->cursor_obj);
}
gma_crtc->cursor_obj = obj;
unlock:
- mutex_unlock(&dev->struct_mutex);
return ret;
unref_cursor:
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
+ drm_gem_object_unreference_unlocked(obj);
return ret;
}
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index ce015db59dc6..8f69225ce2b4 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -425,6 +425,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
if (!resume) {
mutex_init(&dev_priv->gtt_mutex);
+ mutex_init(&dev_priv->mmap_mutex);
psb_gtt_alloc(dev);
}
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index e21726ecac32..3bd2c726dd61 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -465,6 +465,8 @@ struct drm_psb_private {
struct mutex gtt_mutex;
struct resource *gtt_mem; /* Our PCI resource */
+ struct mutex mmap_mutex;
+
struct psb_mmu_driver *mmu;
struct psb_mmu_pd *pf_pd;
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 051eab33e4c7..fcd77b27514d 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -10,6 +10,7 @@ config DRM_I915
# the shmem_readpage() which depends upon tmpfs
select SHMEM
select TMPFS
+ select STOP_MACHINE
select DRM_KMS_HELPER
select DRM_PANEL
select DRM_MIPI_DSI
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 44d290ae1999..0851de07bd13 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -77,6 +77,7 @@ i915-y += dvo_ch7017.o \
dvo_tfp410.o \
intel_crt.o \
intel_ddi.o \
+ intel_dp_link_training.o \
intel_dp_mst.o \
intel_dp.o \
intel_dsi.o \
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index 0e2c1b9648a7..13dea4263554 100644
--- a/drivers/gpu/drm/i915/dvo.h
+++ b/drivers/gpu/drm/i915/dvo.h
@@ -32,7 +32,8 @@ struct intel_dvo_device {
const char *name;
int type;
/* DVOA/B/C output register */
- u32 dvo_reg;
+ i915_reg_t dvo_reg;
+ i915_reg_t dvo_srcdim_reg;
/* GPIO register used for i2c bus to control this device */
u32 gpio;
int slave_addr;
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index db58c8d664c2..814d894ed925 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -407,14 +407,14 @@ static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = {
* LRI.
*/
struct drm_i915_reg_descriptor {
- u32 addr;
+ i915_reg_t addr;
u32 mask;
u32 value;
};
/* Convenience macro for adding 32-bit registers. */
-#define REG32(address, ...) \
- { .addr = address, __VA_ARGS__ }
+#define REG32(_reg, ...) \
+ { .addr = (_reg), __VA_ARGS__ }
/*
* Convenience macro for adding 64-bit registers.
@@ -423,8 +423,13 @@ struct drm_i915_reg_descriptor {
* access commands only allow 32-bit accesses. Hence, we have to include
* entries for both halves of the 64-bit registers.
*/
-#define REG64(addr) \
- REG32(addr), REG32(addr + sizeof(u32))
+#define REG64(_reg) \
+ { .addr = _reg }, \
+ { .addr = _reg ## _UDW }
+
+#define REG64_IDX(_reg, idx) \
+ { .addr = _reg(idx) }, \
+ { .addr = _reg ## _UDW(idx) }
static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
REG64(GPGPU_THREADS_DISPATCHED),
@@ -451,14 +456,14 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
REG32(GEN7_GPGPU_DISPATCHDIMX),
REG32(GEN7_GPGPU_DISPATCHDIMY),
REG32(GEN7_GPGPU_DISPATCHDIMZ),
- REG64(GEN7_SO_NUM_PRIMS_WRITTEN(0)),
- REG64(GEN7_SO_NUM_PRIMS_WRITTEN(1)),
- REG64(GEN7_SO_NUM_PRIMS_WRITTEN(2)),
- REG64(GEN7_SO_NUM_PRIMS_WRITTEN(3)),
- REG64(GEN7_SO_PRIM_STORAGE_NEEDED(0)),
- REG64(GEN7_SO_PRIM_STORAGE_NEEDED(1)),
- REG64(GEN7_SO_PRIM_STORAGE_NEEDED(2)),
- REG64(GEN7_SO_PRIM_STORAGE_NEEDED(3)),
+ REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 0),
+ REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 1),
+ REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 2),
+ REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 3),
+ REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 0),
+ REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 1),
+ REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 2),
+ REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 3),
REG32(GEN7_SO_WRITE_OFFSET(0)),
REG32(GEN7_SO_WRITE_OFFSET(1)),
REG32(GEN7_SO_WRITE_OFFSET(2)),
@@ -592,7 +597,7 @@ static bool check_sorted(int ring_id,
bool ret = true;
for (i = 0; i < reg_count; i++) {
- u32 curr = reg_table[i].addr;
+ u32 curr = i915_mmio_reg_offset(reg_table[i].addr);
if (curr < previous) {
DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n",
@@ -847,7 +852,7 @@ find_reg(const struct drm_i915_reg_descriptor *table,
int i;
for (i = 0; i < count; i++) {
- if (table[i].addr == addr)
+ if (i915_mmio_reg_offset(table[i].addr) == addr)
return &table[i];
}
}
@@ -1023,7 +1028,7 @@ static bool check_cmd(const struct intel_engine_cs *ring,
* to the register. Hence, limit OACONTROL writes to
* only MI_LOAD_REGISTER_IMM commands.
*/
- if (reg_addr == OACONTROL) {
+ if (reg_addr == i915_mmio_reg_offset(OACONTROL)) {
if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n");
return false;
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 8aab974b0564..411a9c68b4ee 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1252,18 +1252,21 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 0 :
rp_state_cap >> 16) & 0xff;
- max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
+ max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
+ GEN9_FREQ_SCALER : 1);
seq_printf(m, "Lowest (RPN) frequency: %dMHz\n",
intel_gpu_freq(dev_priv, max_freq));
max_freq = (rp_state_cap & 0xff00) >> 8;
- max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
+ max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
+ GEN9_FREQ_SCALER : 1);
seq_printf(m, "Nominal (RP1) frequency: %dMHz\n",
intel_gpu_freq(dev_priv, max_freq));
max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 16 :
rp_state_cap >> 0) & 0xff;
- max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
+ max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
+ GEN9_FREQ_SCALER : 1);
seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
intel_gpu_freq(dev_priv, max_freq));
seq_printf(m, "Max overclocked frequency: %dMHz\n",
@@ -1523,7 +1526,7 @@ static int gen6_drpc_info(struct seq_file *m)
seq_printf(m, "RC information accurate: %s\n", yesno(count < 51));
}
- gt_core_status = readl(dev_priv->regs + GEN6_GT_CORE_STATUS);
+ gt_core_status = I915_READ_FW(GEN6_GT_CORE_STATUS);
trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4, true);
rpmodectl1 = I915_READ(GEN6_RP_CONTROL);
@@ -1640,7 +1643,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
seq_puts(m, "FBC enabled\n");
else
seq_printf(m, "FBC disabled: %s\n",
- intel_no_fbc_reason_str(dev_priv->fbc.no_fbc_reason));
+ dev_priv->fbc.no_fbc_reason);
if (INTEL_INFO(dev_priv)->gen >= 7)
seq_printf(m, "Compressing: %s\n",
@@ -1801,7 +1804,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
if (ret)
goto out;
- if (IS_SKYLAKE(dev)) {
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
/* Convert GT frequency to 50 HZ units */
min_gpu_freq =
dev_priv->rps.min_freq_softlimit / GEN9_FREQ_SCALER;
@@ -1821,7 +1824,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
&ia_freq);
seq_printf(m, "%d\t\t%d\t\t\t\t%d\n",
intel_gpu_freq(dev_priv, (gpu_freq *
- (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1))),
+ (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
+ GEN9_FREQ_SCALER : 1))),
((ia_freq >> 0) & 0xff) * 100,
((ia_freq >> 8) & 0xff) * 100);
}
@@ -1873,17 +1877,19 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
struct drm_i915_private *dev_priv = dev->dev_private;
ifbdev = dev_priv->fbdev;
- fb = to_intel_framebuffer(ifbdev->helper.fb);
-
- seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
- fb->base.width,
- fb->base.height,
- fb->base.depth,
- fb->base.bits_per_pixel,
- fb->base.modifier[0],
- atomic_read(&fb->base.refcount.refcount));
- describe_obj(m, fb->obj);
- seq_putc(m, '\n');
+ if (ifbdev) {
+ fb = to_intel_framebuffer(ifbdev->helper.fb);
+
+ seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
+ fb->base.width,
+ fb->base.height,
+ fb->base.depth,
+ fb->base.bits_per_pixel,
+ fb->base.modifier[0],
+ atomic_read(&fb->base.refcount.refcount));
+ describe_obj(m, fb->obj);
+ seq_putc(m, '\n');
+ }
#endif
mutex_lock(&dev->mode_config.fb_lock);
@@ -2402,6 +2408,12 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
seq_printf(m, "\tversion found: %d.%d\n",
guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found);
+ seq_printf(m, "\theader: offset is %d; size = %d\n",
+ guc_fw->header_offset, guc_fw->header_size);
+ seq_printf(m, "\tuCode: offset is %d; size = %d\n",
+ guc_fw->ucode_offset, guc_fw->ucode_size);
+ seq_printf(m, "\tRSA: offset is %d; size = %d\n",
+ guc_fw->rsa_offset, guc_fw->rsa_size);
tmp = I915_READ(GUC_STATUS);
@@ -2550,7 +2562,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
yesno(work_busy(&dev_priv->psr.work.work)));
if (HAS_DDI(dev))
- enabled = I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE;
+ enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
else {
for_each_pipe(dev_priv, pipe) {
stat[pipe] = I915_READ(VLV_PSRSTAT(pipe)) &
@@ -2572,7 +2584,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
/* CHV PSR has no kind of performance counter */
if (HAS_DDI(dev)) {
- psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) &
+ psrperf = I915_READ(EDP_PSR_PERF_CNT) &
EDP_PSR_PERF_CNT_MASK;
seq_printf(m, "Performance_Counter: %u\n", psrperf);
@@ -2696,24 +2708,16 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
return "TRANSCODER_C";
case POWER_DOMAIN_TRANSCODER_EDP:
return "TRANSCODER_EDP";
- case POWER_DOMAIN_PORT_DDI_A_2_LANES:
- return "PORT_DDI_A_2_LANES";
- case POWER_DOMAIN_PORT_DDI_A_4_LANES:
- return "PORT_DDI_A_4_LANES";
- case POWER_DOMAIN_PORT_DDI_B_2_LANES:
- return "PORT_DDI_B_2_LANES";
- case POWER_DOMAIN_PORT_DDI_B_4_LANES:
- return "PORT_DDI_B_4_LANES";
- case POWER_DOMAIN_PORT_DDI_C_2_LANES:
- return "PORT_DDI_C_2_LANES";
- case POWER_DOMAIN_PORT_DDI_C_4_LANES:
- return "PORT_DDI_C_4_LANES";
- case POWER_DOMAIN_PORT_DDI_D_2_LANES:
- return "PORT_DDI_D_2_LANES";
- case POWER_DOMAIN_PORT_DDI_D_4_LANES:
- return "PORT_DDI_D_4_LANES";
- case POWER_DOMAIN_PORT_DDI_E_2_LANES:
- return "PORT_DDI_E_2_LANES";
+ case POWER_DOMAIN_PORT_DDI_A_LANES:
+ return "PORT_DDI_A_LANES";
+ case POWER_DOMAIN_PORT_DDI_B_LANES:
+ return "PORT_DDI_B_LANES";
+ case POWER_DOMAIN_PORT_DDI_C_LANES:
+ return "PORT_DDI_C_LANES";
+ case POWER_DOMAIN_PORT_DDI_D_LANES:
+ return "PORT_DDI_D_LANES";
+ case POWER_DOMAIN_PORT_DDI_E_LANES:
+ return "PORT_DDI_E_LANES";
case POWER_DOMAIN_PORT_DSI:
return "PORT_DSI";
case POWER_DOMAIN_PORT_CRT:
@@ -2736,6 +2740,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
return "AUX_D";
case POWER_DOMAIN_GMBUS:
return "GMBUS";
+ case POWER_DOMAIN_MODESET:
+ return "MODESET";
case POWER_DOMAIN_INIT:
return "INIT";
default:
@@ -2779,6 +2785,51 @@ static int i915_power_domain_info(struct seq_file *m, void *unused)
return 0;
}
+static int i915_dmc_info(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_csr *csr;
+
+ if (!HAS_CSR(dev)) {
+ seq_puts(m, "not supported\n");
+ return 0;
+ }
+
+ csr = &dev_priv->csr;
+
+ intel_runtime_pm_get(dev_priv);
+
+ seq_printf(m, "fw loaded: %s\n", yesno(csr->dmc_payload != NULL));
+ seq_printf(m, "path: %s\n", csr->fw_path);
+
+ if (!csr->dmc_payload)
+ goto out;
+
+ seq_printf(m, "version: %d.%d\n", CSR_VERSION_MAJOR(csr->version),
+ CSR_VERSION_MINOR(csr->version));
+
+ if (IS_SKYLAKE(dev) && csr->version >= CSR_VERSION(1, 6)) {
+ seq_printf(m, "DC3 -> DC5 count: %d\n",
+ I915_READ(SKL_CSR_DC3_DC5_COUNT));
+ seq_printf(m, "DC5 -> DC6 count: %d\n",
+ I915_READ(SKL_CSR_DC5_DC6_COUNT));
+ } else if (IS_BROXTON(dev) && csr->version >= CSR_VERSION(1, 4)) {
+ seq_printf(m, "DC3 -> DC5 count: %d\n",
+ I915_READ(BXT_CSR_DC3_DC5_COUNT));
+ }
+
+out:
+ seq_printf(m, "program base: 0x%08x\n", I915_READ(CSR_PROGRAM(0)));
+ seq_printf(m, "ssp base: 0x%08x\n", I915_READ(CSR_SSP_BASE));
+ seq_printf(m, "htp: 0x%08x\n", I915_READ(CSR_HTP_SKL));
+
+ intel_runtime_pm_put(dev_priv);
+
+ return 0;
+}
+
static void intel_seq_print_mode(struct seq_file *m, int tabs,
struct drm_display_mode *mode)
{
@@ -2946,6 +2997,107 @@ static bool cursor_position(struct drm_device *dev, int pipe, int *x, int *y)
return cursor_active(dev, pipe);
}
+static const char *plane_type(enum drm_plane_type type)
+{
+ switch (type) {
+ case DRM_PLANE_TYPE_OVERLAY:
+ return "OVL";
+ case DRM_PLANE_TYPE_PRIMARY:
+ return "PRI";
+ case DRM_PLANE_TYPE_CURSOR:
+ return "CUR";
+ /*
+ * Deliberately omitting default: to generate compiler warnings
+ * when a new drm_plane_type gets added.
+ */
+ }
+
+ return "unknown";
+}
+
+static const char *plane_rotation(unsigned int rotation)
+{
+ static char buf[48];
+ /*
+ * According to doc only one DRM_ROTATE_ is allowed but this
+ * will print them all to visualize if the values are misused
+ */
+ snprintf(buf, sizeof(buf),
+ "%s%s%s%s%s%s(0x%08x)",
+ (rotation & BIT(DRM_ROTATE_0)) ? "0 " : "",
+ (rotation & BIT(DRM_ROTATE_90)) ? "90 " : "",
+ (rotation & BIT(DRM_ROTATE_180)) ? "180 " : "",
+ (rotation & BIT(DRM_ROTATE_270)) ? "270 " : "",
+ (rotation & BIT(DRM_REFLECT_X)) ? "FLIPX " : "",
+ (rotation & BIT(DRM_REFLECT_Y)) ? "FLIPY " : "",
+ rotation);
+
+ return buf;
+}
+
+static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
+{
+ struct drm_info_node *node = m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct intel_plane *intel_plane;
+
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ struct drm_plane_state *state;
+ struct drm_plane *plane = &intel_plane->base;
+
+ if (!plane->state) {
+ seq_puts(m, "plane->state is NULL!\n");
+ continue;
+ }
+
+ state = plane->state;
+
+ seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n",
+ plane->base.id,
+ plane_type(intel_plane->base.type),
+ state->crtc_x, state->crtc_y,
+ state->crtc_w, state->crtc_h,
+ (state->src_x >> 16),
+ ((state->src_x & 0xffff) * 15625) >> 10,
+ (state->src_y >> 16),
+ ((state->src_y & 0xffff) * 15625) >> 10,
+ (state->src_w >> 16),
+ ((state->src_w & 0xffff) * 15625) >> 10,
+ (state->src_h >> 16),
+ ((state->src_h & 0xffff) * 15625) >> 10,
+ state->fb ? drm_get_format_name(state->fb->pixel_format) : "N/A",
+ plane_rotation(state->rotation));
+ }
+}
+
+static void intel_scaler_info(struct seq_file *m, struct intel_crtc *intel_crtc)
+{
+ struct intel_crtc_state *pipe_config;
+ int num_scalers = intel_crtc->num_scalers;
+ int i;
+
+ pipe_config = to_intel_crtc_state(intel_crtc->base.state);
+
+ /* Not all platformas have a scaler */
+ if (num_scalers) {
+ seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d",
+ num_scalers,
+ pipe_config->scaler_state.scaler_users,
+ pipe_config->scaler_state.scaler_id);
+
+ for (i = 0; i < SKL_NUM_SCALERS; i++) {
+ struct intel_scaler *sc =
+ &pipe_config->scaler_state.scalers[i];
+
+ seq_printf(m, ", scalers[%d]: use=%s, mode=%x",
+ i, yesno(sc->in_use), sc->mode);
+ }
+ seq_puts(m, "\n");
+ } else {
+ seq_puts(m, "\tNo scalers available on this platform\n");
+ }
+}
+
static int i915_display_info(struct seq_file *m, void *unused)
{
struct drm_info_node *node = m->private;
@@ -2965,10 +3117,12 @@ static int i915_display_info(struct seq_file *m, void *unused)
pipe_config = to_intel_crtc_state(crtc->base.state);
- seq_printf(m, "CRTC %d: pipe: %c, active=%s (size=%dx%d)\n",
+ seq_printf(m, "CRTC %d: pipe: %c, active=%s, (size=%dx%d), dither=%s, bpp=%d\n",
crtc->base.base.id, pipe_name(crtc->pipe),
yesno(pipe_config->base.active),
- pipe_config->pipe_src_w, pipe_config->pipe_src_h);
+ pipe_config->pipe_src_w, pipe_config->pipe_src_h,
+ yesno(pipe_config->dither), pipe_config->pipe_bpp);
+
if (pipe_config->base.active) {
intel_crtc_info(m, crtc);
@@ -2978,6 +3132,8 @@ static int i915_display_info(struct seq_file *m, void *unused)
x, y, crtc->base.cursor->state->crtc_w,
crtc->base.cursor->state->crtc_h,
crtc->cursor_addr, yesno(active));
+ intel_scaler_info(m, crtc);
+ intel_plane_info(m, crtc);
}
seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s \n",
@@ -3112,7 +3268,8 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
seq_printf(m, "Workarounds applied: %d\n", dev_priv->workarounds.count);
for (i = 0; i < dev_priv->workarounds.count; ++i) {
- u32 addr, mask, value, read;
+ i915_reg_t addr;
+ u32 mask, value, read;
bool ok;
addr = dev_priv->workarounds.reg[i].addr;
@@ -3121,7 +3278,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
read = I915_READ(addr);
ok = (value & mask) == (read & mask);
seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X, read: 0x%08x, status: %s\n",
- addr, value, mask, read, ok ? "OK" : "FAIL");
+ i915_mmio_reg_offset(addr), value, mask, read, ok ? "OK" : "FAIL");
}
intel_runtime_pm_put(dev_priv);
@@ -5025,7 +5182,7 @@ static void gen9_sseu_device_status(struct drm_device *dev,
stat->slice_total++;
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
ss_cnt = INTEL_INFO(dev)->subslice_per_slice;
for (ss = 0; ss < ss_max; ss++) {
@@ -5238,6 +5395,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_energy_uJ", i915_energy_uJ, 0},
{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
{"i915_power_domain_info", i915_power_domain_info, 0},
+ {"i915_dmc_info", i915_dmc_info, 0},
{"i915_display_info", i915_display_info, 0},
{"i915_semaphore_status", i915_semaphore_status, 0},
{"i915_shared_dplls_info", i915_shared_dplls_info, 0},
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index b4741d121a74..a81c76603544 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -28,7 +28,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/async.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
@@ -338,7 +337,7 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
i915_resume_switcheroo(dev);
dev->switch_power_state = DRM_SWITCH_POWER_ON;
} else {
- pr_err("switched off\n");
+ pr_info("switched off\n");
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
i915_suspend_switcheroo(dev, pmm);
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
@@ -396,7 +395,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
if (ret)
goto cleanup_vga_switcheroo;
- intel_power_domains_init_hw(dev_priv);
+ intel_power_domains_init_hw(dev_priv, false);
+
+ intel_csr_ucode_init(dev_priv);
ret = intel_irq_install(dev_priv);
if (ret)
@@ -437,7 +438,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
* scanning against hotplug events. Hence do this first and ignore the
* tiny window where we will loose hotplug notifactions.
*/
- async_schedule(intel_fbdev_initial_config, dev_priv);
+ intel_fbdev_initial_config_async(dev);
drm_kms_helper_poll_init(dev);
@@ -663,7 +664,8 @@ static void gen9_sseu_info_init(struct drm_device *dev)
* supports EU power gating on devices with more than one EU
* pair per subslice.
*/
- info->has_slice_pg = (IS_SKYLAKE(dev) && (info->slice_total > 1));
+ info->has_slice_pg = ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
+ (info->slice_total > 1));
info->has_subslice_pg = (IS_BROXTON(dev) && (info->subslice_total > 1));
info->has_eu_pg = (info->eu_per_subslice > 2);
}
@@ -890,7 +892,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
spin_lock_init(&dev_priv->mmio_flip_lock);
mutex_init(&dev_priv->sb_lock);
mutex_init(&dev_priv->modeset_restore_lock);
- mutex_init(&dev_priv->csr_lock);
mutex_init(&dev_priv->av_mutex);
intel_pm_setup(dev);
@@ -937,9 +938,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
intel_uncore_init(dev);
- /* Load CSR Firmware for SKL */
- intel_csr_ucode_init(dev);
-
ret = i915_gem_gtt_init(dev);
if (ret)
goto out_freecsr;
@@ -1113,7 +1111,7 @@ out_mtrrfree:
out_gtt:
i915_global_gtt_cleanup(dev);
out_freecsr:
- intel_csr_ucode_fini(dev);
+ intel_csr_ucode_fini(dev_priv);
intel_uncore_fini(dev);
pci_iounmap(dev->pdev, dev_priv->regs);
put_bridge:
@@ -1131,6 +1129,8 @@ int i915_driver_unload(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
+ intel_fbdev_fini(dev);
+
i915_audio_component_cleanup(dev_priv);
ret = i915_gem_suspend(dev);
@@ -1153,8 +1153,6 @@ int i915_driver_unload(struct drm_device *dev)
acpi_video_unregister();
- intel_fbdev_fini(dev);
-
drm_vblank_cleanup(dev);
intel_modeset_cleanup(dev);
@@ -1196,7 +1194,7 @@ int i915_driver_unload(struct drm_device *dev)
intel_fbc_cleanup_cfb(dev_priv);
i915_gem_cleanup_stolen(dev);
- intel_csr_ucode_fini(dev);
+ intel_csr_ucode_fini(dev_priv);
intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev);
@@ -1264,8 +1262,6 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
- if (file_priv && file_priv->bsd_ring)
- file_priv->bsd_ring = NULL;
kfree(file_priv);
}
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 760e0ce4aa26..6344dfb72177 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -383,6 +383,7 @@ static const struct intel_device_info intel_skylake_gt3_info = {
static const struct intel_device_info intel_broxton_info = {
.is_preliminary = 1,
+ .is_broxton = 1,
.gen = 9,
.need_gfx_hws = 1, .has_hotplug = 1,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
@@ -394,50 +395,81 @@ static const struct intel_device_info intel_broxton_info = {
IVB_CURSOR_OFFSETS,
};
+static const struct intel_device_info intel_kabylake_info = {
+ .is_preliminary = 1,
+ .is_kabylake = 1,
+ .gen = 9,
+ .num_pipes = 3,
+ .need_gfx_hws = 1, .has_hotplug = 1,
+ .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
+ .has_llc = 1,
+ .has_ddi = 1,
+ .has_fpga_dbg = 1,
+ .has_fbc = 1,
+ GEN_DEFAULT_PIPEOFFSETS,
+ IVB_CURSOR_OFFSETS,
+};
+
+static const struct intel_device_info intel_kabylake_gt3_info = {
+ .is_preliminary = 1,
+ .is_kabylake = 1,
+ .gen = 9,
+ .num_pipes = 3,
+ .need_gfx_hws = 1, .has_hotplug = 1,
+ .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
+ .has_llc = 1,
+ .has_ddi = 1,
+ .has_fpga_dbg = 1,
+ .has_fbc = 1,
+ GEN_DEFAULT_PIPEOFFSETS,
+ IVB_CURSOR_OFFSETS,
+};
+
/*
* Make sure any device matches here are from most specific to most
* general. For example, since the Quanta match is based on the subsystem
* and subvendor IDs, we need it to come before the more general IVB
* PCI ID matches, otherwise we'll use the wrong info struct above.
*/
-#define INTEL_PCI_IDS \
- INTEL_I830_IDS(&intel_i830_info), \
- INTEL_I845G_IDS(&intel_845g_info), \
- INTEL_I85X_IDS(&intel_i85x_info), \
- INTEL_I865G_IDS(&intel_i865g_info), \
- INTEL_I915G_IDS(&intel_i915g_info), \
- INTEL_I915GM_IDS(&intel_i915gm_info), \
- INTEL_I945G_IDS(&intel_i945g_info), \
- INTEL_I945GM_IDS(&intel_i945gm_info), \
- INTEL_I965G_IDS(&intel_i965g_info), \
- INTEL_G33_IDS(&intel_g33_info), \
- INTEL_I965GM_IDS(&intel_i965gm_info), \
- INTEL_GM45_IDS(&intel_gm45_info), \
- INTEL_G45_IDS(&intel_g45_info), \
- INTEL_PINEVIEW_IDS(&intel_pineview_info), \
- INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info), \
- INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info), \
- INTEL_SNB_D_IDS(&intel_sandybridge_d_info), \
- INTEL_SNB_M_IDS(&intel_sandybridge_m_info), \
- INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */ \
- INTEL_IVB_M_IDS(&intel_ivybridge_m_info), \
- INTEL_IVB_D_IDS(&intel_ivybridge_d_info), \
- INTEL_HSW_D_IDS(&intel_haswell_d_info), \
- INTEL_HSW_M_IDS(&intel_haswell_m_info), \
- INTEL_VLV_M_IDS(&intel_valleyview_m_info), \
- INTEL_VLV_D_IDS(&intel_valleyview_d_info), \
- INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info), \
- INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info), \
- INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info), \
- INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info), \
- INTEL_CHV_IDS(&intel_cherryview_info), \
- INTEL_SKL_GT1_IDS(&intel_skylake_info), \
- INTEL_SKL_GT2_IDS(&intel_skylake_info), \
- INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info), \
- INTEL_BXT_IDS(&intel_broxton_info)
-
-static const struct pci_device_id pciidlist[] = { /* aka */
- INTEL_PCI_IDS,
+static const struct pci_device_id pciidlist[] = {
+ INTEL_I830_IDS(&intel_i830_info),
+ INTEL_I845G_IDS(&intel_845g_info),
+ INTEL_I85X_IDS(&intel_i85x_info),
+ INTEL_I865G_IDS(&intel_i865g_info),
+ INTEL_I915G_IDS(&intel_i915g_info),
+ INTEL_I915GM_IDS(&intel_i915gm_info),
+ INTEL_I945G_IDS(&intel_i945g_info),
+ INTEL_I945GM_IDS(&intel_i945gm_info),
+ INTEL_I965G_IDS(&intel_i965g_info),
+ INTEL_G33_IDS(&intel_g33_info),
+ INTEL_I965GM_IDS(&intel_i965gm_info),
+ INTEL_GM45_IDS(&intel_gm45_info),
+ INTEL_G45_IDS(&intel_g45_info),
+ INTEL_PINEVIEW_IDS(&intel_pineview_info),
+ INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info),
+ INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info),
+ INTEL_SNB_D_IDS(&intel_sandybridge_d_info),
+ INTEL_SNB_M_IDS(&intel_sandybridge_m_info),
+ INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */
+ INTEL_IVB_M_IDS(&intel_ivybridge_m_info),
+ INTEL_IVB_D_IDS(&intel_ivybridge_d_info),
+ INTEL_HSW_D_IDS(&intel_haswell_d_info),
+ INTEL_HSW_M_IDS(&intel_haswell_m_info),
+ INTEL_VLV_M_IDS(&intel_valleyview_m_info),
+ INTEL_VLV_D_IDS(&intel_valleyview_d_info),
+ INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info),
+ INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info),
+ INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info),
+ INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info),
+ INTEL_CHV_IDS(&intel_cherryview_info),
+ INTEL_SKL_GT1_IDS(&intel_skylake_info),
+ INTEL_SKL_GT2_IDS(&intel_skylake_info),
+ INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info),
+ INTEL_BXT_IDS(&intel_broxton_info),
+ INTEL_KBL_GT1_IDS(&intel_kabylake_info),
+ INTEL_KBL_GT2_IDS(&intel_kabylake_info),
+ INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
+ INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
{0, 0, 0}
};
@@ -463,7 +495,7 @@ static enum intel_pch intel_virt_detect_pch(struct drm_device *dev)
} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
ret = PCH_LPT;
DRM_DEBUG_KMS("Assuming LynxPoint PCH\n");
- } else if (IS_SKYLAKE(dev)) {
+ } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
ret = PCH_SPT;
DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n");
}
@@ -526,11 +558,13 @@ void intel_detect_pch(struct drm_device *dev)
} else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_SPT;
DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
- WARN_ON(!IS_SKYLAKE(dev));
+ WARN_ON(!IS_SKYLAKE(dev) &&
+ !IS_KABYLAKE(dev));
} else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_SPT;
DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
- WARN_ON(!IS_SKYLAKE(dev));
+ WARN_ON(!IS_SKYLAKE(dev) &&
+ !IS_KABYLAKE(dev));
} else if (id == INTEL_PCH_P2X_DEVICE_ID_TYPE) {
dev_priv->pch_type = intel_virt_detect_pch(dev);
} else
@@ -570,26 +604,6 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
return true;
}
-void i915_firmware_load_error_print(const char *fw_path, int err)
-{
- DRM_ERROR("failed to load firmware %s (%d)\n", fw_path, err);
-
- /*
- * If the reason is not known assume -ENOENT since that's the most
- * usual failure mode.
- */
- if (!err)
- err = -ENOENT;
-
- if (!(IS_BUILTIN(CONFIG_DRM_I915) && err == -ENOENT))
- return;
-
- DRM_ERROR(
- "The driver is built-in, so to load the firmware you need to\n"
- "include it either in the kernel (see CONFIG_EXTRA_FIRMWARE) or\n"
- "in your initrd/initramfs image.\n");
-}
-
static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
@@ -608,7 +622,6 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
static int intel_suspend_complete(struct drm_i915_private *dev_priv);
static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
bool rpm_resume);
-static int skl_resume_prepare(struct drm_i915_private *dev_priv);
static int bxt_resume_prepare(struct drm_i915_private *dev_priv);
@@ -679,6 +692,9 @@ static int i915_drm_suspend(struct drm_device *dev)
intel_display_set_init_power(dev_priv, false);
+ if (HAS_CSR(dev_priv))
+ flush_work(&dev_priv->csr.work);
+
return 0;
}
@@ -687,10 +703,13 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
struct drm_i915_private *dev_priv = drm_dev->dev_private;
int ret;
+ intel_power_domains_suspend(dev_priv);
+
ret = intel_suspend_complete(dev_priv);
if (ret) {
DRM_ERROR("Suspend complete failed: %d\n", ret);
+ intel_power_domains_init_hw(dev_priv, true);
return ret;
}
@@ -838,13 +857,11 @@ static int i915_drm_resume_early(struct drm_device *dev)
if (IS_BROXTON(dev))
ret = bxt_resume_prepare(dev_priv);
- else if (IS_SKYLAKE(dev_priv))
- ret = skl_resume_prepare(dev_priv);
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
hsw_disable_pc8(dev_priv);
intel_uncore_sanitize(dev);
- intel_power_domains_init_hw(dev_priv);
+ intel_power_domains_init_hw(dev_priv, true);
return ret;
}
@@ -1051,15 +1068,6 @@ static int i915_pm_resume(struct device *dev)
return i915_drm_resume(drm_dev);
}
-static int skl_suspend_complete(struct drm_i915_private *dev_priv)
-{
- /* Enabling DC6 is not a hard requirement to enter runtime D3 */
-
- skl_uninit_cdclk(dev_priv);
-
- return 0;
-}
-
static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
{
hsw_enable_pc8(dev_priv);
@@ -1099,16 +1107,6 @@ static int bxt_resume_prepare(struct drm_i915_private *dev_priv)
return 0;
}
-static int skl_resume_prepare(struct drm_i915_private *dev_priv)
-{
- struct drm_device *dev = dev_priv->dev;
-
- skl_init_cdclk(dev_priv);
- intel_csr_load_program(dev);
-
- return 0;
-}
-
/*
* Save all Gunit registers that may be lost after a D3 and a subsequent
* S0i[R123] transition. The list of registers needing a save/restore is
@@ -1572,8 +1570,6 @@ static int intel_runtime_resume(struct device *device)
if (IS_BROXTON(dev))
ret = bxt_resume_prepare(dev_priv);
- else if (IS_SKYLAKE(dev))
- ret = skl_resume_prepare(dev_priv);
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
hsw_disable_pc8(dev_priv);
else if (IS_VALLEYVIEW(dev_priv))
@@ -1616,8 +1612,6 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
if (IS_BROXTON(dev_priv))
ret = bxt_suspend_complete(dev_priv);
- else if (IS_SKYLAKE(dev_priv))
- ret = skl_suspend_complete(dev_priv);
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
ret = hsw_suspend_complete(dev_priv);
else if (IS_VALLEYVIEW(dev_priv))
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f4af19a0d569..e6ab4655eb23 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -57,7 +57,7 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
-#define DRIVER_DATE "20151010"
+#define DRIVER_DATE "20151120"
#undef WARN_ON
/* Many gcc seem to no see through this and fall over :( */
@@ -180,15 +180,11 @@ enum intel_display_power_domain {
POWER_DOMAIN_TRANSCODER_B,
POWER_DOMAIN_TRANSCODER_C,
POWER_DOMAIN_TRANSCODER_EDP,
- POWER_DOMAIN_PORT_DDI_A_2_LANES,
- POWER_DOMAIN_PORT_DDI_A_4_LANES,
- POWER_DOMAIN_PORT_DDI_B_2_LANES,
- POWER_DOMAIN_PORT_DDI_B_4_LANES,
- POWER_DOMAIN_PORT_DDI_C_2_LANES,
- POWER_DOMAIN_PORT_DDI_C_4_LANES,
- POWER_DOMAIN_PORT_DDI_D_2_LANES,
- POWER_DOMAIN_PORT_DDI_D_4_LANES,
- POWER_DOMAIN_PORT_DDI_E_2_LANES,
+ POWER_DOMAIN_PORT_DDI_A_LANES,
+ POWER_DOMAIN_PORT_DDI_B_LANES,
+ POWER_DOMAIN_PORT_DDI_C_LANES,
+ POWER_DOMAIN_PORT_DDI_D_LANES,
+ POWER_DOMAIN_PORT_DDI_E_LANES,
POWER_DOMAIN_PORT_DSI,
POWER_DOMAIN_PORT_CRT,
POWER_DOMAIN_PORT_OTHER,
@@ -200,6 +196,7 @@ enum intel_display_power_domain {
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_AUX_D,
POWER_DOMAIN_GMBUS,
+ POWER_DOMAIN_MODESET,
POWER_DOMAIN_INIT,
POWER_DOMAIN_NUM,
@@ -289,7 +286,7 @@ struct i915_hotplug {
list_for_each_entry(intel_plane, \
&(dev)->mode_config.plane_list, \
base.head) \
- if ((intel_plane)->pipe == (intel_crtc)->pipe)
+ for_each_if ((intel_plane)->pipe == (intel_crtc)->pipe)
#define for_each_intel_crtc(dev, intel_crtc) \
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
@@ -306,15 +303,15 @@ struct i915_hotplug {
#define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
- if ((intel_encoder)->base.crtc == (__crtc))
+ for_each_if ((intel_encoder)->base.crtc == (__crtc))
#define for_each_connector_on_encoder(dev, __encoder, intel_connector) \
list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
- if ((intel_connector)->base.encoder == (__encoder))
+ for_each_if ((intel_connector)->base.encoder == (__encoder))
#define for_each_power_domain(domain, mask) \
for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
- if ((1 << (domain)) & (mask))
+ for_each_if ((1 << (domain)) & (mask))
struct drm_i915_private;
struct i915_mm_struct;
@@ -631,11 +628,9 @@ struct drm_i915_display_funcs {
int target, int refclk,
struct dpll *match_clock,
struct dpll *best_clock);
+ int (*compute_pipe_wm)(struct intel_crtc *crtc,
+ struct drm_atomic_state *state);
void (*update_wm)(struct drm_crtc *crtc);
- void (*update_sprite_wm)(struct drm_plane *plane,
- struct drm_crtc *crtc,
- uint32_t sprite_width, uint32_t sprite_height,
- int pixel_size, bool enable, bool scaled);
int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
/* Returns the active state of the crtc, and if the crtc is active,
@@ -693,18 +688,18 @@ struct intel_uncore_funcs {
void (*force_wake_put)(struct drm_i915_private *dev_priv,
enum forcewake_domains domains);
- uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
- uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
- uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
- uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
+ uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
+ uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
+ uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
+ uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
- void (*mmio_writeb)(struct drm_i915_private *dev_priv, off_t offset,
+ void (*mmio_writeb)(struct drm_i915_private *dev_priv, i915_reg_t r,
uint8_t val, bool trace);
- void (*mmio_writew)(struct drm_i915_private *dev_priv, off_t offset,
+ void (*mmio_writew)(struct drm_i915_private *dev_priv, i915_reg_t r,
uint16_t val, bool trace);
- void (*mmio_writel)(struct drm_i915_private *dev_priv, off_t offset,
+ void (*mmio_writel)(struct drm_i915_private *dev_priv, i915_reg_t r,
uint32_t val, bool trace);
- void (*mmio_writeq)(struct drm_i915_private *dev_priv, off_t offset,
+ void (*mmio_writeq)(struct drm_i915_private *dev_priv, i915_reg_t r,
uint64_t val, bool trace);
};
@@ -721,11 +716,11 @@ struct intel_uncore {
enum forcewake_domain_id id;
unsigned wake_count;
struct timer_list timer;
- u32 reg_set;
+ i915_reg_t reg_set;
u32 val_set;
u32 val_clear;
- u32 reg_ack;
- u32 reg_post;
+ i915_reg_t reg_ack;
+ i915_reg_t reg_post;
u32 val_reset;
} fw_domain[FW_DOMAIN_ID_COUNT];
};
@@ -735,25 +730,24 @@ struct intel_uncore {
for ((i__) = 0, (domain__) = &(dev_priv__)->uncore.fw_domain[0]; \
(i__) < FW_DOMAIN_ID_COUNT; \
(i__)++, (domain__) = &(dev_priv__)->uncore.fw_domain[i__]) \
- if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
+ for_each_if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
#define for_each_fw_domain(domain__, dev_priv__, i__) \
for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
-enum csr_state {
- FW_UNINITIALIZED = 0,
- FW_LOADED,
- FW_FAILED
-};
+#define CSR_VERSION(major, minor) ((major) << 16 | (minor))
+#define CSR_VERSION_MAJOR(version) ((version) >> 16)
+#define CSR_VERSION_MINOR(version) ((version) & 0xffff)
struct intel_csr {
+ struct work_struct work;
const char *fw_path;
uint32_t *dmc_payload;
uint32_t dmc_fw_size;
+ uint32_t version;
uint32_t mmio_count;
- uint32_t mmioaddr[8];
+ i915_reg_t mmioaddr[8];
uint32_t mmiodata[8];
- enum csr_state state;
};
#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
@@ -771,6 +765,8 @@ struct intel_csr {
func(is_valleyview) sep \
func(is_haswell) sep \
func(is_skylake) sep \
+ func(is_broxton) sep \
+ func(is_kabylake) sep \
func(is_preliminary) sep \
func(has_fbc) sep \
func(has_pipe_cxsr) sep \
@@ -929,24 +925,7 @@ struct i915_fbc {
struct drm_framebuffer *fb;
} *fbc_work;
- enum no_fbc_reason {
- FBC_OK, /* FBC is enabled */
- FBC_UNSUPPORTED, /* FBC is not supported by this chipset */
- FBC_NO_OUTPUT, /* no outputs enabled to compress */
- FBC_STOLEN_TOO_SMALL, /* not enough space for buffers */
- FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
- FBC_MODE_TOO_LARGE, /* mode too large for compression */
- FBC_BAD_PLANE, /* fbc not supported on plane */
- FBC_NOT_TILED, /* buffer not tiled */
- FBC_MULTIPLE_PIPES, /* more than one pipe active */
- FBC_MODULE_PARAM,
- FBC_CHIP_DEFAULT, /* disabled by default on this chip */
- FBC_ROTATION, /* rotation is not supported */
- FBC_IN_DBG_MASTER, /* kernel debugger is active */
- FBC_BAD_STRIDE, /* stride is not supported */
- FBC_PIXEL_RATE, /* pixel rate is too big */
- FBC_PIXEL_FORMAT /* pixel format is invalid */
- } no_fbc_reason;
+ const char *no_fbc_reason;
bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
void (*enable_fbc)(struct intel_crtc *crtc);
@@ -1020,7 +999,7 @@ struct intel_gmbus {
struct i2c_adapter adapter;
u32 force_bit;
u32 reg0;
- u32 gpio_reg;
+ i915_reg_t gpio_reg;
struct i2c_algo_bit_data bit_algo;
struct drm_i915_private *dev_priv;
};
@@ -1669,7 +1648,7 @@ struct i915_frontbuffer_tracking {
};
struct i915_wa_reg {
- u32 addr;
+ i915_reg_t addr;
u32 value;
/* bitmask representing WA bits */
u32 mask;
@@ -1698,6 +1677,13 @@ struct i915_execbuffer_params {
struct drm_i915_gem_request *request;
};
+/* used in computing the new watermarks state */
+struct intel_wm_config {
+ unsigned int num_pipes_active;
+ bool sprites_enabled;
+ bool sprites_scaled;
+};
+
struct drm_i915_private {
struct drm_device *dev;
struct kmem_cache *objects;
@@ -1718,9 +1704,6 @@ struct drm_i915_private {
struct intel_csr csr;
- /* Display CSR-related protection */
- struct mutex csr_lock;
-
struct intel_gmbus gmbus[GMBUS_NUM_PINS];
/** gmbus_mutex protects against concurrent usage of the single hw gmbus
@@ -1735,6 +1718,8 @@ struct drm_i915_private {
/* MMIO base address for MIPI regs */
uint32_t mipi_mmio_base;
+ uint32_t psr_mmio_base;
+
wait_queue_head_t gmbus_wait_queue;
struct pci_dev *bridge_dev;
@@ -1922,6 +1907,9 @@ struct drm_i915_private {
*/
uint16_t skl_latency[8];
+ /* Committed wm config */
+ struct intel_wm_config config;
+
/*
* The skl_wm_values structure is a bit too big for stack
* allocation, so we keep the staging struct where we store
@@ -1956,6 +1944,8 @@ struct drm_i915_private {
/* perform PHY state sanity checks? */
bool chv_phy_assert[2];
+ struct intel_encoder *dig_port_map[I915_MAX_PORTS];
+
/*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
* will be rejected. Instead look for a better place.
@@ -1980,7 +1970,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
/* Iterate over initialised rings */
#define for_each_ring(ring__, dev_priv__, i__) \
for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
- if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
+ for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
enum hdmi_force_audio {
HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */
@@ -2445,6 +2435,15 @@ struct drm_i915_cmd_table {
#define INTEL_DEVID(p) (INTEL_INFO(p)->device_id)
#define INTEL_REVID(p) (__I915__(p)->dev->pdev->revision)
+#define REVID_FOREVER 0xff
+/*
+ * Return true if revision is in range [since,until] inclusive.
+ *
+ * Use 0 for open-ended since, and REVID_FOREVER for open-ended until.
+ */
+#define IS_REVID(p, since, until) \
+ (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until))
+
#define IS_I830(dev) (INTEL_DEVID(dev) == 0x3577)
#define IS_845G(dev) (INTEL_DEVID(dev) == 0x2562)
#define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x)
@@ -2471,7 +2470,8 @@ struct drm_i915_cmd_table {
#define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell)
#define IS_BROADWELL(dev) (!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
#define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake)
-#define IS_BROXTON(dev) (!INTEL_INFO(dev)->is_skylake && IS_GEN9(dev))
+#define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton)
+#define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake)
#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
#define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \
(INTEL_DEVID(dev) & 0xFF00) == 0x0C00)
@@ -2506,16 +2506,21 @@ struct drm_i915_cmd_table {
#define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
-#define SKL_REVID_A0 (0x0)
-#define SKL_REVID_B0 (0x1)
-#define SKL_REVID_C0 (0x2)
-#define SKL_REVID_D0 (0x3)
-#define SKL_REVID_E0 (0x4)
-#define SKL_REVID_F0 (0x5)
+#define SKL_REVID_A0 0x0
+#define SKL_REVID_B0 0x1
+#define SKL_REVID_C0 0x2
+#define SKL_REVID_D0 0x3
+#define SKL_REVID_E0 0x4
+#define SKL_REVID_F0 0x5
+
+#define IS_SKL_REVID(p, since, until) (IS_SKYLAKE(p) && IS_REVID(p, since, until))
-#define BXT_REVID_A0 (0x0)
-#define BXT_REVID_B0 (0x3)
-#define BXT_REVID_C0 (0x9)
+#define BXT_REVID_A0 0x0
+#define BXT_REVID_A1 0x1
+#define BXT_REVID_B0 0x3
+#define BXT_REVID_C0 0x9
+
+#define IS_BXT_REVID(p, since, until) (IS_BROXTON(p) && IS_REVID(p, since, until))
/*
* The genX designation typically refers to the render engine, so render
@@ -2587,10 +2592,10 @@ struct drm_i915_cmd_table {
#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev) || \
IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || \
- IS_SKYLAKE(dev))
+ IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
#define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \
IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \
- IS_SKYLAKE(dev))
+ IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
#define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6)
#define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
@@ -2650,6 +2655,7 @@ struct i915_params {
int panel_use_ssc;
int vbt_sdvo_panel_type;
int enable_rc6;
+ int enable_dc;
int enable_fbc;
int enable_ppgtt;
int enable_execlists;
@@ -2698,7 +2704,6 @@ extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
-void i915_firmware_load_error_print(const char *fw_path, int err);
/* intel_hotplug.c */
void intel_hpd_irq_handler(struct drm_device *dev, u32 pin_mask, u32 long_mask);
@@ -3008,8 +3013,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write);
int __must_check
i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
u32 alignment,
- struct intel_engine_cs *pipelined,
- struct drm_i915_gem_request **pipelined_request,
const struct i915_ggtt_view *view);
void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj,
const struct i915_ggtt_view *view);
@@ -3364,7 +3367,6 @@ extern void intel_set_rps(struct drm_device *dev, u8 val);
extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
bool enable);
extern void intel_detect_pch(struct drm_device *dev);
-extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
extern int intel_enable_rc6(const struct drm_device *dev);
extern bool i915_semaphore_is_enabled(struct drm_device *dev);
@@ -3447,6 +3449,32 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
#define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg)
#define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg)
+#define __raw_read(x, s) \
+static inline uint##x##_t __raw_i915_read##x(struct drm_i915_private *dev_priv, \
+ i915_reg_t reg) \
+{ \
+ return read##s(dev_priv->regs + i915_mmio_reg_offset(reg)); \
+}
+
+#define __raw_write(x, s) \
+static inline void __raw_i915_write##x(struct drm_i915_private *dev_priv, \
+ i915_reg_t reg, uint##x##_t val) \
+{ \
+ write##s(val, dev_priv->regs + i915_mmio_reg_offset(reg)); \
+}
+__raw_read(8, b)
+__raw_read(16, w)
+__raw_read(32, l)
+__raw_read(64, q)
+
+__raw_write(8, b)
+__raw_write(16, w)
+__raw_write(32, l)
+__raw_write(64, q)
+
+#undef __raw_read
+#undef __raw_write
+
/* These are untraced mmio-accessors that are only valid to be used inside
* criticial sections inside IRQ handlers where forcewake is explicitly
* controlled.
@@ -3454,8 +3482,8 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
* Note: Should only be used between intel_uncore_forcewake_irqlock() and
* intel_uncore_forcewake_irqunlock().
*/
-#define I915_READ_FW(reg__) readl(dev_priv->regs + (reg__))
-#define I915_WRITE_FW(reg__, val__) writel(val__, dev_priv->regs + (reg__))
+#define I915_READ_FW(reg__) __raw_i915_read32(dev_priv, (reg__))
+#define I915_WRITE_FW(reg__, val__) __raw_i915_write32(dev_priv, (reg__), (val__))
#define POSTING_READ_FW(reg__) (void)I915_READ_FW(reg__)
/* "Broadcast RGB" property */
@@ -3463,7 +3491,7 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
#define INTEL_BROADCAST_RGB_FULL 1
#define INTEL_BROADCAST_RGB_LIMITED 2
-static inline uint32_t i915_vgacntrl_reg(struct drm_device *dev)
+static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev)
{
if (IS_VALLEYVIEW(dev))
return VLV_VGACNTRL;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index f56af0aaafde..262020f8b38d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2797,6 +2797,8 @@ static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
struct intel_engine_cs *ring)
{
+ struct intel_ringbuffer *buffer;
+
while (!list_empty(&ring->active_list)) {
struct drm_i915_gem_object *obj;
@@ -2812,18 +2814,23 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
* are the ones that keep the context and ringbuffer backing objects
* pinned in place.
*/
- while (!list_empty(&ring->execlist_queue)) {
- struct drm_i915_gem_request *submit_req;
- submit_req = list_first_entry(&ring->execlist_queue,
- struct drm_i915_gem_request,
- execlist_link);
- list_del(&submit_req->execlist_link);
+ if (i915.enable_execlists) {
+ spin_lock_irq(&ring->execlist_lock);
+ while (!list_empty(&ring->execlist_queue)) {
+ struct drm_i915_gem_request *submit_req;
+
+ submit_req = list_first_entry(&ring->execlist_queue,
+ struct drm_i915_gem_request,
+ execlist_link);
+ list_del(&submit_req->execlist_link);
- if (submit_req->ctx != ring->default_context)
- intel_lr_context_unpin(submit_req);
+ if (submit_req->ctx != ring->default_context)
+ intel_lr_context_unpin(submit_req);
- i915_gem_request_unreference(submit_req);
+ i915_gem_request_unreference(submit_req);
+ }
+ spin_unlock_irq(&ring->execlist_lock);
}
/*
@@ -2842,6 +2849,18 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
i915_gem_request_retire(request);
}
+
+ /* Having flushed all requests from all queues, we know that all
+ * ringbuffers must now be empty. However, since we do not reclaim
+ * all space when retiring the request (to prevent HEADs colliding
+ * with rapid ringbuffer wraparound) the amount of available space
+ * upon reset is less than when we start. Do one more pass over
+ * all the ringbuffers to reset last_retired_head.
+ */
+ list_for_each_entry(buffer, &ring->buffers, link) {
+ buffer->last_retired_head = buffer->tail;
+ intel_ring_update_space(buffer);
+ }
}
void i915_gem_reset(struct drm_device *dev)
@@ -3886,7 +3905,7 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
* cacheline, whereas normally such cachelines would get
* invalidated.
*/
- if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
return -ENODEV;
level = I915_CACHE_LLC;
@@ -3929,17 +3948,11 @@ rpm_put:
int
i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
u32 alignment,
- struct intel_engine_cs *pipelined,
- struct drm_i915_gem_request **pipelined_request,
const struct i915_ggtt_view *view)
{
u32 old_read_domains, old_write_domain;
int ret;
- ret = i915_gem_object_sync(obj, pipelined, pipelined_request);
- if (ret)
- return ret;
-
/* Mark the pin_display early so that we account for the
* display coherency whilst setting up the cache domains.
*/
@@ -4541,10 +4554,8 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
{
struct i915_vma *vma;
list_for_each_entry(vma, &obj->vma_list, vma_link) {
- if (i915_is_ggtt(vma->vm) &&
- vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL)
- continue;
- if (vma->vm == vm)
+ if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL &&
+ vma->vm == vm)
return vma;
}
return NULL;
@@ -4633,7 +4644,6 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice)
struct intel_engine_cs *ring = req->ring;
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 reg_base = GEN7_L3LOG_BASE + (slice * 0x200);
u32 *remap_info = dev_priv->l3_parity.remap_info[slice];
int i, ret;
@@ -4649,10 +4659,10 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice)
* here because no other code should access these registers other than
* at initialization time.
*/
- for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) {
+ for (i = 0; i < GEN7_L3LOG_SIZE / 4; i++) {
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, reg_base + i);
- intel_ring_emit(ring, remap_info[i/4]);
+ intel_ring_emit_reg(ring, GEN7_L3LOG(slice, i));
+ intel_ring_emit(ring, remap_info[i]);
}
intel_ring_advance(ring);
@@ -4820,18 +4830,9 @@ i915_gem_init_hw(struct drm_device *dev)
if (HAS_GUC_UCODE(dev)) {
ret = intel_guc_ucode_load(dev);
if (ret) {
- /*
- * If we got an error and GuC submission is enabled, map
- * the error to -EIO so the GPU will be declared wedged.
- * OTOH, if we didn't intend to use the GuC anyway, just
- * discard the error and carry on.
- */
- DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret,
- i915.enable_guc_submission ? "" :
- " (ignored)");
- ret = i915.enable_guc_submission ? -EIO : 0;
- if (ret)
- goto out;
+ DRM_ERROR("Failed to initialize GuC, error %d\n", ret);
+ ret = -EIO;
+ goto out;
}
}
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 02ceb7a4b481..43761c5bcaca 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -554,7 +554,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
if (signaller == ring)
continue;
- intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base));
+ intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base));
intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
}
}
@@ -579,7 +579,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
if (signaller == ring)
continue;
- intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base));
+ intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base));
intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
}
}
@@ -923,6 +923,14 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
case I915_CONTEXT_PARAM_NO_ZEROMAP:
args->value = ctx->flags & CONTEXT_NO_ZEROMAP;
break;
+ case I915_CONTEXT_PARAM_GTT_SIZE:
+ if (ctx->ppgtt)
+ args->value = ctx->ppgtt->base.total;
+ else if (to_i915(dev)->mm.aliasing_ppgtt)
+ args->value = to_i915(dev)->mm.aliasing_ppgtt->base.total;
+ else
+ args->value = to_i915(dev)->gtt.base.total;
+ break;
default:
ret = -EINVAL;
break;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 6ed7d63a0688..a4c243cec4aa 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1114,7 +1114,7 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,
for (i = 0; i < 4; i++) {
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, GEN7_SO_WRITE_OFFSET(i));
+ intel_ring_emit_reg(ring, GEN7_SO_WRITE_OFFSET(i));
intel_ring_emit(ring, 0);
}
@@ -1241,7 +1241,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, INSTPM);
+ intel_ring_emit_reg(ring, INSTPM);
intel_ring_emit(ring, instp_mask << 16 | instp_mode);
intel_ring_advance(ring);
diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c
index f010391b87f5..598198543dcd 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence.c
@@ -59,7 +59,7 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
struct drm_i915_gem_object *obj)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- int fence_reg_lo, fence_reg_hi;
+ i915_reg_t fence_reg_lo, fence_reg_hi;
int fence_pitch_shift;
if (INTEL_INFO(dev)->gen >= 6) {
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 86c7500454b4..f4cd01df40db 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -24,6 +24,7 @@
*/
#include <linux/seq_file.h>
+#include <linux/stop_machine.h>
#include <drm/drmP.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
@@ -104,9 +105,11 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
{
bool has_aliasing_ppgtt;
bool has_full_ppgtt;
+ bool has_full_48bit_ppgtt;
has_aliasing_ppgtt = INTEL_INFO(dev)->gen >= 6;
has_full_ppgtt = INTEL_INFO(dev)->gen >= 7;
+ has_full_48bit_ppgtt = IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9;
if (intel_vgpu_active(dev))
has_full_ppgtt = false; /* emulation is too hard */
@@ -125,6 +128,9 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
if (enable_ppgtt == 2 && has_full_ppgtt)
return 2;
+ if (enable_ppgtt == 3 && has_full_48bit_ppgtt)
+ return 3;
+
#ifdef CONFIG_INTEL_IOMMU
/* Disable ppgtt on SNB if VT-d is on. */
if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) {
@@ -141,7 +147,7 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
}
if (INTEL_INFO(dev)->gen >= 8 && i915.enable_execlists)
- return 2;
+ return has_full_48bit_ppgtt ? 3 : 2;
else
return has_aliasing_ppgtt ? 1 : 0;
}
@@ -661,10 +667,10 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req,
return ret;
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, GEN8_RING_PDP_UDW(ring, entry));
+ intel_ring_emit_reg(ring, GEN8_RING_PDP_UDW(ring, entry));
intel_ring_emit(ring, upper_32_bits(addr));
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, GEN8_RING_PDP_LDW(ring, entry));
+ intel_ring_emit_reg(ring, GEN8_RING_PDP_LDW(ring, entry));
intel_ring_emit(ring, lower_32_bits(addr));
intel_ring_advance(ring);
@@ -904,14 +910,13 @@ static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
enum vgt_g2v_type msg;
struct drm_device *dev = ppgtt->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- unsigned int offset = vgtif_reg(pdp0_lo);
int i;
if (USES_FULL_48BIT_PPGTT(dev)) {
u64 daddr = px_dma(&ppgtt->pml4);
- I915_WRITE(offset, lower_32_bits(daddr));
- I915_WRITE(offset + 4, upper_32_bits(daddr));
+ I915_WRITE(vgtif_reg(pdp[0].lo), lower_32_bits(daddr));
+ I915_WRITE(vgtif_reg(pdp[0].hi), upper_32_bits(daddr));
msg = (create ? VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE :
VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY);
@@ -919,10 +924,8 @@ static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
for (i = 0; i < GEN8_LEGACY_PDPES; i++) {
u64 daddr = i915_page_dir_dma_addr(ppgtt, i);
- I915_WRITE(offset, lower_32_bits(daddr));
- I915_WRITE(offset + 4, upper_32_bits(daddr));
-
- offset += 8;
+ I915_WRITE(vgtif_reg(pdp[i].lo), lower_32_bits(daddr));
+ I915_WRITE(vgtif_reg(pdp[i].hi), upper_32_bits(daddr));
}
msg = (create ? VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE :
@@ -1662,9 +1665,9 @@ static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
return ret;
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
- intel_ring_emit(ring, RING_PP_DIR_DCLV(ring));
+ intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring));
intel_ring_emit(ring, PP_DIR_DCLV_2G);
- intel_ring_emit(ring, RING_PP_DIR_BASE(ring));
+ intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring));
intel_ring_emit(ring, get_pd_offset(ppgtt));
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
@@ -1699,9 +1702,9 @@ static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
return ret;
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
- intel_ring_emit(ring, RING_PP_DIR_DCLV(ring));
+ intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring));
intel_ring_emit(ring, PP_DIR_DCLV_2G);
- intel_ring_emit(ring, RING_PP_DIR_BASE(ring));
+ intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring));
intel_ring_emit(ring, get_pd_offset(ppgtt));
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
@@ -2528,6 +2531,26 @@ static int ggtt_bind_vma(struct i915_vma *vma,
return 0;
}
+struct ggtt_bind_vma__cb {
+ struct i915_vma *vma;
+ enum i915_cache_level cache_level;
+ u32 flags;
+};
+
+static int ggtt_bind_vma__cb(void *_arg)
+{
+ struct ggtt_bind_vma__cb *arg = _arg;
+ return ggtt_bind_vma(arg->vma, arg->cache_level, arg->flags);
+}
+
+static int ggtt_bind_vma__BKL(struct i915_vma *vma,
+ enum i915_cache_level cache_level,
+ u32 flags)
+{
+ struct ggtt_bind_vma__cb arg = { vma, cache_level, flags };
+ return stop_machine(ggtt_bind_vma__cb, &arg, NULL);
+}
+
static int aliasing_gtt_bind_vma(struct i915_vma *vma,
enum i915_cache_level cache_level,
u32 flags)
@@ -2996,6 +3019,9 @@ static int gen8_gmch_probe(struct drm_device *dev,
dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
+ if (IS_CHERRYVIEW(dev))
+ dev_priv->gtt.base.bind_vma = ggtt_bind_vma__BKL;
+
return ret;
}
@@ -3303,7 +3329,7 @@ static struct sg_table *
intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
struct drm_i915_gem_object *obj)
{
- struct intel_rotation_info *rot_info = &ggtt_view->rotation_info;
+ struct intel_rotation_info *rot_info = &ggtt_view->params.rotation_info;
unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
unsigned int size_pages_uv;
struct sg_page_iter sg_iter;
@@ -3535,7 +3561,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
if (view->type == I915_GGTT_VIEW_NORMAL) {
return obj->base.size;
} else if (view->type == I915_GGTT_VIEW_ROTATED) {
- return view->rotation_info.size;
+ return view->params.rotation_info.size;
} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
return view->params.partial.size << PAGE_SHIFT;
} else {
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index a216397ead52..877c32c78a6a 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -156,13 +156,10 @@ struct i915_ggtt_view {
u64 offset;
unsigned int size;
} partial;
+ struct intel_rotation_info rotation_info;
} params;
struct sg_table *pages;
-
- union {
- struct intel_rotation_info rotation_info;
- };
};
extern const struct i915_ggtt_view i915_ggtt_view_normal;
@@ -556,7 +553,7 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
if (a->type != b->type)
return false;
- if (a->type == I915_GGTT_VIEW_PARTIAL)
+ if (a->type != I915_GGTT_VIEW_NORMAL)
return !memcmp(&a->params, &b->params, sizeof(a->params));
return true;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 87e919a06b27..3476877fc0d6 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -433,7 +433,8 @@ int i915_gem_init_stolen(struct drm_device *dev)
&reserved_size);
break;
default:
- if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
+ if (IS_BROADWELL(dev_priv) ||
+ IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev))
bdw_get_stolen_reserved(dev_priv, &reserved_base,
&reserved_size);
else
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 8a6717cc265c..7410f6c962e7 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -176,6 +176,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
return -EINVAL;
}
+ intel_runtime_pm_get(dev_priv);
+
mutex_lock(&dev->struct_mutex);
if (obj->pin_display || obj->framebuffer_references) {
ret = -EBUSY;
@@ -269,6 +271,8 @@ err:
drm_gem_object_unreference(&obj->base);
mutex_unlock(&dev->struct_mutex);
+ intel_runtime_pm_put(dev_priv);
+
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 2f04e4f2ff35..06ca4082735b 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -366,6 +366,17 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
err_printf(m, "Suspend count: %u\n", error->suspend_count);
err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device);
err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
+
+ if (HAS_CSR(dev)) {
+ struct intel_csr *csr = &dev_priv->csr;
+
+ err_printf(m, "DMC loaded: %s\n",
+ yesno(csr->dmc_payload != NULL));
+ err_printf(m, "DMC fw version: %d.%d\n",
+ CSR_VERSION_MAJOR(csr->version),
+ CSR_VERSION_MINOR(csr->version));
+ }
+
err_printf(m, "EIR: 0x%08x\n", error->eir);
err_printf(m, "IER: 0x%08x\n", error->ier);
if (INTEL_INFO(dev)->gen >= 8) {
@@ -862,7 +873,7 @@ static void i915_record_ring_state(struct drm_device *dev,
struct drm_i915_private *dev_priv = dev->dev_private;
if (INTEL_INFO(dev)->gen >= 6) {
- ering->rc_psmi = I915_READ(ring->mmio_base + 0x50);
+ ering->rc_psmi = I915_READ(RING_PSMI_CTL(ring->mmio_base));
ering->fault_reg = I915_READ(RING_FAULT_REG(ring));
if (INTEL_INFO(dev)->gen >= 8)
gen8_record_semaphore_state(dev_priv, error, ring, ering);
@@ -899,7 +910,7 @@ static void i915_record_ring_state(struct drm_device *dev,
ering->ctl = I915_READ_CTL(ring);
if (I915_NEED_GFX_HWS(dev)) {
- int mmio;
+ i915_reg_t mmio;
if (IS_GEN7(dev)) {
switch (ring->id) {
@@ -1071,6 +1082,25 @@ static void i915_gem_record_rings(struct drm_device *dev,
list_for_each_entry(request, &ring->request_list, list) {
struct drm_i915_error_request *erq;
+ if (count >= error->ring[i].num_requests) {
+ /*
+ * If the ring request list was changed in
+ * between the point where the error request
+ * list was created and dimensioned and this
+ * point then just exit early to avoid crashes.
+ *
+ * We don't need to communicate that the
+ * request list changed state during error
+ * state capture and that the error state is
+ * slightly incorrect as a consequence since we
+ * are typically only interested in the request
+ * list state at the point of error state
+ * capture, not in any changes happening during
+ * the capture.
+ */
+ break;
+ }
+
erq = &error->ring[i].requests[count++];
erq->seqno = request->seqno;
erq->jiffies = request->emitted_jiffies;
@@ -1181,7 +1211,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
if (IS_VALLEYVIEW(dev)) {
error->gtier[0] = I915_READ(GTIER);
error->ier = I915_READ(VLV_IER);
- error->forcewake = I915_READ(FORCEWAKE_VLV);
+ error->forcewake = I915_READ_FW(FORCEWAKE_VLV);
}
if (IS_GEN7(dev))
@@ -1193,14 +1223,14 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
}
if (IS_GEN6(dev)) {
- error->forcewake = I915_READ(FORCEWAKE);
+ error->forcewake = I915_READ_FW(FORCEWAKE);
error->gab_ctl = I915_READ(GAB_CTL);
error->gfx_mode = I915_READ(GFX_MODE);
}
/* 2: Registers which belong to multiple generations */
if (INTEL_INFO(dev)->gen >= 7)
- error->forcewake = I915_READ(FORCEWAKE_MT);
+ error->forcewake = I915_READ_FW(FORCEWAKE_MT);
if (INTEL_INFO(dev)->gen >= 6) {
error->derrmr = I915_READ(DERRMR);
diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h
index c4cb1c0c4d0d..685c7991e24f 100644
--- a/drivers/gpu/drm/i915/i915_guc_reg.h
+++ b/drivers/gpu/drm/i915/i915_guc_reg.h
@@ -26,7 +26,7 @@
/* Definitions of GuC H/W registers, bits, etc */
-#define GUC_STATUS 0xc000
+#define GUC_STATUS _MMIO(0xc000)
#define GS_BOOTROM_SHIFT 1
#define GS_BOOTROM_MASK (0x7F << GS_BOOTROM_SHIFT)
#define GS_BOOTROM_RSA_FAILED (0x50 << GS_BOOTROM_SHIFT)
@@ -39,40 +39,41 @@
#define GS_MIA_MASK (0x07 << GS_MIA_SHIFT)
#define GS_MIA_CORE_STATE (1 << GS_MIA_SHIFT)
-#define SOFT_SCRATCH(n) (0xc180 + ((n) * 4))
+#define SOFT_SCRATCH(n) _MMIO(0xc180 + (n) * 4)
-#define UOS_RSA_SCRATCH(i) (0xc200 + (i) * 4)
-#define DMA_ADDR_0_LOW 0xc300
-#define DMA_ADDR_0_HIGH 0xc304
-#define DMA_ADDR_1_LOW 0xc308
-#define DMA_ADDR_1_HIGH 0xc30c
+#define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4)
+#define UOS_RSA_SCRATCH_MAX_COUNT 64
+#define DMA_ADDR_0_LOW _MMIO(0xc300)
+#define DMA_ADDR_0_HIGH _MMIO(0xc304)
+#define DMA_ADDR_1_LOW _MMIO(0xc308)
+#define DMA_ADDR_1_HIGH _MMIO(0xc30c)
#define DMA_ADDRESS_SPACE_WOPCM (7 << 16)
#define DMA_ADDRESS_SPACE_GTT (8 << 16)
-#define DMA_COPY_SIZE 0xc310
-#define DMA_CTRL 0xc314
+#define DMA_COPY_SIZE _MMIO(0xc310)
+#define DMA_CTRL _MMIO(0xc314)
#define UOS_MOVE (1<<4)
#define START_DMA (1<<0)
-#define DMA_GUC_WOPCM_OFFSET 0xc340
+#define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340)
#define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */
-#define GUC_MAX_IDLE_COUNT 0xC3E4
+#define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4)
-#define GUC_WOPCM_SIZE 0xc050
+#define GUC_WOPCM_SIZE _MMIO(0xc050)
#define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */
/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */
#define GUC_WOPCM_TOP (GUC_WOPCM_SIZE_VALUE)
-#define GEN8_GT_PM_CONFIG 0x138140
-#define GEN9LP_GT_PM_CONFIG 0x138140
-#define GEN9_GT_PM_CONFIG 0x13816c
+#define GEN8_GT_PM_CONFIG _MMIO(0x138140)
+#define GEN9LP_GT_PM_CONFIG _MMIO(0x138140)
+#define GEN9_GT_PM_CONFIG _MMIO(0x13816c)
#define GT_DOORBELL_ENABLE (1<<0)
-#define GEN8_GTCR 0x4274
+#define GEN8_GTCR _MMIO(0x4274)
#define GEN8_GTCR_INVALIDATE (1<<0)
-#define GUC_ARAT_C6DIS 0xA178
+#define GUC_ARAT_C6DIS _MMIO(0xA178)
-#define GUC_SHIM_CONTROL 0xc064
+#define GUC_SHIM_CONTROL _MMIO(0xc064)
#define GUC_DISABLE_SRAM_INIT_TO_ZEROES (1<<0)
#define GUC_ENABLE_READ_CACHE_LOGIC (1<<1)
#define GUC_ENABLE_MIA_CACHING (1<<2)
@@ -89,21 +90,21 @@
GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | \
GUC_ENABLE_MIA_CLOCK_GATING)
-#define HOST2GUC_INTERRUPT 0xc4c8
+#define HOST2GUC_INTERRUPT _MMIO(0xc4c8)
#define HOST2GUC_TRIGGER (1<<0)
#define DRBMISC1 0x1984
#define DOORBELL_ENABLE (1<<0)
-#define GEN8_DRBREGL(x) (0x1000 + (x) * 8)
+#define GEN8_DRBREGL(x) _MMIO(0x1000 + (x) * 8)
#define GEN8_DRB_VALID (1<<0)
-#define GEN8_DRBREGU(x) (GEN8_DRBREGL(x) + 4)
+#define GEN8_DRBREGU(x) _MMIO(0x1000 + (x) * 8 + 4)
-#define DE_GUCRMR 0x44054
+#define DE_GUCRMR _MMIO(0x44054)
-#define GUC_BCS_RCS_IER 0xC550
-#define GUC_VCS2_VCS1_IER 0xC554
-#define GUC_WD_VECS_IER 0xC558
-#define GUC_PM_P24C_IER 0xC55C
+#define GUC_BCS_RCS_IER _MMIO(0xC550)
+#define GUC_VCS2_VCS1_IER _MMIO(0xC554)
+#define GUC_WD_VECS_IER _MMIO(0xC558)
+#define GUC_PM_P24C_IER _MMIO(0xC55C)
#endif
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 036b42bae827..ed9f1002ab36 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -27,7 +27,7 @@
#include "intel_guc.h"
/**
- * DOC: GuC Client
+ * DOC: GuC-based command submission
*
* i915_guc_client:
* We use the term client to avoid confusion with contexts. A i915_guc_client is
@@ -161,9 +161,9 @@ static int host2guc_sample_forcewake(struct intel_guc *guc,
data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE;
/* WaRsDisableCoarsePowerGating:skl,bxt */
if (!intel_enable_rc6(dev_priv->dev) ||
- (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) ||
- (IS_SKL_GT3(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0)) ||
- (IS_SKL_GT4(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0)))
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1) ||
+ (IS_SKL_GT3(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0)) ||
+ (IS_SKL_GT4(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0)))
data[1] = 0;
else
/* bit 0 and 1 are for Render and Media domain separately */
@@ -258,7 +258,7 @@ static void guc_disable_doorbell(struct intel_guc *guc,
struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct guc_doorbell_info *doorbell;
void *base;
- int drbreg = GEN8_DRBREGL(client->doorbell_id);
+ i915_reg_t drbreg = GEN8_DRBREGL(client->doorbell_id);
int value;
base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
@@ -588,8 +588,7 @@ static void lr_context_update(struct drm_i915_gem_request *rq)
/**
* i915_guc_submit() - Submit commands through GuC
* @client: the guc client where commands will go through
- * @ctx: LRC where commands come from
- * @ring: HW engine that will excute the commands
+ * @rq: request associated with the commands
*
* Return: 0 if succeed
*/
@@ -731,7 +730,8 @@ static void guc_client_free(struct drm_device *dev,
* The kernel client to replace ExecList submission is created with
* NORMAL priority. Priority of a client for scheduler can be HIGH,
* while a preemption context can use CRITICAL.
- * @ctx the context to own the client (we use the default render context)
+ * @ctx: the context that owns the client (we use the default render
+ * context)
*
* Return: An i915_guc_client object if success.
*/
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 0d228f909dcb..c8ba94968aaf 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -139,7 +139,8 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = {
/*
* We should clear IMR at preinstall/uninstall, and just check at postinstall.
*/
-static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, u32 reg)
+static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv,
+ i915_reg_t reg)
{
u32 val = I915_READ(reg);
@@ -147,7 +148,7 @@ static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, u32 reg)
return;
WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n",
- reg, val);
+ i915_mmio_reg_offset(reg), val);
I915_WRITE(reg, 0xffffffff);
POSTING_READ(reg);
I915_WRITE(reg, 0xffffffff);
@@ -283,17 +284,17 @@ void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
ilk_update_gt_irq(dev_priv, mask, 0);
}
-static u32 gen6_pm_iir(struct drm_i915_private *dev_priv)
+static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv)
{
return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR;
}
-static u32 gen6_pm_imr(struct drm_i915_private *dev_priv)
+static i915_reg_t gen6_pm_imr(struct drm_i915_private *dev_priv)
{
return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IMR(2) : GEN6_PMIMR;
}
-static u32 gen6_pm_ier(struct drm_i915_private *dev_priv)
+static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv)
{
return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IER(2) : GEN6_PMIER;
}
@@ -350,7 +351,7 @@ void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
void gen6_reset_rps_interrupts(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- uint32_t reg = gen6_pm_iir(dev_priv);
+ i915_reg_t reg = gen6_pm_iir(dev_priv);
spin_lock_irq(&dev_priv->irq_lock);
I915_WRITE(reg, dev_priv->pm_rps_events);
@@ -477,7 +478,7 @@ static void
__i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
u32 enable_mask, u32 status_mask)
{
- u32 reg = PIPESTAT(pipe);
+ i915_reg_t reg = PIPESTAT(pipe);
u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
assert_spin_locked(&dev_priv->irq_lock);
@@ -504,7 +505,7 @@ static void
__i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
u32 enable_mask, u32 status_mask)
{
- u32 reg = PIPESTAT(pipe);
+ i915_reg_t reg = PIPESTAT(pipe);
u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
assert_spin_locked(&dev_priv->irq_lock);
@@ -665,8 +666,7 @@ static u32 i8xx_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- unsigned long high_frame;
- unsigned long low_frame;
+ i915_reg_t high_frame, low_frame;
u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal;
struct intel_crtc *intel_crtc =
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
@@ -717,9 +717,7 @@ static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
return I915_READ(PIPE_FRMCOUNT_G4X(pipe));
}
-/* raw reads, only for fast reads of display block, no need for forcewake etc. */
-#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__))
-
+/* I915_READ_FW, only for fast reads of display block, no need for forcewake etc. */
static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
@@ -733,9 +731,9 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
vtotal /= 2;
if (IS_GEN2(dev))
- position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2;
+ position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN2;
else
- position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
+ position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
/*
* On HSW, the DSL reg (0x70000) appears to return 0 if we
@@ -827,7 +825,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
* We can split this into vertical and horizontal
* scanout position.
*/
- position = (__raw_i915_read32(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT;
+ position = (I915_READ_FW(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT;
/* convert to pixel counts */
vbl_start *= htotal;
@@ -1188,7 +1186,7 @@ static void ivybridge_parity_work(struct work_struct *work)
POSTING_READ(GEN7_MISCCPCTL);
while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) {
- u32 reg;
+ i915_reg_t reg;
slice--;
if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv->dev)))
@@ -1196,7 +1194,7 @@ static void ivybridge_parity_work(struct work_struct *work)
dev_priv->l3_parity.which_slice &= ~(1<<slice);
- reg = GEN7_L3CDERRST1 + (slice * 0x200);
+ reg = GEN7_L3CDERRST1(slice);
error_status = I915_READ(reg);
row = GEN7_PARITY_ERROR_ROW(error_status);
@@ -1290,70 +1288,69 @@ static void snb_gt_irq_handler(struct drm_device *dev,
ivybridge_parity_error_irq_handler(dev, gt_iir);
}
+static __always_inline void
+gen8_cs_irq_handler(struct intel_engine_cs *ring, u32 iir, int test_shift)
+{
+ if (iir & (GT_RENDER_USER_INTERRUPT << test_shift))
+ notify_ring(ring);
+ if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift))
+ intel_lrc_irq_handler(ring);
+}
+
static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
u32 master_ctl)
{
irqreturn_t ret = IRQ_NONE;
if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
- u32 tmp = I915_READ_FW(GEN8_GT_IIR(0));
- if (tmp) {
- I915_WRITE_FW(GEN8_GT_IIR(0), tmp);
+ u32 iir = I915_READ_FW(GEN8_GT_IIR(0));
+ if (iir) {
+ I915_WRITE_FW(GEN8_GT_IIR(0), iir);
ret = IRQ_HANDLED;
- if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT))
- intel_lrc_irq_handler(&dev_priv->ring[RCS]);
- if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT))
- notify_ring(&dev_priv->ring[RCS]);
+ gen8_cs_irq_handler(&dev_priv->ring[RCS],
+ iir, GEN8_RCS_IRQ_SHIFT);
- if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT))
- intel_lrc_irq_handler(&dev_priv->ring[BCS]);
- if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT))
- notify_ring(&dev_priv->ring[BCS]);
+ gen8_cs_irq_handler(&dev_priv->ring[BCS],
+ iir, GEN8_BCS_IRQ_SHIFT);
} else
DRM_ERROR("The master control interrupt lied (GT0)!\n");
}
if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
- u32 tmp = I915_READ_FW(GEN8_GT_IIR(1));
- if (tmp) {
- I915_WRITE_FW(GEN8_GT_IIR(1), tmp);
+ u32 iir = I915_READ_FW(GEN8_GT_IIR(1));
+ if (iir) {
+ I915_WRITE_FW(GEN8_GT_IIR(1), iir);
ret = IRQ_HANDLED;
- if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT))
- intel_lrc_irq_handler(&dev_priv->ring[VCS]);
- if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT))
- notify_ring(&dev_priv->ring[VCS]);
+ gen8_cs_irq_handler(&dev_priv->ring[VCS],
+ iir, GEN8_VCS1_IRQ_SHIFT);
- if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT))
- intel_lrc_irq_handler(&dev_priv->ring[VCS2]);
- if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT))
- notify_ring(&dev_priv->ring[VCS2]);
+ gen8_cs_irq_handler(&dev_priv->ring[VCS2],
+ iir, GEN8_VCS2_IRQ_SHIFT);
} else
DRM_ERROR("The master control interrupt lied (GT1)!\n");
}
if (master_ctl & GEN8_GT_VECS_IRQ) {
- u32 tmp = I915_READ_FW(GEN8_GT_IIR(3));
- if (tmp) {
- I915_WRITE_FW(GEN8_GT_IIR(3), tmp);
+ u32 iir = I915_READ_FW(GEN8_GT_IIR(3));
+ if (iir) {
+ I915_WRITE_FW(GEN8_GT_IIR(3), iir);
ret = IRQ_HANDLED;
- if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT))
- intel_lrc_irq_handler(&dev_priv->ring[VECS]);
- if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT))
- notify_ring(&dev_priv->ring[VECS]);
+ gen8_cs_irq_handler(&dev_priv->ring[VECS],
+ iir, GEN8_VECS_IRQ_SHIFT);
} else
DRM_ERROR("The master control interrupt lied (GT3)!\n");
}
if (master_ctl & GEN8_GT_PM_IRQ) {
- u32 tmp = I915_READ_FW(GEN8_GT_IIR(2));
- if (tmp & dev_priv->pm_rps_events) {
+ u32 iir = I915_READ_FW(GEN8_GT_IIR(2));
+ if (iir & dev_priv->pm_rps_events) {
I915_WRITE_FW(GEN8_GT_IIR(2),
- tmp & dev_priv->pm_rps_events);
+ iir & dev_priv->pm_rps_events);
ret = IRQ_HANDLED;
- gen6_rps_irq_handler(dev_priv, tmp);
+ gen6_rps_irq_handler(dev_priv, iir);
} else
DRM_ERROR("The master control interrupt lied (PM)!\n");
}
@@ -1625,7 +1622,7 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
spin_lock(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
- int reg;
+ i915_reg_t reg;
u32 mask, iir_bit = 0;
/*
@@ -2354,9 +2351,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
spt_irq_handler(dev, pch_iir);
else
cpt_irq_handler(dev, pch_iir);
- } else
- DRM_ERROR("The master control interrupt lied (SDE)!\n");
-
+ } else {
+ /*
+ * Like on previous PCH there seems to be something
+ * fishy going on with forwarding PCH interrupts.
+ */
+ DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n");
+ }
}
I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
@@ -3869,7 +3870,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
DRM_DEBUG("Command parser error, iir 0x%08x\n", iir);
for_each_pipe(dev_priv, pipe) {
- int reg = PIPESTAT(pipe);
+ i915_reg_t reg = PIPESTAT(pipe);
pipe_stats[pipe] = I915_READ(reg);
/*
@@ -4050,7 +4051,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
DRM_DEBUG("Command parser error, iir 0x%08x\n", iir);
for_each_pipe(dev_priv, pipe) {
- int reg = PIPESTAT(pipe);
+ i915_reg_t reg = PIPESTAT(pipe);
pipe_stats[pipe] = I915_READ(reg);
/* Clear the PIPE*STAT regs before the IIR */
@@ -4272,7 +4273,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
DRM_DEBUG("Command parser error, iir 0x%08x\n", iir);
for_each_pipe(dev_priv, pipe) {
- int reg = PIPESTAT(pipe);
+ i915_reg_t reg = PIPESTAT(pipe);
pipe_stats[pipe] = I915_READ(reg);
/*
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 4be13a5eb932..835d6099c769 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -32,6 +32,7 @@ struct i915_params i915 __read_mostly = {
.panel_use_ssc = -1,
.vbt_sdvo_panel_type = -1,
.enable_rc6 = -1,
+ .enable_dc = -1,
.enable_fbc = -1,
.enable_execlists = -1,
.enable_hangcheck = true,
@@ -80,6 +81,11 @@ MODULE_PARM_DESC(enable_rc6,
"For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. "
"default: -1 (use per-chip default)");
+module_param_named_unsafe(enable_dc, i915.enable_dc, int, 0400);
+MODULE_PARM_DESC(enable_dc,
+ "Enable power-saving display C-states. "
+ "(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6)");
+
module_param_named_unsafe(enable_fbc, i915.enable_fbc, int, 0600);
MODULE_PARM_DESC(enable_fbc,
"Enable frame buffer compression for power savings "
@@ -112,7 +118,7 @@ MODULE_PARM_DESC(enable_hangcheck,
module_param_named_unsafe(enable_ppgtt, i915.enable_ppgtt, int, 0400);
MODULE_PARM_DESC(enable_ppgtt,
"Override PPGTT usage. "
- "(-1=auto [default], 0=disabled, 1=aliasing, 2=full)");
+ "(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)");
module_param_named_unsafe(enable_execlists, i915.enable_execlists, int, 0400);
MODULE_PARM_DESC(enable_execlists,
@@ -126,7 +132,7 @@ module_param_named_unsafe(preliminary_hw_support, i915.preliminary_hw_support, i
MODULE_PARM_DESC(preliminary_hw_support,
"Enable preliminary hardware support.");
-module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0600);
+module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0400);
MODULE_PARM_DESC(disable_power_well,
"Disable display power wells when possible "
"(-1=auto [default], 0=power wells always on, 1=power wells disabled when possible)");
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index bc7b8faba84d..1a12d44b9710 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -25,14 +25,43 @@
#ifndef _I915_REG_H_
#define _I915_REG_H_
+typedef struct {
+ uint32_t reg;
+} i915_reg_t;
+
+#define _MMIO(r) ((const i915_reg_t){ .reg = (r) })
+
+#define INVALID_MMIO_REG _MMIO(0)
+
+static inline uint32_t i915_mmio_reg_offset(i915_reg_t reg)
+{
+ return reg.reg;
+}
+
+static inline bool i915_mmio_reg_equal(i915_reg_t a, i915_reg_t b)
+{
+ return i915_mmio_reg_offset(a) == i915_mmio_reg_offset(b);
+}
+
+static inline bool i915_mmio_reg_valid(i915_reg_t reg)
+{
+ return !i915_mmio_reg_equal(reg, INVALID_MMIO_REG);
+}
+
#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
+#define _MMIO_PIPE(pipe, a, b) _MMIO(_PIPE(pipe, a, b))
#define _PLANE(plane, a, b) _PIPE(plane, a, b)
-#define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a)))
+#define _MMIO_PLANE(plane, a, b) _MMIO_PIPE(plane, a, b)
+#define _TRANS(tran, a, b) ((a) + (tran)*((b)-(a)))
+#define _MMIO_TRANS(tran, a, b) _MMIO(_TRANS(tran, a, b))
#define _PORT(port, a, b) ((a) + (port)*((b)-(a)))
+#define _MMIO_PORT(port, a, b) _MMIO(_PORT(port, a, b))
#define _PIPE3(pipe, a, b, c) ((pipe) == PIPE_A ? (a) : \
(pipe) == PIPE_B ? (b) : (c))
+#define _MMIO_PIPE3(pipe, a, b, c) _MMIO(_PIPE3(pipe, a, b, c))
#define _PORT3(port, a, b, c) ((port) == PORT_A ? (a) : \
(port) == PORT_B ? (b) : (c))
+#define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PORT3(pipe, a, b, c))
#define _MASKED_FIELD(mask, value) ({ \
if (__builtin_constant_p(mask)) \
@@ -105,14 +134,14 @@
#define GRDOM_RESET_STATUS (1<<1)
#define GRDOM_RESET_ENABLE (1<<0)
-#define ILK_GDSR (MCHBAR_MIRROR_BASE + 0x2ca4)
+#define ILK_GDSR _MMIO(MCHBAR_MIRROR_BASE + 0x2ca4)
#define ILK_GRDOM_FULL (0<<1)
#define ILK_GRDOM_RENDER (1<<1)
#define ILK_GRDOM_MEDIA (3<<1)
#define ILK_GRDOM_MASK (3<<1)
#define ILK_GRDOM_RESET_ENABLE (1<<0)
-#define GEN6_MBCUNIT_SNPCR 0x900c /* for LLC config */
+#define GEN6_MBCUNIT_SNPCR _MMIO(0x900c) /* for LLC config */
#define GEN6_MBC_SNPCR_SHIFT 21
#define GEN6_MBC_SNPCR_MASK (3<<21)
#define GEN6_MBC_SNPCR_MAX (0<<21)
@@ -120,31 +149,31 @@
#define GEN6_MBC_SNPCR_LOW (2<<21)
#define GEN6_MBC_SNPCR_MIN (3<<21) /* only 1/16th of the cache is shared */
-#define VLV_G3DCTL 0x9024
-#define VLV_GSCKGCTL 0x9028
+#define VLV_G3DCTL _MMIO(0x9024)
+#define VLV_GSCKGCTL _MMIO(0x9028)
-#define GEN6_MBCTL 0x0907c
+#define GEN6_MBCTL _MMIO(0x0907c)
#define GEN6_MBCTL_ENABLE_BOOT_FETCH (1 << 4)
#define GEN6_MBCTL_CTX_FETCH_NEEDED (1 << 3)
#define GEN6_MBCTL_BME_UPDATE_ENABLE (1 << 2)
#define GEN6_MBCTL_MAE_UPDATE_ENABLE (1 << 1)
#define GEN6_MBCTL_BOOT_FETCH_MECH (1 << 0)
-#define GEN6_GDRST 0x941c
+#define GEN6_GDRST _MMIO(0x941c)
#define GEN6_GRDOM_FULL (1 << 0)
#define GEN6_GRDOM_RENDER (1 << 1)
#define GEN6_GRDOM_MEDIA (1 << 2)
#define GEN6_GRDOM_BLT (1 << 3)
-#define RING_PP_DIR_BASE(ring) ((ring)->mmio_base+0x228)
-#define RING_PP_DIR_BASE_READ(ring) ((ring)->mmio_base+0x518)
-#define RING_PP_DIR_DCLV(ring) ((ring)->mmio_base+0x220)
+#define RING_PP_DIR_BASE(ring) _MMIO((ring)->mmio_base+0x228)
+#define RING_PP_DIR_BASE_READ(ring) _MMIO((ring)->mmio_base+0x518)
+#define RING_PP_DIR_DCLV(ring) _MMIO((ring)->mmio_base+0x220)
#define PP_DIR_DCLV_2G 0xffffffff
-#define GEN8_RING_PDP_UDW(ring, n) ((ring)->mmio_base+0x270 + ((n) * 8 + 4))
-#define GEN8_RING_PDP_LDW(ring, n) ((ring)->mmio_base+0x270 + (n) * 8)
+#define GEN8_RING_PDP_UDW(ring, n) _MMIO((ring)->mmio_base+0x270 + (n) * 8 + 4)
+#define GEN8_RING_PDP_LDW(ring, n) _MMIO((ring)->mmio_base+0x270 + (n) * 8)
-#define GEN8_R_PWR_CLK_STATE 0x20C8
+#define GEN8_R_PWR_CLK_STATE _MMIO(0x20C8)
#define GEN8_RPCS_ENABLE (1 << 31)
#define GEN8_RPCS_S_CNT_ENABLE (1 << 18)
#define GEN8_RPCS_S_CNT_SHIFT 15
@@ -157,7 +186,7 @@
#define GEN8_RPCS_EU_MIN_SHIFT 0
#define GEN8_RPCS_EU_MIN_MASK (0xf << GEN8_RPCS_EU_MIN_SHIFT)
-#define GAM_ECOCHK 0x4090
+#define GAM_ECOCHK _MMIO(0x4090)
#define BDW_DISABLE_HDC_INVALIDATION (1<<25)
#define ECOCHK_SNB_BIT (1<<10)
#define ECOCHK_DIS_TLB (1<<8)
@@ -170,15 +199,15 @@
#define ECOCHK_PPGTT_WT_HSW (0x2<<3)
#define ECOCHK_PPGTT_WB_HSW (0x3<<3)
-#define GAC_ECO_BITS 0x14090
+#define GAC_ECO_BITS _MMIO(0x14090)
#define ECOBITS_SNB_BIT (1<<13)
#define ECOBITS_PPGTT_CACHE64B (3<<8)
#define ECOBITS_PPGTT_CACHE4B (0<<8)
-#define GAB_CTL 0x24000
+#define GAB_CTL _MMIO(0x24000)
#define GAB_CTL_CONT_AFTER_PAGEFAULT (1<<8)
-#define GEN6_STOLEN_RESERVED 0x1082C0
+#define GEN6_STOLEN_RESERVED _MMIO(0x1082C0)
#define GEN6_STOLEN_RESERVED_ADDR_MASK (0xFFF << 20)
#define GEN7_STOLEN_RESERVED_ADDR_MASK (0x3FFF << 18)
#define GEN6_STOLEN_RESERVED_SIZE_MASK (3 << 4)
@@ -200,6 +229,7 @@
#define VGA_ST01_MDA 0x3ba
#define VGA_ST01_CGA 0x3da
+#define _VGA_MSR_WRITE _MMIO(0x3c2)
#define VGA_MSR_WRITE 0x3c2
#define VGA_MSR_READ 0x3cc
#define VGA_MSR_MEM_EN (1<<1)
@@ -377,10 +407,12 @@
#define MI_BATCH_BUFFER_START_GEN8 MI_INSTR(0x31, 1)
#define MI_BATCH_RESOURCE_STREAMER (1<<10)
-#define MI_PREDICATE_SRC0 (0x2400)
-#define MI_PREDICATE_SRC1 (0x2408)
+#define MI_PREDICATE_SRC0 _MMIO(0x2400)
+#define MI_PREDICATE_SRC0_UDW _MMIO(0x2400 + 4)
+#define MI_PREDICATE_SRC1 _MMIO(0x2408)
+#define MI_PREDICATE_SRC1_UDW _MMIO(0x2408 + 4)
-#define MI_PREDICATE_RESULT_2 (0x2214)
+#define MI_PREDICATE_RESULT_2 _MMIO(0x2214)
#define LOWER_SLICE_ENABLED (1<<0)
#define LOWER_SLICE_DISABLED (0<<0)
@@ -509,49 +541,61 @@
/*
* Registers used only by the command parser
*/
-#define BCS_SWCTRL 0x22200
-
-#define GPGPU_THREADS_DISPATCHED 0x2290
-#define HS_INVOCATION_COUNT 0x2300
-#define DS_INVOCATION_COUNT 0x2308
-#define IA_VERTICES_COUNT 0x2310
-#define IA_PRIMITIVES_COUNT 0x2318
-#define VS_INVOCATION_COUNT 0x2320
-#define GS_INVOCATION_COUNT 0x2328
-#define GS_PRIMITIVES_COUNT 0x2330
-#define CL_INVOCATION_COUNT 0x2338
-#define CL_PRIMITIVES_COUNT 0x2340
-#define PS_INVOCATION_COUNT 0x2348
-#define PS_DEPTH_COUNT 0x2350
+#define BCS_SWCTRL _MMIO(0x22200)
+
+#define GPGPU_THREADS_DISPATCHED _MMIO(0x2290)
+#define GPGPU_THREADS_DISPATCHED_UDW _MMIO(0x2290 + 4)
+#define HS_INVOCATION_COUNT _MMIO(0x2300)
+#define HS_INVOCATION_COUNT_UDW _MMIO(0x2300 + 4)
+#define DS_INVOCATION_COUNT _MMIO(0x2308)
+#define DS_INVOCATION_COUNT_UDW _MMIO(0x2308 + 4)
+#define IA_VERTICES_COUNT _MMIO(0x2310)
+#define IA_VERTICES_COUNT_UDW _MMIO(0x2310 + 4)
+#define IA_PRIMITIVES_COUNT _MMIO(0x2318)
+#define IA_PRIMITIVES_COUNT_UDW _MMIO(0x2318 + 4)
+#define VS_INVOCATION_COUNT _MMIO(0x2320)
+#define VS_INVOCATION_COUNT_UDW _MMIO(0x2320 + 4)
+#define GS_INVOCATION_COUNT _MMIO(0x2328)
+#define GS_INVOCATION_COUNT_UDW _MMIO(0x2328 + 4)
+#define GS_PRIMITIVES_COUNT _MMIO(0x2330)
+#define GS_PRIMITIVES_COUNT_UDW _MMIO(0x2330 + 4)
+#define CL_INVOCATION_COUNT _MMIO(0x2338)
+#define CL_INVOCATION_COUNT_UDW _MMIO(0x2338 + 4)
+#define CL_PRIMITIVES_COUNT _MMIO(0x2340)
+#define CL_PRIMITIVES_COUNT_UDW _MMIO(0x2340 + 4)
+#define PS_INVOCATION_COUNT _MMIO(0x2348)
+#define PS_INVOCATION_COUNT_UDW _MMIO(0x2348 + 4)
+#define PS_DEPTH_COUNT _MMIO(0x2350)
+#define PS_DEPTH_COUNT_UDW _MMIO(0x2350 + 4)
/* There are the 4 64-bit counter registers, one for each stream output */
-#define GEN7_SO_NUM_PRIMS_WRITTEN(n) (0x5200 + (n) * 8)
+#define GEN7_SO_NUM_PRIMS_WRITTEN(n) _MMIO(0x5200 + (n) * 8)
+#define GEN7_SO_NUM_PRIMS_WRITTEN_UDW(n) _MMIO(0x5200 + (n) * 8 + 4)
-#define GEN7_SO_PRIM_STORAGE_NEEDED(n) (0x5240 + (n) * 8)
+#define GEN7_SO_PRIM_STORAGE_NEEDED(n) _MMIO(0x5240 + (n) * 8)
+#define GEN7_SO_PRIM_STORAGE_NEEDED_UDW(n) _MMIO(0x5240 + (n) * 8 + 4)
-#define GEN7_3DPRIM_END_OFFSET 0x2420
-#define GEN7_3DPRIM_START_VERTEX 0x2430
-#define GEN7_3DPRIM_VERTEX_COUNT 0x2434
-#define GEN7_3DPRIM_INSTANCE_COUNT 0x2438
-#define GEN7_3DPRIM_START_INSTANCE 0x243C
-#define GEN7_3DPRIM_BASE_VERTEX 0x2440
+#define GEN7_3DPRIM_END_OFFSET _MMIO(0x2420)
+#define GEN7_3DPRIM_START_VERTEX _MMIO(0x2430)
+#define GEN7_3DPRIM_VERTEX_COUNT _MMIO(0x2434)
+#define GEN7_3DPRIM_INSTANCE_COUNT _MMIO(0x2438)
+#define GEN7_3DPRIM_START_INSTANCE _MMIO(0x243C)
+#define GEN7_3DPRIM_BASE_VERTEX _MMIO(0x2440)
-#define GEN7_GPGPU_DISPATCHDIMX 0x2500
-#define GEN7_GPGPU_DISPATCHDIMY 0x2504
-#define GEN7_GPGPU_DISPATCHDIMZ 0x2508
+#define GEN7_GPGPU_DISPATCHDIMX _MMIO(0x2500)
+#define GEN7_GPGPU_DISPATCHDIMY _MMIO(0x2504)
+#define GEN7_GPGPU_DISPATCHDIMZ _MMIO(0x2508)
-#define OACONTROL 0x2360
+#define OACONTROL _MMIO(0x2360)
#define _GEN7_PIPEA_DE_LOAD_SL 0x70068
#define _GEN7_PIPEB_DE_LOAD_SL 0x71068
-#define GEN7_PIPE_DE_LOAD_SL(pipe) _PIPE(pipe, \
- _GEN7_PIPEA_DE_LOAD_SL, \
- _GEN7_PIPEB_DE_LOAD_SL)
+#define GEN7_PIPE_DE_LOAD_SL(pipe) _MMIO_PIPE(pipe, _GEN7_PIPEA_DE_LOAD_SL, _GEN7_PIPEB_DE_LOAD_SL)
/*
* Reset registers
*/
-#define DEBUG_RESET_I830 0x6070
+#define DEBUG_RESET_I830 _MMIO(0x6070)
#define DEBUG_RESET_FULL (1<<7)
#define DEBUG_RESET_RENDER (1<<8)
#define DEBUG_RESET_DISPLAY (1<<9)
@@ -559,7 +603,7 @@
/*
* IOSF sideband
*/
-#define VLV_IOSF_DOORBELL_REQ (VLV_DISPLAY_BASE + 0x2100)
+#define VLV_IOSF_DOORBELL_REQ _MMIO(VLV_DISPLAY_BASE + 0x2100)
#define IOSF_DEVFN_SHIFT 24
#define IOSF_OPCODE_SHIFT 16
#define IOSF_PORT_SHIFT 8
@@ -576,8 +620,8 @@
#define IOSF_PORT_CCU 0xA9
#define IOSF_PORT_GPS_CORE 0x48
#define IOSF_PORT_FLISDSI 0x1B
-#define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104)
-#define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108)
+#define VLV_IOSF_DATA _MMIO(VLV_DISPLAY_BASE + 0x2104)
+#define VLV_IOSF_ADDR _MMIO(VLV_DISPLAY_BASE + 0x2108)
/* See configdb bunit SB addr map */
#define BUNIT_REG_BISOC 0x11
@@ -609,6 +653,7 @@
/* See the PUNIT HAS v0.8 for the below bits */
enum punit_power_well {
+ /* These numbers are fixed and must match the position of the pw bits */
PUNIT_POWER_WELL_RENDER = 0,
PUNIT_POWER_WELL_MEDIA = 1,
PUNIT_POWER_WELL_DISP2D = 3,
@@ -621,10 +666,12 @@ enum punit_power_well {
PUNIT_POWER_WELL_DPIO_RX1 = 11,
PUNIT_POWER_WELL_DPIO_CMN_D = 12,
- PUNIT_POWER_WELL_NUM,
+ /* Not actual bit groups. Used as IDs for lookup_power_well() */
+ PUNIT_POWER_WELL_ALWAYS_ON,
};
enum skl_disp_power_wells {
+ /* These numbers are fixed and must match the position of the pw bits */
SKL_DISP_PW_MISC_IO,
SKL_DISP_PW_DDI_A_E,
SKL_DISP_PW_DDI_B,
@@ -632,6 +679,10 @@ enum skl_disp_power_wells {
SKL_DISP_PW_DDI_D,
SKL_DISP_PW_1 = 14,
SKL_DISP_PW_2,
+
+ /* Not actual bit groups. Used as IDs for lookup_power_well() */
+ SKL_DISP_PW_ALWAYS_ON,
+ SKL_DISP_PW_DC_OFF,
};
#define SKL_POWER_WELL_STATE(pw) (1 << ((pw) * 2))
@@ -832,7 +883,7 @@ enum skl_disp_power_wells {
*/
#define DPIO_DEVFN 0
-#define DPIO_CTL (VLV_DISPLAY_BASE + 0x2110)
+#define DPIO_CTL _MMIO(VLV_DISPLAY_BASE + 0x2110)
#define DPIO_MODSEL1 (1<<3) /* if ref clk b == 27 */
#define DPIO_MODSEL0 (1<<2) /* if ref clk a == 27 */
#define DPIO_SFR_BYPASS (1<<1)
@@ -1185,9 +1236,9 @@ enum skl_disp_power_wells {
#define DPIO_UPAR_SHIFT 30
/* BXT PHY registers */
-#define _BXT_PHY(phy, a, b) _PIPE((phy), (a), (b))
+#define _BXT_PHY(phy, a, b) _MMIO_PIPE((phy), (a), (b))
-#define BXT_P_CR_GT_DISP_PWRON 0x138090
+#define BXT_P_CR_GT_DISP_PWRON _MMIO(0x138090)
#define GT_DISPLAY_POWER_ON(phy) (1 << (phy))
#define _PHY_CTL_FAMILY_EDP 0x64C80
@@ -1203,7 +1254,7 @@ enum skl_disp_power_wells {
#define PORT_PLL_ENABLE (1 << 31)
#define PORT_PLL_LOCK (1 << 30)
#define PORT_PLL_REF_SEL (1 << 27)
-#define BXT_PORT_PLL_ENABLE(port) _PORT(port, _PORT_PLL_A, _PORT_PLL_B)
+#define BXT_PORT_PLL_ENABLE(port) _MMIO_PORT(port, _PORT_PLL_A, _PORT_PLL_B)
#define _PORT_PLL_EBB_0_A 0x162034
#define _PORT_PLL_EBB_0_B 0x6C034
@@ -1214,7 +1265,7 @@ enum skl_disp_power_wells {
#define PORT_PLL_P2_SHIFT 8
#define PORT_PLL_P2_MASK (0x1f << PORT_PLL_P2_SHIFT)
#define PORT_PLL_P2(x) ((x) << PORT_PLL_P2_SHIFT)
-#define BXT_PORT_PLL_EBB_0(port) _PORT3(port, _PORT_PLL_EBB_0_A, \
+#define BXT_PORT_PLL_EBB_0(port) _MMIO_PORT3(port, _PORT_PLL_EBB_0_A, \
_PORT_PLL_EBB_0_B, \
_PORT_PLL_EBB_0_C)
@@ -1223,7 +1274,7 @@ enum skl_disp_power_wells {
#define _PORT_PLL_EBB_4_C 0x6C344
#define PORT_PLL_10BIT_CLK_ENABLE (1 << 13)
#define PORT_PLL_RECALIBRATE (1 << 14)
-#define BXT_PORT_PLL_EBB_4(port) _PORT3(port, _PORT_PLL_EBB_4_A, \
+#define BXT_PORT_PLL_EBB_4(port) _MMIO_PORT3(port, _PORT_PLL_EBB_4_A, \
_PORT_PLL_EBB_4_B, \
_PORT_PLL_EBB_4_C)
@@ -1259,7 +1310,7 @@ enum skl_disp_power_wells {
#define _PORT_PLL_BASE(port) _PORT3(port, _PORT_PLL_0_A, \
_PORT_PLL_0_B, \
_PORT_PLL_0_C)
-#define BXT_PORT_PLL(port, idx) (_PORT_PLL_BASE(port) + (idx) * 4)
+#define BXT_PORT_PLL(port, idx) _MMIO(_PORT_PLL_BASE(port) + (idx) * 4)
/* BXT PHY common lane registers */
#define _PORT_CL1CM_DW0_A 0x162000
@@ -1297,7 +1348,7 @@ enum skl_disp_power_wells {
_PORT_CL1CM_DW30_A)
/* Defined for PHY0 only */
-#define BXT_PORT_CL2CM_DW6_BC 0x6C358
+#define BXT_PORT_CL2CM_DW6_BC _MMIO(0x6C358)
#define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28)
/* BXT PHY Ref registers */
@@ -1337,10 +1388,10 @@ enum skl_disp_power_wells {
#define _PORT_PCS_DW10_GRP_A 0x162C28
#define _PORT_PCS_DW10_GRP_B 0x6CC28
#define _PORT_PCS_DW10_GRP_C 0x6CE28
-#define BXT_PORT_PCS_DW10_LN01(port) _PORT3(port, _PORT_PCS_DW10_LN01_A, \
+#define BXT_PORT_PCS_DW10_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW10_LN01_A, \
_PORT_PCS_DW10_LN01_B, \
_PORT_PCS_DW10_LN01_C)
-#define BXT_PORT_PCS_DW10_GRP(port) _PORT3(port, _PORT_PCS_DW10_GRP_A, \
+#define BXT_PORT_PCS_DW10_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW10_GRP_A, \
_PORT_PCS_DW10_GRP_B, \
_PORT_PCS_DW10_GRP_C)
#define TX2_SWING_CALC_INIT (1 << 31)
@@ -1357,13 +1408,13 @@ enum skl_disp_power_wells {
#define _PORT_PCS_DW12_GRP_C 0x6CE30
#define LANESTAGGER_STRAP_OVRD (1 << 6)
#define LANE_STAGGER_MASK 0x1F
-#define BXT_PORT_PCS_DW12_LN01(port) _PORT3(port, _PORT_PCS_DW12_LN01_A, \
+#define BXT_PORT_PCS_DW12_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN01_A, \
_PORT_PCS_DW12_LN01_B, \
_PORT_PCS_DW12_LN01_C)
-#define BXT_PORT_PCS_DW12_LN23(port) _PORT3(port, _PORT_PCS_DW12_LN23_A, \
+#define BXT_PORT_PCS_DW12_LN23(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN23_A, \
_PORT_PCS_DW12_LN23_B, \
_PORT_PCS_DW12_LN23_C)
-#define BXT_PORT_PCS_DW12_GRP(port) _PORT3(port, _PORT_PCS_DW12_GRP_A, \
+#define BXT_PORT_PCS_DW12_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW12_GRP_A, \
_PORT_PCS_DW12_GRP_B, \
_PORT_PCS_DW12_GRP_C)
@@ -1377,10 +1428,10 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW2_GRP_A 0x162D08
#define _PORT_TX_DW2_GRP_B 0x6CD08
#define _PORT_TX_DW2_GRP_C 0x6CF08
-#define BXT_PORT_TX_DW2_GRP(port) _PORT3(port, _PORT_TX_DW2_GRP_A, \
+#define BXT_PORT_TX_DW2_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW2_GRP_A, \
_PORT_TX_DW2_GRP_B, \
_PORT_TX_DW2_GRP_C)
-#define BXT_PORT_TX_DW2_LN0(port) _PORT3(port, _PORT_TX_DW2_LN0_A, \
+#define BXT_PORT_TX_DW2_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW2_LN0_A, \
_PORT_TX_DW2_LN0_B, \
_PORT_TX_DW2_LN0_C)
#define MARGIN_000_SHIFT 16
@@ -1394,10 +1445,10 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW3_GRP_A 0x162D0C
#define _PORT_TX_DW3_GRP_B 0x6CD0C
#define _PORT_TX_DW3_GRP_C 0x6CF0C
-#define BXT_PORT_TX_DW3_GRP(port) _PORT3(port, _PORT_TX_DW3_GRP_A, \
+#define BXT_PORT_TX_DW3_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW3_GRP_A, \
_PORT_TX_DW3_GRP_B, \
_PORT_TX_DW3_GRP_C)
-#define BXT_PORT_TX_DW3_LN0(port) _PORT3(port, _PORT_TX_DW3_LN0_A, \
+#define BXT_PORT_TX_DW3_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW3_LN0_A, \
_PORT_TX_DW3_LN0_B, \
_PORT_TX_DW3_LN0_C)
#define SCALE_DCOMP_METHOD (1 << 26)
@@ -1409,10 +1460,10 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW4_GRP_A 0x162D10
#define _PORT_TX_DW4_GRP_B 0x6CD10
#define _PORT_TX_DW4_GRP_C 0x6CF10
-#define BXT_PORT_TX_DW4_LN0(port) _PORT3(port, _PORT_TX_DW4_LN0_A, \
+#define BXT_PORT_TX_DW4_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW4_LN0_A, \
_PORT_TX_DW4_LN0_B, \
_PORT_TX_DW4_LN0_C)
-#define BXT_PORT_TX_DW4_GRP(port) _PORT3(port, _PORT_TX_DW4_GRP_A, \
+#define BXT_PORT_TX_DW4_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW4_GRP_A, \
_PORT_TX_DW4_GRP_B, \
_PORT_TX_DW4_GRP_C)
#define DEEMPH_SHIFT 24
@@ -1423,17 +1474,17 @@ enum skl_disp_power_wells {
#define _PORT_TX_DW14_LN0_C 0x6C938
#define LATENCY_OPTIM_SHIFT 30
#define LATENCY_OPTIM (1 << LATENCY_OPTIM_SHIFT)
-#define BXT_PORT_TX_DW14_LN(port, lane) (_PORT3((port), _PORT_TX_DW14_LN0_A, \
+#define BXT_PORT_TX_DW14_LN(port, lane) _MMIO(_PORT3((port), _PORT_TX_DW14_LN0_A, \
_PORT_TX_DW14_LN0_B, \
_PORT_TX_DW14_LN0_C) + \
_BXT_LANE_OFFSET(lane))
/* UAIMI scratch pad register 1 */
-#define UAIMI_SPR1 0x4F074
+#define UAIMI_SPR1 _MMIO(0x4F074)
/* SKL VccIO mask */
#define SKL_VCCIO_MASK 0x1
/* SKL balance leg register */
-#define DISPIO_CR_TX_BMU_CR0 0x6C00C
+#define DISPIO_CR_TX_BMU_CR0 _MMIO(0x6C00C)
/* I_boost values */
#define BALANCE_LEG_SHIFT(port) (8+3*(port))
#define BALANCE_LEG_MASK(port) (7<<(8+3*(port)))
@@ -1450,7 +1501,7 @@ enum skl_disp_power_wells {
* [0-15] @ 0x100000 gen6,vlv,chv
* [0-31] @ 0x100000 gen7+
*/
-#define FENCE_REG(i) (0x2000 + (((i) & 8) << 9) + ((i) & 7) * 4)
+#define FENCE_REG(i) _MMIO(0x2000 + (((i) & 8) << 9) + ((i) & 7) * 4)
#define I830_FENCE_START_MASK 0x07f80000
#define I830_FENCE_TILING_Y_SHIFT 12
#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
@@ -1463,21 +1514,21 @@ enum skl_disp_power_wells {
#define I915_FENCE_START_MASK 0x0ff00000
#define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8)
-#define FENCE_REG_965_LO(i) (0x03000 + (i) * 8)
-#define FENCE_REG_965_HI(i) (0x03000 + (i) * 8 + 4)
+#define FENCE_REG_965_LO(i) _MMIO(0x03000 + (i) * 8)
+#define FENCE_REG_965_HI(i) _MMIO(0x03000 + (i) * 8 + 4)
#define I965_FENCE_PITCH_SHIFT 2
#define I965_FENCE_TILING_Y_SHIFT 1
#define I965_FENCE_REG_VALID (1<<0)
#define I965_FENCE_MAX_PITCH_VAL 0x0400
-#define FENCE_REG_GEN6_LO(i) (0x100000 + (i) * 8)
-#define FENCE_REG_GEN6_HI(i) (0x100000 + (i) * 8 + 4)
+#define FENCE_REG_GEN6_LO(i) _MMIO(0x100000 + (i) * 8)
+#define FENCE_REG_GEN6_HI(i) _MMIO(0x100000 + (i) * 8 + 4)
#define GEN6_FENCE_PITCH_SHIFT 32
#define GEN7_FENCE_MAX_PITCH_VAL 0x0800
/* control register for cpu gtt access */
-#define TILECTL 0x101000
+#define TILECTL _MMIO(0x101000)
#define TILECTL_SWZCTL (1 << 0)
#define TILECTL_TLBPF (1 << 1)
#define TILECTL_TLB_PREFETCH_DIS (1 << 2)
@@ -1486,30 +1537,30 @@ enum skl_disp_power_wells {
/*
* Instruction and interrupt control regs
*/
-#define PGTBL_CTL 0x02020
+#define PGTBL_CTL _MMIO(0x02020)
#define PGTBL_ADDRESS_LO_MASK 0xfffff000 /* bits [31:12] */
#define PGTBL_ADDRESS_HI_MASK 0x000000f0 /* bits [35:32] (gen4) */
-#define PGTBL_ER 0x02024
-#define PRB0_BASE (0x2030-0x30)
-#define PRB1_BASE (0x2040-0x30) /* 830,gen3 */
-#define PRB2_BASE (0x2050-0x30) /* gen3 */
-#define SRB0_BASE (0x2100-0x30) /* gen2 */
-#define SRB1_BASE (0x2110-0x30) /* gen2 */
-#define SRB2_BASE (0x2120-0x30) /* 830 */
-#define SRB3_BASE (0x2130-0x30) /* 830 */
+#define PGTBL_ER _MMIO(0x02024)
+#define PRB0_BASE (0x2030-0x30)
+#define PRB1_BASE (0x2040-0x30) /* 830,gen3 */
+#define PRB2_BASE (0x2050-0x30) /* gen3 */
+#define SRB0_BASE (0x2100-0x30) /* gen2 */
+#define SRB1_BASE (0x2110-0x30) /* gen2 */
+#define SRB2_BASE (0x2120-0x30) /* 830 */
+#define SRB3_BASE (0x2130-0x30) /* 830 */
#define RENDER_RING_BASE 0x02000
#define BSD_RING_BASE 0x04000
#define GEN6_BSD_RING_BASE 0x12000
#define GEN8_BSD2_RING_BASE 0x1c000
#define VEBOX_RING_BASE 0x1a000
#define BLT_RING_BASE 0x22000
-#define RING_TAIL(base) ((base)+0x30)
-#define RING_HEAD(base) ((base)+0x34)
-#define RING_START(base) ((base)+0x38)
-#define RING_CTL(base) ((base)+0x3c)
-#define RING_SYNC_0(base) ((base)+0x40)
-#define RING_SYNC_1(base) ((base)+0x44)
-#define RING_SYNC_2(base) ((base)+0x48)
+#define RING_TAIL(base) _MMIO((base)+0x30)
+#define RING_HEAD(base) _MMIO((base)+0x34)
+#define RING_START(base) _MMIO((base)+0x38)
+#define RING_CTL(base) _MMIO((base)+0x3c)
+#define RING_SYNC_0(base) _MMIO((base)+0x40)
+#define RING_SYNC_1(base) _MMIO((base)+0x44)
+#define RING_SYNC_2(base) _MMIO((base)+0x48)
#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE))
#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE))
#define GEN6_RVESYNC (RING_SYNC_2(RENDER_RING_BASE))
@@ -1522,51 +1573,52 @@ enum skl_disp_power_wells {
#define GEN6_VEBSYNC (RING_SYNC_0(VEBOX_RING_BASE))
#define GEN6_VERSYNC (RING_SYNC_1(VEBOX_RING_BASE))
#define GEN6_VEVSYNC (RING_SYNC_2(VEBOX_RING_BASE))
-#define GEN6_NOSYNC 0
-#define RING_PSMI_CTL(base) ((base)+0x50)
-#define RING_MAX_IDLE(base) ((base)+0x54)
-#define RING_HWS_PGA(base) ((base)+0x80)
-#define RING_HWS_PGA_GEN6(base) ((base)+0x2080)
-#define RING_RESET_CTL(base) ((base)+0xd0)
+#define GEN6_NOSYNC INVALID_MMIO_REG
+#define RING_PSMI_CTL(base) _MMIO((base)+0x50)
+#define RING_MAX_IDLE(base) _MMIO((base)+0x54)
+#define RING_HWS_PGA(base) _MMIO((base)+0x80)
+#define RING_HWS_PGA_GEN6(base) _MMIO((base)+0x2080)
+#define RING_RESET_CTL(base) _MMIO((base)+0xd0)
#define RESET_CTL_REQUEST_RESET (1 << 0)
#define RESET_CTL_READY_TO_RESET (1 << 1)
-#define HSW_GTT_CACHE_EN 0x4024
+#define HSW_GTT_CACHE_EN _MMIO(0x4024)
#define GTT_CACHE_EN_ALL 0xF0007FFF
-#define GEN7_WR_WATERMARK 0x4028
-#define GEN7_GFX_PRIO_CTRL 0x402C
-#define ARB_MODE 0x4030
+#define GEN7_WR_WATERMARK _MMIO(0x4028)
+#define GEN7_GFX_PRIO_CTRL _MMIO(0x402C)
+#define ARB_MODE _MMIO(0x4030)
#define ARB_MODE_SWIZZLE_SNB (1<<4)
#define ARB_MODE_SWIZZLE_IVB (1<<5)
-#define GEN7_GFX_PEND_TLB0 0x4034
-#define GEN7_GFX_PEND_TLB1 0x4038
+#define GEN7_GFX_PEND_TLB0 _MMIO(0x4034)
+#define GEN7_GFX_PEND_TLB1 _MMIO(0x4038)
/* L3, CVS, ZTLB, RCC, CASC LRA min, max values */
-#define GEN7_LRA_LIMITS(i) (0x403C + (i) * 4)
+#define GEN7_LRA_LIMITS(i) _MMIO(0x403C + (i) * 4)
#define GEN7_LRA_LIMITS_REG_NUM 13
-#define GEN7_MEDIA_MAX_REQ_COUNT 0x4070
-#define GEN7_GFX_MAX_REQ_COUNT 0x4074
+#define GEN7_MEDIA_MAX_REQ_COUNT _MMIO(0x4070)
+#define GEN7_GFX_MAX_REQ_COUNT _MMIO(0x4074)
-#define GAMTARBMODE 0x04a08
+#define GAMTARBMODE _MMIO(0x04a08)
#define ARB_MODE_BWGTLB_DISABLE (1<<9)
#define ARB_MODE_SWIZZLE_BDW (1<<1)
-#define RENDER_HWS_PGA_GEN7 (0x04080)
-#define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id)
+#define RENDER_HWS_PGA_GEN7 _MMIO(0x04080)
+#define RING_FAULT_REG(ring) _MMIO(0x4094 + 0x100*(ring)->id)
#define RING_FAULT_GTTSEL_MASK (1<<11)
#define RING_FAULT_SRCID(x) (((x) >> 3) & 0xff)
#define RING_FAULT_FAULT_TYPE(x) (((x) >> 1) & 0x3)
#define RING_FAULT_VALID (1<<0)
-#define DONE_REG 0x40b0
-#define GEN8_PRIVATE_PAT_LO 0x40e0
-#define GEN8_PRIVATE_PAT_HI (0x40e0 + 4)
-#define BSD_HWS_PGA_GEN7 (0x04180)
-#define BLT_HWS_PGA_GEN7 (0x04280)
-#define VEBOX_HWS_PGA_GEN7 (0x04380)
-#define RING_ACTHD(base) ((base)+0x74)
-#define RING_ACTHD_UDW(base) ((base)+0x5c)
-#define RING_NOPID(base) ((base)+0x94)
-#define RING_IMR(base) ((base)+0xa8)
-#define RING_HWSTAM(base) ((base)+0x98)
-#define RING_TIMESTAMP(base) ((base)+0x358)
+#define DONE_REG _MMIO(0x40b0)
+#define GEN8_PRIVATE_PAT_LO _MMIO(0x40e0)
+#define GEN8_PRIVATE_PAT_HI _MMIO(0x40e0 + 4)
+#define BSD_HWS_PGA_GEN7 _MMIO(0x04180)
+#define BLT_HWS_PGA_GEN7 _MMIO(0x04280)
+#define VEBOX_HWS_PGA_GEN7 _MMIO(0x04380)
+#define RING_ACTHD(base) _MMIO((base)+0x74)
+#define RING_ACTHD_UDW(base) _MMIO((base)+0x5c)
+#define RING_NOPID(base) _MMIO((base)+0x94)
+#define RING_IMR(base) _MMIO((base)+0xa8)
+#define RING_HWSTAM(base) _MMIO((base)+0x98)
+#define RING_TIMESTAMP(base) _MMIO((base)+0x358)
+#define RING_TIMESTAMP_UDW(base) _MMIO((base)+0x358 + 4)
#define TAIL_ADDR 0x001FFFF8
#define HEAD_WRAP_COUNT 0xFFE00000
#define HEAD_WRAP_ONE 0x00200000
@@ -1583,57 +1635,65 @@ enum skl_disp_power_wells {
#define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */
#define RING_WAIT_SEMAPHORE (1<<10) /* gen6+ */
-#define GEN7_TLB_RD_ADDR 0x4700
+#define GEN7_TLB_RD_ADDR _MMIO(0x4700)
#if 0
-#define PRB0_TAIL 0x02030
-#define PRB0_HEAD 0x02034
-#define PRB0_START 0x02038
-#define PRB0_CTL 0x0203c
-#define PRB1_TAIL 0x02040 /* 915+ only */
-#define PRB1_HEAD 0x02044 /* 915+ only */
-#define PRB1_START 0x02048 /* 915+ only */
-#define PRB1_CTL 0x0204c /* 915+ only */
+#define PRB0_TAIL _MMIO(0x2030)
+#define PRB0_HEAD _MMIO(0x2034)
+#define PRB0_START _MMIO(0x2038)
+#define PRB0_CTL _MMIO(0x203c)
+#define PRB1_TAIL _MMIO(0x2040) /* 915+ only */
+#define PRB1_HEAD _MMIO(0x2044) /* 915+ only */
+#define PRB1_START _MMIO(0x2048) /* 915+ only */
+#define PRB1_CTL _MMIO(0x204c) /* 915+ only */
#endif
-#define IPEIR_I965 0x02064
-#define IPEHR_I965 0x02068
-#define GEN7_SC_INSTDONE 0x07100
-#define GEN7_SAMPLER_INSTDONE 0x0e160
-#define GEN7_ROW_INSTDONE 0x0e164
+#define IPEIR_I965 _MMIO(0x2064)
+#define IPEHR_I965 _MMIO(0x2068)
+#define GEN7_SC_INSTDONE _MMIO(0x7100)
+#define GEN7_SAMPLER_INSTDONE _MMIO(0xe160)
+#define GEN7_ROW_INSTDONE _MMIO(0xe164)
#define I915_NUM_INSTDONE_REG 4
-#define RING_IPEIR(base) ((base)+0x64)
-#define RING_IPEHR(base) ((base)+0x68)
+#define RING_IPEIR(base) _MMIO((base)+0x64)
+#define RING_IPEHR(base) _MMIO((base)+0x68)
/*
* On GEN4, only the render ring INSTDONE exists and has a different
* layout than the GEN7+ version.
* The GEN2 counterpart of this register is GEN2_INSTDONE.
*/
-#define RING_INSTDONE(base) ((base)+0x6c)
-#define RING_INSTPS(base) ((base)+0x70)
-#define RING_DMA_FADD(base) ((base)+0x78)
-#define RING_DMA_FADD_UDW(base) ((base)+0x60) /* gen8+ */
-#define RING_INSTPM(base) ((base)+0xc0)
-#define RING_MI_MODE(base) ((base)+0x9c)
-#define INSTPS 0x02070 /* 965+ only */
-#define GEN4_INSTDONE1 0x0207c /* 965+ only, aka INSTDONE_2 on SNB */
-#define ACTHD_I965 0x02074
-#define HWS_PGA 0x02080
+#define RING_INSTDONE(base) _MMIO((base)+0x6c)
+#define RING_INSTPS(base) _MMIO((base)+0x70)
+#define RING_DMA_FADD(base) _MMIO((base)+0x78)
+#define RING_DMA_FADD_UDW(base) _MMIO((base)+0x60) /* gen8+ */
+#define RING_INSTPM(base) _MMIO((base)+0xc0)
+#define RING_MI_MODE(base) _MMIO((base)+0x9c)
+#define INSTPS _MMIO(0x2070) /* 965+ only */
+#define GEN4_INSTDONE1 _MMIO(0x207c) /* 965+ only, aka INSTDONE_2 on SNB */
+#define ACTHD_I965 _MMIO(0x2074)
+#define HWS_PGA _MMIO(0x2080)
#define HWS_ADDRESS_MASK 0xfffff000
#define HWS_START_ADDRESS_SHIFT 4
-#define PWRCTXA 0x2088 /* 965GM+ only */
+#define PWRCTXA _MMIO(0x2088) /* 965GM+ only */
#define PWRCTX_EN (1<<0)
-#define IPEIR 0x02088
-#define IPEHR 0x0208c
-#define GEN2_INSTDONE 0x02090
-#define NOPID 0x02094
-#define HWSTAM 0x02098
-#define DMA_FADD_I8XX 0x020d0
-#define RING_BBSTATE(base) ((base)+0x110)
-#define RING_BBADDR(base) ((base)+0x140)
-#define RING_BBADDR_UDW(base) ((base)+0x168) /* gen8+ */
-
-#define ERROR_GEN6 0x040a0
-#define GEN7_ERR_INT 0x44040
+#define IPEIR _MMIO(0x2088)
+#define IPEHR _MMIO(0x208c)
+#define GEN2_INSTDONE _MMIO(0x2090)
+#define NOPID _MMIO(0x2094)
+#define HWSTAM _MMIO(0x2098)
+#define DMA_FADD_I8XX _MMIO(0x20d0)
+#define RING_BBSTATE(base) _MMIO((base)+0x110)
+#define RING_BB_PPGTT (1 << 5)
+#define RING_SBBADDR(base) _MMIO((base)+0x114) /* hsw+ */
+#define RING_SBBSTATE(base) _MMIO((base)+0x118) /* hsw+ */
+#define RING_SBBADDR_UDW(base) _MMIO((base)+0x11c) /* gen8+ */
+#define RING_BBADDR(base) _MMIO((base)+0x140)
+#define RING_BBADDR_UDW(base) _MMIO((base)+0x168) /* gen8+ */
+#define RING_BB_PER_CTX_PTR(base) _MMIO((base)+0x1c0) /* gen8+ */
+#define RING_INDIRECT_CTX(base) _MMIO((base)+0x1c4) /* gen8+ */
+#define RING_INDIRECT_CTX_OFFSET(base) _MMIO((base)+0x1c8) /* gen8+ */
+#define RING_CTX_TIMESTAMP(base) _MMIO((base)+0x3a8) /* gen8+ */
+
+#define ERROR_GEN6 _MMIO(0x40a0)
+#define GEN7_ERR_INT _MMIO(0x44040)
#define ERR_INT_POISON (1<<31)
#define ERR_INT_MMIO_UNCLAIMED (1<<13)
#define ERR_INT_PIPE_CRC_DONE_C (1<<8)
@@ -1645,13 +1705,13 @@ enum skl_disp_power_wells {
#define ERR_INT_FIFO_UNDERRUN_A (1<<0)
#define ERR_INT_FIFO_UNDERRUN(pipe) (1<<((pipe)*3))
-#define GEN8_FAULT_TLB_DATA0 0x04b10
-#define GEN8_FAULT_TLB_DATA1 0x04b14
+#define GEN8_FAULT_TLB_DATA0 _MMIO(0x4b10)
+#define GEN8_FAULT_TLB_DATA1 _MMIO(0x4b14)
-#define FPGA_DBG 0x42300
+#define FPGA_DBG _MMIO(0x42300)
#define FPGA_DBG_RM_NOCLAIM (1<<31)
-#define DERRMR 0x44050
+#define DERRMR _MMIO(0x44050)
/* Note that HBLANK events are reserved on bdw+ */
#define DERRMR_PIPEA_SCANLINE (1<<0)
#define DERRMR_PIPEA_PRI_FLIP_DONE (1<<1)
@@ -1675,29 +1735,29 @@ enum skl_disp_power_wells {
* for various sorts of correct behavior. The top 16 bits of each are
* the enables for writing to the corresponding low bit.
*/
-#define _3D_CHICKEN 0x02084
+#define _3D_CHICKEN _MMIO(0x2084)
#define _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB (1 << 10)
-#define _3D_CHICKEN2 0x0208c
+#define _3D_CHICKEN2 _MMIO(0x208c)
/* Disables pipelining of read flushes past the SF-WIZ interface.
* Required on all Ironlake steppings according to the B-Spec, but the
* particular danger of not doing so is not specified.
*/
# define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14)
-#define _3D_CHICKEN3 0x02090
+#define _3D_CHICKEN3 _MMIO(0x2090)
#define _3D_CHICKEN_SF_DISABLE_OBJEND_CULL (1 << 10)
#define _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL (1 << 5)
#define _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(x) ((x)<<1) /* gen8+ */
#define _3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH (1 << 1) /* gen6 */
-#define MI_MODE 0x0209c
+#define MI_MODE _MMIO(0x209c)
# define VS_TIMER_DISPATCH (1 << 6)
# define MI_FLUSH_ENABLE (1 << 12)
# define ASYNC_FLIP_PERF_DISABLE (1 << 14)
# define MODE_IDLE (1 << 9)
# define STOP_RING (1 << 8)
-#define GEN6_GT_MODE 0x20d0
-#define GEN7_GT_MODE 0x7008
+#define GEN6_GT_MODE _MMIO(0x20d0)
+#define GEN7_GT_MODE _MMIO(0x7008)
#define GEN6_WIZ_HASHING(hi, lo) (((hi) << 9) | ((lo) << 7))
#define GEN6_WIZ_HASHING_8x8 GEN6_WIZ_HASHING(0, 0)
#define GEN6_WIZ_HASHING_8x4 GEN6_WIZ_HASHING(0, 1)
@@ -1707,9 +1767,9 @@ enum skl_disp_power_wells {
#define GEN9_IZ_HASHING_MASK(slice) (0x3 << ((slice) * 2))
#define GEN9_IZ_HASHING(slice, val) ((val) << ((slice) * 2))
-#define GFX_MODE 0x02520
-#define GFX_MODE_GEN7 0x0229c
-#define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c)
+#define GFX_MODE _MMIO(0x2520)
+#define GFX_MODE_GEN7 _MMIO(0x229c)
+#define RING_MODE_GEN7(ring) _MMIO((ring)->mmio_base+0x29c)
#define GFX_RUN_LIST_ENABLE (1<<15)
#define GFX_INTERRUPT_STEERING (1<<14)
#define GFX_TLB_INVALIDATE_EXPLICIT (1<<13)
@@ -1727,36 +1787,36 @@ enum skl_disp_power_wells {
#define VLV_DISPLAY_BASE 0x180000
#define VLV_MIPI_BASE VLV_DISPLAY_BASE
-#define VLV_GU_CTL0 (VLV_DISPLAY_BASE + 0x2030)
-#define VLV_GU_CTL1 (VLV_DISPLAY_BASE + 0x2034)
-#define SCPD0 0x0209c /* 915+ only */
-#define IER 0x020a0
-#define IIR 0x020a4
-#define IMR 0x020a8
-#define ISR 0x020ac
-#define VLV_GUNIT_CLOCK_GATE (VLV_DISPLAY_BASE + 0x2060)
+#define VLV_GU_CTL0 _MMIO(VLV_DISPLAY_BASE + 0x2030)
+#define VLV_GU_CTL1 _MMIO(VLV_DISPLAY_BASE + 0x2034)
+#define SCPD0 _MMIO(0x209c) /* 915+ only */
+#define IER _MMIO(0x20a0)
+#define IIR _MMIO(0x20a4)
+#define IMR _MMIO(0x20a8)
+#define ISR _MMIO(0x20ac)
+#define VLV_GUNIT_CLOCK_GATE _MMIO(VLV_DISPLAY_BASE + 0x2060)
#define GINT_DIS (1<<22)
#define GCFG_DIS (1<<8)
-#define VLV_GUNIT_CLOCK_GATE2 (VLV_DISPLAY_BASE + 0x2064)
-#define VLV_IIR_RW (VLV_DISPLAY_BASE + 0x2084)
-#define VLV_IER (VLV_DISPLAY_BASE + 0x20a0)
-#define VLV_IIR (VLV_DISPLAY_BASE + 0x20a4)
-#define VLV_IMR (VLV_DISPLAY_BASE + 0x20a8)
-#define VLV_ISR (VLV_DISPLAY_BASE + 0x20ac)
-#define VLV_PCBR (VLV_DISPLAY_BASE + 0x2120)
+#define VLV_GUNIT_CLOCK_GATE2 _MMIO(VLV_DISPLAY_BASE + 0x2064)
+#define VLV_IIR_RW _MMIO(VLV_DISPLAY_BASE + 0x2084)
+#define VLV_IER _MMIO(VLV_DISPLAY_BASE + 0x20a0)
+#define VLV_IIR _MMIO(VLV_DISPLAY_BASE + 0x20a4)
+#define VLV_IMR _MMIO(VLV_DISPLAY_BASE + 0x20a8)
+#define VLV_ISR _MMIO(VLV_DISPLAY_BASE + 0x20ac)
+#define VLV_PCBR _MMIO(VLV_DISPLAY_BASE + 0x2120)
#define VLV_PCBR_ADDR_SHIFT 12
#define DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
-#define EIR 0x020b0
-#define EMR 0x020b4
-#define ESR 0x020b8
+#define EIR _MMIO(0x20b0)
+#define EMR _MMIO(0x20b4)
+#define ESR _MMIO(0x20b8)
#define GM45_ERROR_PAGE_TABLE (1<<5)
#define GM45_ERROR_MEM_PRIV (1<<4)
#define I915_ERROR_PAGE_TABLE (1<<4)
#define GM45_ERROR_CP_PRIV (1<<3)
#define I915_ERROR_MEMORY_REFRESH (1<<1)
#define I915_ERROR_INSTRUCTION (1<<0)
-#define INSTPM 0x020c0
+#define INSTPM _MMIO(0x20c0)
#define INSTPM_SELF_EN (1<<12) /* 915GM only */
#define INSTPM_AGPBUSY_INT_EN (1<<11) /* gen3: when disabled, pending interrupts
will not assert AGPBUSY# and will only
@@ -1764,14 +1824,14 @@ enum skl_disp_power_wells {
#define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */
#define INSTPM_TLB_INVALIDATE (1<<9)
#define INSTPM_SYNC_FLUSH (1<<5)
-#define ACTHD 0x020c8
-#define MEM_MODE 0x020cc
+#define ACTHD _MMIO(0x20c8)
+#define MEM_MODE _MMIO(0x20cc)
#define MEM_DISPLAY_B_TRICKLE_FEED_DISABLE (1<<3) /* 830 only */
#define MEM_DISPLAY_A_TRICKLE_FEED_DISABLE (1<<2) /* 830/845 only */
#define MEM_DISPLAY_TRICKLE_FEED_DISABLE (1<<2) /* 85x only */
-#define FW_BLC 0x020d8
-#define FW_BLC2 0x020dc
-#define FW_BLC_SELF 0x020e0 /* 915+ only */
+#define FW_BLC _MMIO(0x20d8)
+#define FW_BLC2 _MMIO(0x20dc)
+#define FW_BLC_SELF _MMIO(0x20e0) /* 915+ only */
#define FW_BLC_SELF_EN_MASK (1<<31)
#define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */
#define FW_BLC_SELF_EN (1<<15) /* 945 only */
@@ -1779,7 +1839,7 @@ enum skl_disp_power_wells {
#define MM_FIFO_WATERMARK 0x0001F000
#define LM_BURST_LENGTH 0x00000700
#define LM_FIFO_WATERMARK 0x0000001F
-#define MI_ARB_STATE 0x020e4 /* 915+ only */
+#define MI_ARB_STATE _MMIO(0x20e4) /* 915+ only */
/* Make render/texture TLB fetches lower priorty than associated data
* fetches. This is not turned on by default
@@ -1843,11 +1903,11 @@ enum skl_disp_power_wells {
#define MI_ARB_DISPLAY_PRIORITY_A_B (0 << 0) /* display A > display B */
#define MI_ARB_DISPLAY_PRIORITY_B_A (1 << 0) /* display B > display A */
-#define MI_STATE 0x020e4 /* gen2 only */
+#define MI_STATE _MMIO(0x20e4) /* gen2 only */
#define MI_AGPBUSY_INT_EN (1 << 1) /* 85x only */
#define MI_AGPBUSY_830_MODE (1 << 0) /* 85x only */
-#define CACHE_MODE_0 0x02120 /* 915+ only */
+#define CACHE_MODE_0 _MMIO(0x2120) /* 915+ only */
#define CM0_PIPELINED_RENDER_FLUSH_DISABLE (1<<8)
#define CM0_IZ_OPT_DISABLE (1<<6)
#define CM0_ZR_OPT_DISABLE (1<<5)
@@ -1856,32 +1916,32 @@ enum skl_disp_power_wells {
#define CM0_COLOR_EVICT_DISABLE (1<<3)
#define CM0_DEPTH_WRITE_DISABLE (1<<1)
#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
-#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
-#define GFX_FLSH_CNTL_GEN6 0x101008
+#define GFX_FLSH_CNTL _MMIO(0x2170) /* 915+ only */
+#define GFX_FLSH_CNTL_GEN6 _MMIO(0x101008)
#define GFX_FLSH_CNTL_EN (1<<0)
-#define ECOSKPD 0x021d0
+#define ECOSKPD _MMIO(0x21d0)
#define ECO_GATING_CX_ONLY (1<<3)
#define ECO_FLIP_DONE (1<<0)
-#define CACHE_MODE_0_GEN7 0x7000 /* IVB+ */
+#define CACHE_MODE_0_GEN7 _MMIO(0x7000) /* IVB+ */
#define RC_OP_FLUSH_ENABLE (1<<0)
#define HIZ_RAW_STALL_OPT_DISABLE (1<<2)
-#define CACHE_MODE_1 0x7004 /* IVB+ */
+#define CACHE_MODE_1 _MMIO(0x7004) /* IVB+ */
#define PIXEL_SUBSPAN_COLLECT_OPT_DISABLE (1<<6)
#define GEN8_4x4_STC_OPTIMIZATION_DISABLE (1<<6)
#define GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE (1<<1)
-#define GEN6_BLITTER_ECOSKPD 0x221d0
+#define GEN6_BLITTER_ECOSKPD _MMIO(0x221d0)
#define GEN6_BLITTER_LOCK_SHIFT 16
#define GEN6_BLITTER_FBC_NOTIFY (1<<3)
-#define GEN6_RC_SLEEP_PSMI_CONTROL 0x2050
+#define GEN6_RC_SLEEP_PSMI_CONTROL _MMIO(0x2050)
#define GEN6_PSMI_SLEEP_MSG_DISABLE (1 << 0)
#define GEN8_RC_SEMA_IDLE_MSG_DISABLE (1 << 12)
#define GEN8_FF_DOP_CLOCK_GATE_DISABLE (1<<10)
/* Fuse readout registers for GT */
-#define CHV_FUSE_GT (VLV_DISPLAY_BASE + 0x2168)
+#define CHV_FUSE_GT _MMIO(VLV_DISPLAY_BASE + 0x2168)
#define CHV_FGT_DISABLE_SS0 (1 << 10)
#define CHV_FGT_DISABLE_SS1 (1 << 11)
#define CHV_FGT_EU_DIS_SS0_R0_SHIFT 16
@@ -1893,7 +1953,7 @@ enum skl_disp_power_wells {
#define CHV_FGT_EU_DIS_SS1_R1_SHIFT 28
#define CHV_FGT_EU_DIS_SS1_R1_MASK (0xf << CHV_FGT_EU_DIS_SS1_R1_SHIFT)
-#define GEN8_FUSE2 0x9120
+#define GEN8_FUSE2 _MMIO(0x9120)
#define GEN8_F2_SS_DIS_SHIFT 21
#define GEN8_F2_SS_DIS_MASK (0x7 << GEN8_F2_SS_DIS_SHIFT)
#define GEN8_F2_S_ENA_SHIFT 25
@@ -1902,22 +1962,22 @@ enum skl_disp_power_wells {
#define GEN9_F2_SS_DIS_SHIFT 20
#define GEN9_F2_SS_DIS_MASK (0xf << GEN9_F2_SS_DIS_SHIFT)
-#define GEN8_EU_DISABLE0 0x9134
+#define GEN8_EU_DISABLE0 _MMIO(0x9134)
#define GEN8_EU_DIS0_S0_MASK 0xffffff
#define GEN8_EU_DIS0_S1_SHIFT 24
#define GEN8_EU_DIS0_S1_MASK (0xff << GEN8_EU_DIS0_S1_SHIFT)
-#define GEN8_EU_DISABLE1 0x9138
+#define GEN8_EU_DISABLE1 _MMIO(0x9138)
#define GEN8_EU_DIS1_S1_MASK 0xffff
#define GEN8_EU_DIS1_S2_SHIFT 16
#define GEN8_EU_DIS1_S2_MASK (0xffff << GEN8_EU_DIS1_S2_SHIFT)
-#define GEN8_EU_DISABLE2 0x913c
+#define GEN8_EU_DISABLE2 _MMIO(0x913c)
#define GEN8_EU_DIS2_S2_MASK 0xff
-#define GEN9_EU_DISABLE(slice) (0x9134 + (slice)*0x4)
+#define GEN9_EU_DISABLE(slice) _MMIO(0x9134 + (slice)*0x4)
-#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050
+#define GEN6_BSD_SLEEP_PSMI_CONTROL _MMIO(0x12050)
#define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0)
#define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2)
#define GEN6_BSD_SLEEP_INDICATOR (1 << 3)
@@ -1995,9 +2055,9 @@ enum skl_disp_power_wells {
#define I915_ASLE_INTERRUPT (1<<0)
#define I915_BSD_USER_INTERRUPT (1<<25)
-#define GEN6_BSD_RNCID 0x12198
+#define GEN6_BSD_RNCID _MMIO(0x12198)
-#define GEN7_FF_THREAD_MODE 0x20a0
+#define GEN7_FF_THREAD_MODE _MMIO(0x20a0)
#define GEN7_FF_SCHED_MASK 0x0077070
#define GEN8_FF_DS_REF_CNT_FFME (1 << 19)
#define GEN7_FF_TS_SCHED_HS1 (0x5<<16)
@@ -2018,9 +2078,9 @@ enum skl_disp_power_wells {
* Framebuffer compression (915+ only)
*/
-#define FBC_CFB_BASE 0x03200 /* 4k page aligned */
-#define FBC_LL_BASE 0x03204 /* 4k page aligned */
-#define FBC_CONTROL 0x03208
+#define FBC_CFB_BASE _MMIO(0x3200) /* 4k page aligned */
+#define FBC_LL_BASE _MMIO(0x3204) /* 4k page aligned */
+#define FBC_CONTROL _MMIO(0x3208)
#define FBC_CTL_EN (1<<31)
#define FBC_CTL_PERIODIC (1<<30)
#define FBC_CTL_INTERVAL_SHIFT (16)
@@ -2028,14 +2088,14 @@ enum skl_disp_power_wells {
#define FBC_CTL_C3_IDLE (1<<13)
#define FBC_CTL_STRIDE_SHIFT (5)
#define FBC_CTL_FENCENO_SHIFT (0)
-#define FBC_COMMAND 0x0320c
+#define FBC_COMMAND _MMIO(0x320c)
#define FBC_CMD_COMPRESS (1<<0)
-#define FBC_STATUS 0x03210
+#define FBC_STATUS _MMIO(0x3210)
#define FBC_STAT_COMPRESSING (1<<31)
#define FBC_STAT_COMPRESSED (1<<30)
#define FBC_STAT_MODIFIED (1<<29)
#define FBC_STAT_CURRENT_LINE_SHIFT (0)
-#define FBC_CONTROL2 0x03214
+#define FBC_CONTROL2 _MMIO(0x3214)
#define FBC_CTL_FENCE_DBL (0<<4)
#define FBC_CTL_IDLE_IMM (0<<2)
#define FBC_CTL_IDLE_FULL (1<<2)
@@ -2043,17 +2103,17 @@ enum skl_disp_power_wells {
#define FBC_CTL_IDLE_DEBUG (3<<2)
#define FBC_CTL_CPU_FENCE (1<<1)
#define FBC_CTL_PLANE(plane) ((plane)<<0)
-#define FBC_FENCE_OFF 0x03218 /* BSpec typo has 321Bh */
-#define FBC_TAG(i) (0x03300 + (i) * 4)
+#define FBC_FENCE_OFF _MMIO(0x3218) /* BSpec typo has 321Bh */
+#define FBC_TAG(i) _MMIO(0x3300 + (i) * 4)
-#define FBC_STATUS2 0x43214
+#define FBC_STATUS2 _MMIO(0x43214)
#define FBC_COMPRESSION_MASK 0x7ff
#define FBC_LL_SIZE (1536)
/* Framebuffer compression for GM45+ */
-#define DPFC_CB_BASE 0x3200
-#define DPFC_CONTROL 0x3208
+#define DPFC_CB_BASE _MMIO(0x3200)
+#define DPFC_CONTROL _MMIO(0x3208)
#define DPFC_CTL_EN (1<<31)
#define DPFC_CTL_PLANE(plane) ((plane)<<30)
#define IVB_DPFC_CTL_PLANE(plane) ((plane)<<29)
@@ -2064,37 +2124,37 @@ enum skl_disp_power_wells {
#define DPFC_CTL_LIMIT_1X (0<<6)
#define DPFC_CTL_LIMIT_2X (1<<6)
#define DPFC_CTL_LIMIT_4X (2<<6)
-#define DPFC_RECOMP_CTL 0x320c
+#define DPFC_RECOMP_CTL _MMIO(0x320c)
#define DPFC_RECOMP_STALL_EN (1<<27)
#define DPFC_RECOMP_STALL_WM_SHIFT (16)
#define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000)
#define DPFC_RECOMP_TIMER_COUNT_SHIFT (0)
#define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f)
-#define DPFC_STATUS 0x3210
+#define DPFC_STATUS _MMIO(0x3210)
#define DPFC_INVAL_SEG_SHIFT (16)
#define DPFC_INVAL_SEG_MASK (0x07ff0000)
#define DPFC_COMP_SEG_SHIFT (0)
#define DPFC_COMP_SEG_MASK (0x000003ff)
-#define DPFC_STATUS2 0x3214
-#define DPFC_FENCE_YOFF 0x3218
-#define DPFC_CHICKEN 0x3224
+#define DPFC_STATUS2 _MMIO(0x3214)
+#define DPFC_FENCE_YOFF _MMIO(0x3218)
+#define DPFC_CHICKEN _MMIO(0x3224)
#define DPFC_HT_MODIFY (1<<31)
/* Framebuffer compression for Ironlake */
-#define ILK_DPFC_CB_BASE 0x43200
-#define ILK_DPFC_CONTROL 0x43208
+#define ILK_DPFC_CB_BASE _MMIO(0x43200)
+#define ILK_DPFC_CONTROL _MMIO(0x43208)
#define FBC_CTL_FALSE_COLOR (1<<10)
/* The bit 28-8 is reserved */
#define DPFC_RESERVED (0x1FFFFF00)
-#define ILK_DPFC_RECOMP_CTL 0x4320c
-#define ILK_DPFC_STATUS 0x43210
-#define ILK_DPFC_FENCE_YOFF 0x43218
-#define ILK_DPFC_CHICKEN 0x43224
-#define ILK_FBC_RT_BASE 0x2128
+#define ILK_DPFC_RECOMP_CTL _MMIO(0x4320c)
+#define ILK_DPFC_STATUS _MMIO(0x43210)
+#define ILK_DPFC_FENCE_YOFF _MMIO(0x43218)
+#define ILK_DPFC_CHICKEN _MMIO(0x43224)
+#define ILK_FBC_RT_BASE _MMIO(0x2128)
#define ILK_FBC_RT_VALID (1<<0)
#define SNB_FBC_FRONT_BUFFER (1<<1)
-#define ILK_DISPLAY_CHICKEN1 0x42000
+#define ILK_DISPLAY_CHICKEN1 _MMIO(0x42000)
#define ILK_FBCQ_DIS (1<<22)
#define ILK_PABSTRETCH_DIS (1<<21)
@@ -2104,31 +2164,31 @@ enum skl_disp_power_wells {
*
* The following two registers are of type GTTMMADR
*/
-#define SNB_DPFC_CTL_SA 0x100100
+#define SNB_DPFC_CTL_SA _MMIO(0x100100)
#define SNB_CPU_FENCE_ENABLE (1<<29)
-#define DPFC_CPU_FENCE_OFFSET 0x100104
+#define DPFC_CPU_FENCE_OFFSET _MMIO(0x100104)
/* Framebuffer compression for Ivybridge */
-#define IVB_FBC_RT_BASE 0x7020
+#define IVB_FBC_RT_BASE _MMIO(0x7020)
-#define IPS_CTL 0x43408
+#define IPS_CTL _MMIO(0x43408)
#define IPS_ENABLE (1 << 31)
-#define MSG_FBC_REND_STATE 0x50380
+#define MSG_FBC_REND_STATE _MMIO(0x50380)
#define FBC_REND_NUKE (1<<2)
#define FBC_REND_CACHE_CLEAN (1<<1)
/*
* GPIO regs
*/
-#define GPIOA 0x5010
-#define GPIOB 0x5014
-#define GPIOC 0x5018
-#define GPIOD 0x501c
-#define GPIOE 0x5020
-#define GPIOF 0x5024
-#define GPIOG 0x5028
-#define GPIOH 0x502c
+#define GPIOA _MMIO(0x5010)
+#define GPIOB _MMIO(0x5014)
+#define GPIOC _MMIO(0x5018)
+#define GPIOD _MMIO(0x501c)
+#define GPIOE _MMIO(0x5020)
+#define GPIOF _MMIO(0x5024)
+#define GPIOG _MMIO(0x5028)
+#define GPIOH _MMIO(0x502c)
# define GPIO_CLOCK_DIR_MASK (1 << 0)
# define GPIO_CLOCK_DIR_IN (0 << 1)
# define GPIO_CLOCK_DIR_OUT (1 << 1)
@@ -2144,7 +2204,7 @@ enum skl_disp_power_wells {
# define GPIO_DATA_VAL_IN (1 << 12)
# define GPIO_DATA_PULLUP_DISABLE (1 << 13)
-#define GMBUS0 (dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */
+#define GMBUS0 _MMIO(dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */
#define GMBUS_RATE_100KHZ (0<<8)
#define GMBUS_RATE_50KHZ (1<<8)
#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
@@ -2163,7 +2223,7 @@ enum skl_disp_power_wells {
#define GMBUS_PIN_2_BXT 2
#define GMBUS_PIN_3_BXT 3
#define GMBUS_NUM_PINS 7 /* including 0 */
-#define GMBUS1 (dev_priv->gpio_mmio_base + 0x5104) /* command/status */
+#define GMBUS1 _MMIO(dev_priv->gpio_mmio_base + 0x5104) /* command/status */
#define GMBUS_SW_CLR_INT (1<<31)
#define GMBUS_SW_RDY (1<<30)
#define GMBUS_ENT (1<<29) /* enable timeout */
@@ -2177,7 +2237,7 @@ enum skl_disp_power_wells {
#define GMBUS_SLAVE_ADDR_SHIFT 1
#define GMBUS_SLAVE_READ (1<<0)
#define GMBUS_SLAVE_WRITE (0<<0)
-#define GMBUS2 (dev_priv->gpio_mmio_base + 0x5108) /* status */
+#define GMBUS2 _MMIO(dev_priv->gpio_mmio_base + 0x5108) /* status */
#define GMBUS_INUSE (1<<15)
#define GMBUS_HW_WAIT_PHASE (1<<14)
#define GMBUS_STALL_TIMEOUT (1<<13)
@@ -2185,14 +2245,14 @@ enum skl_disp_power_wells {
#define GMBUS_HW_RDY (1<<11)
#define GMBUS_SATOER (1<<10)
#define GMBUS_ACTIVE (1<<9)
-#define GMBUS3 (dev_priv->gpio_mmio_base + 0x510c) /* data buffer bytes 3-0 */
-#define GMBUS4 (dev_priv->gpio_mmio_base + 0x5110) /* interrupt mask (Pineview+) */
+#define GMBUS3 _MMIO(dev_priv->gpio_mmio_base + 0x510c) /* data buffer bytes 3-0 */
+#define GMBUS4 _MMIO(dev_priv->gpio_mmio_base + 0x5110) /* interrupt mask (Pineview+) */
#define GMBUS_SLAVE_TIMEOUT_EN (1<<4)
#define GMBUS_NAK_EN (1<<3)
#define GMBUS_IDLE_EN (1<<2)
#define GMBUS_HW_WAIT_EN (1<<1)
#define GMBUS_HW_RDY_EN (1<<0)
-#define GMBUS5 (dev_priv->gpio_mmio_base + 0x5120) /* byte index */
+#define GMBUS5 _MMIO(dev_priv->gpio_mmio_base + 0x5120) /* byte index */
#define GMBUS_2BYTE_INDEX_EN (1<<31)
/*
@@ -2201,11 +2261,11 @@ enum skl_disp_power_wells {
#define _DPLL_A (dev_priv->info.display_mmio_offset + 0x6014)
#define _DPLL_B (dev_priv->info.display_mmio_offset + 0x6018)
#define _CHV_DPLL_C (dev_priv->info.display_mmio_offset + 0x6030)
-#define DPLL(pipe) _PIPE3((pipe), _DPLL_A, _DPLL_B, _CHV_DPLL_C)
+#define DPLL(pipe) _MMIO_PIPE3((pipe), _DPLL_A, _DPLL_B, _CHV_DPLL_C)
-#define VGA0 0x6000
-#define VGA1 0x6004
-#define VGA_PD 0x6010
+#define VGA0 _MMIO(0x6000)
+#define VGA1 _MMIO(0x6004)
+#define VGA_PD _MMIO(0x6010)
#define VGA0_PD_P2_DIV_4 (1 << 7)
#define VGA0_PD_P1_DIV_2 (1 << 5)
#define VGA0_PD_P1_SHIFT 0
@@ -2241,9 +2301,9 @@ enum skl_disp_power_wells {
#define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
/* Additional CHV pll/phy registers */
-#define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240)
+#define DPIO_PHY_STATUS _MMIO(VLV_DISPLAY_BASE + 0x6240)
#define DPLL_PORTD_READY_MASK (0xf)
-#define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100)
+#define DISPLAY_PHY_CONTROL _MMIO(VLV_DISPLAY_BASE + 0x60100)
#define PHY_CH_POWER_DOWN_OVRD_EN(phy, ch) (1 << (2*(phy)+(ch)+27))
#define PHY_LDO_DELAY_0NS 0x0
#define PHY_LDO_DELAY_200NS 0x1
@@ -2254,7 +2314,7 @@ enum skl_disp_power_wells {
#define PHY_CH_DEEP_PSR 0x7
#define PHY_CH_POWER_MODE(mode, phy, ch) ((mode) << (6*(phy)+3*(ch)+2))
#define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy))
-#define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104)
+#define DISPLAY_PHY_STATUS _MMIO(VLV_DISPLAY_BASE + 0x60104)
#define PHY_POWERGOOD(phy) (((phy) == DPIO_PHY0) ? (1<<31) : (1<<30))
#define PHY_STATUS_CMN_LDO(phy, ch) (1 << (6-(6*(phy)+3*(ch))))
#define PHY_STATUS_SPLINE_LDO(phy, ch, spline) (1 << (8-(6*(phy)+3*(ch)+(spline))))
@@ -2300,7 +2360,7 @@ enum skl_disp_power_wells {
#define _DPLL_A_MD (dev_priv->info.display_mmio_offset + 0x601c)
#define _DPLL_B_MD (dev_priv->info.display_mmio_offset + 0x6020)
#define _CHV_DPLL_C_MD (dev_priv->info.display_mmio_offset + 0x603c)
-#define DPLL_MD(pipe) _PIPE3((pipe), _DPLL_A_MD, _DPLL_B_MD, _CHV_DPLL_C_MD)
+#define DPLL_MD(pipe) _MMIO_PIPE3((pipe), _DPLL_A_MD, _DPLL_B_MD, _CHV_DPLL_C_MD)
/*
* UDI pixel divider, controlling how many pixels are stuffed into a packet.
@@ -2339,12 +2399,12 @@ enum skl_disp_power_wells {
#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
-#define _FPA0 0x06040
-#define _FPA1 0x06044
-#define _FPB0 0x06048
-#define _FPB1 0x0604c
-#define FP0(pipe) _PIPE(pipe, _FPA0, _FPB0)
-#define FP1(pipe) _PIPE(pipe, _FPA1, _FPB1)
+#define _FPA0 0x6040
+#define _FPA1 0x6044
+#define _FPB0 0x6048
+#define _FPB1 0x604c
+#define FP0(pipe) _MMIO_PIPE(pipe, _FPA0, _FPB0)
+#define FP1(pipe) _MMIO_PIPE(pipe, _FPA1, _FPB1)
#define FP_N_DIV_MASK 0x003f0000
#define FP_N_PINEVIEW_DIV_MASK 0x00ff0000
#define FP_N_DIV_SHIFT 16
@@ -2353,7 +2413,7 @@ enum skl_disp_power_wells {
#define FP_M2_DIV_MASK 0x0000003f
#define FP_M2_PINEVIEW_DIV_MASK 0x000000ff
#define FP_M2_DIV_SHIFT 0
-#define DPLL_TEST 0x606c
+#define DPLL_TEST _MMIO(0x606c)
#define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
#define DPLLB_TEST_SDVO_DIV_2 (1 << 22)
#define DPLLB_TEST_SDVO_DIV_4 (2 << 22)
@@ -2364,12 +2424,12 @@ enum skl_disp_power_wells {
#define DPLLA_TEST_N_BYPASS (1 << 3)
#define DPLLA_TEST_M_BYPASS (1 << 2)
#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
-#define D_STATE 0x6104
+#define D_STATE _MMIO(0x6104)
#define DSTATE_GFX_RESET_I830 (1<<6)
#define DSTATE_PLL_D3_OFF (1<<3)
#define DSTATE_GFX_CLOCK_GATING (1<<1)
#define DSTATE_DOT_CLOCK_GATING (1<<0)
-#define DSPCLK_GATE_D (dev_priv->info.display_mmio_offset + 0x6200)
+#define DSPCLK_GATE_D _MMIO(dev_priv->info.display_mmio_offset + 0x6200)
# define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */
# define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */
# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */
@@ -2408,7 +2468,7 @@ enum skl_disp_power_wells {
# define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */
# define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */
-#define RENCLK_GATE_D1 0x6204
+#define RENCLK_GATE_D1 _MMIO(0x6204)
# define BLITTER_CLOCK_GATE_DISABLE (1 << 13) /* 945GM only */
# define MPEG_CLOCK_GATE_DISABLE (1 << 12) /* 945GM only */
# define PC_FE_CLOCK_GATE_DISABLE (1 << 11)
@@ -2472,35 +2532,35 @@ enum skl_disp_power_wells {
# define I965_FT_CLOCK_GATE_DISABLE (1 << 1)
# define I965_DM_CLOCK_GATE_DISABLE (1 << 0)
-#define RENCLK_GATE_D2 0x6208
+#define RENCLK_GATE_D2 _MMIO(0x6208)
#define VF_UNIT_CLOCK_GATE_DISABLE (1 << 9)
#define GS_UNIT_CLOCK_GATE_DISABLE (1 << 7)
#define CL_UNIT_CLOCK_GATE_DISABLE (1 << 6)
-#define VDECCLK_GATE_D 0x620C /* g4x only */
+#define VDECCLK_GATE_D _MMIO(0x620C) /* g4x only */
#define VCP_UNIT_CLOCK_GATE_DISABLE (1 << 4)
-#define RAMCLK_GATE_D 0x6210 /* CRL only */
-#define DEUC 0x6214 /* CRL only */
+#define RAMCLK_GATE_D _MMIO(0x6210) /* CRL only */
+#define DEUC _MMIO(0x6214) /* CRL only */
-#define FW_BLC_SELF_VLV (VLV_DISPLAY_BASE + 0x6500)
+#define FW_BLC_SELF_VLV _MMIO(VLV_DISPLAY_BASE + 0x6500)
#define FW_CSPWRDWNEN (1<<15)
-#define MI_ARB_VLV (VLV_DISPLAY_BASE + 0x6504)
+#define MI_ARB_VLV _MMIO(VLV_DISPLAY_BASE + 0x6504)
-#define CZCLK_CDCLK_FREQ_RATIO (VLV_DISPLAY_BASE + 0x6508)
+#define CZCLK_CDCLK_FREQ_RATIO _MMIO(VLV_DISPLAY_BASE + 0x6508)
#define CDCLK_FREQ_SHIFT 4
#define CDCLK_FREQ_MASK (0x1f << CDCLK_FREQ_SHIFT)
#define CZCLK_FREQ_MASK 0xf
-#define GCI_CONTROL (VLV_DISPLAY_BASE + 0x650C)
+#define GCI_CONTROL _MMIO(VLV_DISPLAY_BASE + 0x650C)
#define PFI_CREDIT_63 (9 << 28) /* chv only */
#define PFI_CREDIT_31 (8 << 28) /* chv only */
#define PFI_CREDIT(x) (((x) - 8) << 28) /* 8-15 */
#define PFI_CREDIT_RESEND (1 << 27)
#define VGA_FAST_MODE_DISABLE (1 << 14)
-#define GMBUSFREQ_VLV (VLV_DISPLAY_BASE + 0x6510)
+#define GMBUSFREQ_VLV _MMIO(VLV_DISPLAY_BASE + 0x6510)
/*
* Palette regs
@@ -2508,8 +2568,8 @@ enum skl_disp_power_wells {
#define PALETTE_A_OFFSET 0xa000
#define PALETTE_B_OFFSET 0xa800
#define CHV_PALETTE_C_OFFSET 0xc000
-#define PALETTE(pipe, i) (dev_priv->info.palette_offsets[pipe] + \
- dev_priv->info.display_mmio_offset + (i) * 4)
+#define PALETTE(pipe, i) _MMIO(dev_priv->info.palette_offsets[pipe] + \
+ dev_priv->info.display_mmio_offset + (i) * 4)
/* MCH MMIO space */
@@ -2527,37 +2587,37 @@ enum skl_disp_power_wells {
#define MCHBAR_MIRROR_BASE_SNB 0x140000
-#define CTG_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x34)
-#define ELK_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x48)
+#define CTG_STOLEN_RESERVED _MMIO(MCHBAR_MIRROR_BASE + 0x34)
+#define ELK_STOLEN_RESERVED _MMIO(MCHBAR_MIRROR_BASE + 0x48)
#define G4X_STOLEN_RESERVED_ADDR1_MASK (0xFFFF << 16)
#define G4X_STOLEN_RESERVED_ADDR2_MASK (0xFFF << 4)
/* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */
-#define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04)
+#define DCLK _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5e04)
/* 915-945 and GM965 MCH register controlling DRAM channel access */
-#define DCC 0x10200
+#define DCC _MMIO(MCHBAR_MIRROR_BASE + 0x200)
#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL (0 << 0)
#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC (1 << 0)
#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED (2 << 0)
#define DCC_ADDRESSING_MODE_MASK (3 << 0)
#define DCC_CHANNEL_XOR_DISABLE (1 << 10)
#define DCC_CHANNEL_XOR_BIT_17 (1 << 9)
-#define DCC2 0x10204
+#define DCC2 _MMIO(MCHBAR_MIRROR_BASE + 0x204)
#define DCC2_MODIFIED_ENHANCED_DISABLE (1 << 20)
/* Pineview MCH register contains DDR3 setting */
-#define CSHRDDR3CTL 0x101a8
+#define CSHRDDR3CTL _MMIO(MCHBAR_MIRROR_BASE + 0x1a8)
#define CSHRDDR3CTL_DDR3 (1 << 2)
/* 965 MCH register controlling DRAM channel configuration */
-#define C0DRB3 0x10206
-#define C1DRB3 0x10606
+#define C0DRB3 _MMIO(MCHBAR_MIRROR_BASE + 0x206)
+#define C1DRB3 _MMIO(MCHBAR_MIRROR_BASE + 0x606)
/* snb MCH registers for reading the DRAM channel configuration */
-#define MAD_DIMM_C0 (MCHBAR_MIRROR_BASE_SNB + 0x5004)
-#define MAD_DIMM_C1 (MCHBAR_MIRROR_BASE_SNB + 0x5008)
-#define MAD_DIMM_C2 (MCHBAR_MIRROR_BASE_SNB + 0x500C)
+#define MAD_DIMM_C0 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5004)
+#define MAD_DIMM_C1 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5008)
+#define MAD_DIMM_C2 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C)
#define MAD_DIMM_ECC_MASK (0x3 << 24)
#define MAD_DIMM_ECC_OFF (0x0 << 24)
#define MAD_DIMM_ECC_IO_ON_LOGIC_OFF (0x1 << 24)
@@ -2577,14 +2637,14 @@ enum skl_disp_power_wells {
#define MAD_DIMM_A_SIZE_MASK (0xff << MAD_DIMM_A_SIZE_SHIFT)
/* snb MCH registers for priority tuning */
-#define MCH_SSKPD (MCHBAR_MIRROR_BASE_SNB + 0x5d10)
+#define MCH_SSKPD _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5d10)
#define MCH_SSKPD_WM0_MASK 0x3f
#define MCH_SSKPD_WM0_VAL 0xc
-#define MCH_SECP_NRG_STTS (MCHBAR_MIRROR_BASE_SNB + 0x592c)
+#define MCH_SECP_NRG_STTS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x592c)
/* Clocking configuration register */
-#define CLKCFG 0x10c00
+#define CLKCFG _MMIO(MCHBAR_MIRROR_BASE + 0xc00)
#define CLKCFG_FSB_400 (5 << 0) /* hrawclk 100 */
#define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */
#define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */
@@ -2600,26 +2660,26 @@ enum skl_disp_power_wells {
#define CLKCFG_MEM_800 (3 << 4)
#define CLKCFG_MEM_MASK (7 << 4)
-#define HPLLVCO (MCHBAR_MIRROR_BASE + 0xc38)
-#define HPLLVCO_MOBILE (MCHBAR_MIRROR_BASE + 0xc0f)
+#define HPLLVCO _MMIO(MCHBAR_MIRROR_BASE + 0xc38)
+#define HPLLVCO_MOBILE _MMIO(MCHBAR_MIRROR_BASE + 0xc0f)
-#define TSC1 0x11001
+#define TSC1 _MMIO(0x11001)
#define TSE (1<<0)
-#define TR1 0x11006
-#define TSFS 0x11020
+#define TR1 _MMIO(0x11006)
+#define TSFS _MMIO(0x11020)
#define TSFS_SLOPE_MASK 0x0000ff00
#define TSFS_SLOPE_SHIFT 8
#define TSFS_INTR_MASK 0x000000ff
-#define CRSTANDVID 0x11100
-#define PXVFREQ(i) (0x11110 + (i) * 4) /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
+#define CRSTANDVID _MMIO(0x11100)
+#define PXVFREQ(fstart) _MMIO(0x11110 + (fstart) * 4) /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
#define PXVFREQ_PX_MASK 0x7f000000
#define PXVFREQ_PX_SHIFT 24
-#define VIDFREQ_BASE 0x11110
-#define VIDFREQ1 0x11110 /* VIDFREQ1-4 (0x1111c) (Cantiga) */
-#define VIDFREQ2 0x11114
-#define VIDFREQ3 0x11118
-#define VIDFREQ4 0x1111c
+#define VIDFREQ_BASE _MMIO(0x11110)
+#define VIDFREQ1 _MMIO(0x11110) /* VIDFREQ1-4 (0x1111c) (Cantiga) */
+#define VIDFREQ2 _MMIO(0x11114)
+#define VIDFREQ3 _MMIO(0x11118)
+#define VIDFREQ4 _MMIO(0x1111c)
#define VIDFREQ_P0_MASK 0x1f000000
#define VIDFREQ_P0_SHIFT 24
#define VIDFREQ_P0_CSCLK_MASK 0x00f00000
@@ -2631,8 +2691,8 @@ enum skl_disp_power_wells {
#define VIDFREQ_P1_CSCLK_MASK 0x000000f0
#define VIDFREQ_P1_CSCLK_SHIFT 4
#define VIDFREQ_P1_CRCLK_MASK 0x0000000f
-#define INTTOEXT_BASE_ILK 0x11300
-#define INTTOEXT_BASE 0x11120 /* INTTOEXT1-8 (0x1113c) */
+#define INTTOEXT_BASE_ILK _MMIO(0x11300)
+#define INTTOEXT_BASE _MMIO(0x11120) /* INTTOEXT1-8 (0x1113c) */
#define INTTOEXT_MAP3_SHIFT 24
#define INTTOEXT_MAP3_MASK (0x1f << INTTOEXT_MAP3_SHIFT)
#define INTTOEXT_MAP2_SHIFT 16
@@ -2641,7 +2701,7 @@ enum skl_disp_power_wells {
#define INTTOEXT_MAP1_MASK (0x1f << INTTOEXT_MAP1_SHIFT)
#define INTTOEXT_MAP0_SHIFT 0
#define INTTOEXT_MAP0_MASK (0x1f << INTTOEXT_MAP0_SHIFT)
-#define MEMSWCTL 0x11170 /* Ironlake only */
+#define MEMSWCTL _MMIO(0x11170) /* Ironlake only */
#define MEMCTL_CMD_MASK 0xe000
#define MEMCTL_CMD_SHIFT 13
#define MEMCTL_CMD_RCLK_OFF 0
@@ -2656,8 +2716,8 @@ enum skl_disp_power_wells {
#define MEMCTL_FREQ_SHIFT 8
#define MEMCTL_SFCAVM (1<<7)
#define MEMCTL_TGT_VID_MASK 0x007f
-#define MEMIHYST 0x1117c
-#define MEMINTREN 0x11180 /* 16 bits */
+#define MEMIHYST _MMIO(0x1117c)
+#define MEMINTREN _MMIO(0x11180) /* 16 bits */
#define MEMINT_RSEXIT_EN (1<<8)
#define MEMINT_CX_SUPR_EN (1<<7)
#define MEMINT_CONT_BUSY_EN (1<<6)
@@ -2667,7 +2727,7 @@ enum skl_disp_power_wells {
#define MEMINT_UP_EVAL_EN (1<<2)
#define MEMINT_DOWN_EVAL_EN (1<<1)
#define MEMINT_SW_CMD_EN (1<<0)
-#define MEMINTRSTR 0x11182 /* 16 bits */
+#define MEMINTRSTR _MMIO(0x11182) /* 16 bits */
#define MEM_RSEXIT_MASK 0xc000
#define MEM_RSEXIT_SHIFT 14
#define MEM_CONT_BUSY_MASK 0x3000
@@ -2687,7 +2747,7 @@ enum skl_disp_power_wells {
#define MEM_INT_STEER_CMR 1
#define MEM_INT_STEER_SMI 2
#define MEM_INT_STEER_SCI 3
-#define MEMINTRSTS 0x11184
+#define MEMINTRSTS _MMIO(0x11184)
#define MEMINT_RSEXIT (1<<7)
#define MEMINT_CONT_BUSY (1<<6)
#define MEMINT_AVG_BUSY (1<<5)
@@ -2696,7 +2756,7 @@ enum skl_disp_power_wells {
#define MEMINT_UP_EVAL (1<<2)
#define MEMINT_DOWN_EVAL (1<<1)
#define MEMINT_SW_CMD (1<<0)
-#define MEMMODECTL 0x11190
+#define MEMMODECTL _MMIO(0x11190)
#define MEMMODE_BOOST_EN (1<<31)
#define MEMMODE_BOOST_FREQ_MASK 0x0f000000 /* jitter for boost, 0-15 */
#define MEMMODE_BOOST_FREQ_SHIFT 24
@@ -2713,8 +2773,8 @@ enum skl_disp_power_wells {
#define MEMMODE_FMAX_MASK 0x000000f0 /* max jitter, 0-15 */
#define MEMMODE_FMAX_SHIFT 4
#define MEMMODE_FMIN_MASK 0x0000000f /* min jitter, 0-15 */
-#define RCBMAXAVG 0x1119c
-#define MEMSWCTL2 0x1119e /* Cantiga only */
+#define RCBMAXAVG _MMIO(0x1119c)
+#define MEMSWCTL2 _MMIO(0x1119e) /* Cantiga only */
#define SWMEMCMD_RENDER_OFF (0 << 13)
#define SWMEMCMD_RENDER_ON (1 << 13)
#define SWMEMCMD_SWFREQ (2 << 13)
@@ -2726,11 +2786,11 @@ enum skl_disp_power_wells {
#define SWFREQ_MASK 0x0380 /* P0-7 */
#define SWFREQ_SHIFT 7
#define TARVID_MASK 0x001f
-#define MEMSTAT_CTG 0x111a0
-#define RCBMINAVG 0x111a0
-#define RCUPEI 0x111b0
-#define RCDNEI 0x111b4
-#define RSTDBYCTL 0x111b8
+#define MEMSTAT_CTG _MMIO(0x111a0)
+#define RCBMINAVG _MMIO(0x111a0)
+#define RCUPEI _MMIO(0x111b0)
+#define RCDNEI _MMIO(0x111b4)
+#define RSTDBYCTL _MMIO(0x111b8)
#define RS1EN (1<<31)
#define RS2EN (1<<30)
#define RS3EN (1<<29)
@@ -2774,10 +2834,10 @@ enum skl_disp_power_wells {
#define RS_CSTATE_C367_RS2 (3<<4)
#define REDSAVES (1<<3) /* no context save if was idle during rs0 */
#define REDRESTORES (1<<2) /* no restore if was idle during rs0 */
-#define VIDCTL 0x111c0
-#define VIDSTS 0x111c8
-#define VIDSTART 0x111cc /* 8 bits */
-#define MEMSTAT_ILK 0x111f8
+#define VIDCTL _MMIO(0x111c0)
+#define VIDSTS _MMIO(0x111c8)
+#define VIDSTART _MMIO(0x111cc) /* 8 bits */
+#define MEMSTAT_ILK _MMIO(0x111f8)
#define MEMSTAT_VID_MASK 0x7f00
#define MEMSTAT_VID_SHIFT 8
#define MEMSTAT_PSTATE_MASK 0x00f8
@@ -2788,55 +2848,55 @@ enum skl_disp_power_wells {
#define MEMSTAT_SRC_CTL_TRB 1
#define MEMSTAT_SRC_CTL_THM 2
#define MEMSTAT_SRC_CTL_STDBY 3
-#define RCPREVBSYTUPAVG 0x113b8
-#define RCPREVBSYTDNAVG 0x113bc
-#define PMMISC 0x11214
+#define RCPREVBSYTUPAVG _MMIO(0x113b8)
+#define RCPREVBSYTDNAVG _MMIO(0x113bc)
+#define PMMISC _MMIO(0x11214)
#define MCPPCE_EN (1<<0) /* enable PM_MSG from PCH->MPC */
-#define SDEW 0x1124c
-#define CSIEW0 0x11250
-#define CSIEW1 0x11254
-#define CSIEW2 0x11258
-#define PEW(i) (0x1125c + (i) * 4) /* 5 registers */
-#define DEW(i) (0x11270 + (i) * 4) /* 3 registers */
-#define MCHAFE 0x112c0
-#define CSIEC 0x112e0
-#define DMIEC 0x112e4
-#define DDREC 0x112e8
-#define PEG0EC 0x112ec
-#define PEG1EC 0x112f0
-#define GFXEC 0x112f4
-#define RPPREVBSYTUPAVG 0x113b8
-#define RPPREVBSYTDNAVG 0x113bc
-#define ECR 0x11600
+#define SDEW _MMIO(0x1124c)
+#define CSIEW0 _MMIO(0x11250)
+#define CSIEW1 _MMIO(0x11254)
+#define CSIEW2 _MMIO(0x11258)
+#define PEW(i) _MMIO(0x1125c + (i) * 4) /* 5 registers */
+#define DEW(i) _MMIO(0x11270 + (i) * 4) /* 3 registers */
+#define MCHAFE _MMIO(0x112c0)
+#define CSIEC _MMIO(0x112e0)
+#define DMIEC _MMIO(0x112e4)
+#define DDREC _MMIO(0x112e8)
+#define PEG0EC _MMIO(0x112ec)
+#define PEG1EC _MMIO(0x112f0)
+#define GFXEC _MMIO(0x112f4)
+#define RPPREVBSYTUPAVG _MMIO(0x113b8)
+#define RPPREVBSYTDNAVG _MMIO(0x113bc)
+#define ECR _MMIO(0x11600)
#define ECR_GPFE (1<<31)
#define ECR_IMONE (1<<30)
#define ECR_CAP_MASK 0x0000001f /* Event range, 0-31 */
-#define OGW0 0x11608
-#define OGW1 0x1160c
-#define EG0 0x11610
-#define EG1 0x11614
-#define EG2 0x11618
-#define EG3 0x1161c
-#define EG4 0x11620
-#define EG5 0x11624
-#define EG6 0x11628
-#define EG7 0x1162c
-#define PXW(i) (0x11664 + (i) * 4) /* 4 registers */
-#define PXWL(i) (0x11680 + (i) * 4) /* 8 registers */
-#define LCFUSE02 0x116c0
+#define OGW0 _MMIO(0x11608)
+#define OGW1 _MMIO(0x1160c)
+#define EG0 _MMIO(0x11610)
+#define EG1 _MMIO(0x11614)
+#define EG2 _MMIO(0x11618)
+#define EG3 _MMIO(0x1161c)
+#define EG4 _MMIO(0x11620)
+#define EG5 _MMIO(0x11624)
+#define EG6 _MMIO(0x11628)
+#define EG7 _MMIO(0x1162c)
+#define PXW(i) _MMIO(0x11664 + (i) * 4) /* 4 registers */
+#define PXWL(i) _MMIO(0x11680 + (i) * 8) /* 8 registers */
+#define LCFUSE02 _MMIO(0x116c0)
#define LCFUSE_HIV_MASK 0x000000ff
-#define CSIPLL0 0x12c10
-#define DDRMPLL1 0X12c20
-#define PEG_BAND_GAP_DATA 0x14d68
+#define CSIPLL0 _MMIO(0x12c10)
+#define DDRMPLL1 _MMIO(0X12c20)
+#define PEG_BAND_GAP_DATA _MMIO(0x14d68)
-#define GEN6_GT_THREAD_STATUS_REG 0x13805c
+#define GEN6_GT_THREAD_STATUS_REG _MMIO(0x13805c)
#define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7
-#define GEN6_GT_PERF_STATUS (MCHBAR_MIRROR_BASE_SNB + 0x5948)
-#define BXT_GT_PERF_STATUS (MCHBAR_MIRROR_BASE_SNB + 0x7070)
-#define GEN6_RP_STATE_LIMITS (MCHBAR_MIRROR_BASE_SNB + 0x5994)
-#define GEN6_RP_STATE_CAP (MCHBAR_MIRROR_BASE_SNB + 0x5998)
-#define BXT_RP_STATE_CAP 0x138170
+#define GEN6_GT_PERF_STATUS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5948)
+#define BXT_GT_PERF_STATUS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x7070)
+#define GEN6_RP_STATE_LIMITS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5994)
+#define GEN6_RP_STATE_CAP _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5998)
+#define BXT_RP_STATE_CAP _MMIO(0x138170)
#define INTERVAL_1_28_US(us) (((us) * 100) >> 7)
#define INTERVAL_1_33_US(us) (((us) * 3) >> 2)
@@ -2850,7 +2910,7 @@ enum skl_disp_power_wells {
/*
* Logical Context regs
*/
-#define CCID 0x2180
+#define CCID _MMIO(0x2180)
#define CCID_EN (1<<0)
/*
* Notes on SNB/IVB/VLV context size:
@@ -2865,7 +2925,7 @@ enum skl_disp_power_wells {
* - GT1 size just indicates how much of render context
* doesn't need saving on GT1
*/
-#define CXT_SIZE 0x21a0
+#define CXT_SIZE _MMIO(0x21a0)
#define GEN6_CXT_POWER_SIZE(cxt_reg) (((cxt_reg) >> 24) & 0x3f)
#define GEN6_CXT_RING_SIZE(cxt_reg) (((cxt_reg) >> 18) & 0x3f)
#define GEN6_CXT_RENDER_SIZE(cxt_reg) (((cxt_reg) >> 12) & 0x3f)
@@ -2874,7 +2934,7 @@ enum skl_disp_power_wells {
#define GEN6_CXT_TOTAL_SIZE(cxt_reg) (GEN6_CXT_RING_SIZE(cxt_reg) + \
GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \
GEN6_CXT_PIPELINE_SIZE(cxt_reg))
-#define GEN7_CXT_SIZE 0x21a8
+#define GEN7_CXT_SIZE _MMIO(0x21a8)
#define GEN7_CXT_POWER_SIZE(ctx_reg) (((ctx_reg) >> 25) & 0x7f)
#define GEN7_CXT_RING_SIZE(ctx_reg) (((ctx_reg) >> 22) & 0x7)
#define GEN7_CXT_RENDER_SIZE(ctx_reg) (((ctx_reg) >> 16) & 0x3f)
@@ -2894,23 +2954,23 @@ enum skl_disp_power_wells {
/* Same as Haswell, but 72064 bytes now. */
#define GEN8_CXT_TOTAL_SIZE (18 * PAGE_SIZE)
-#define CHV_CLK_CTL1 0x101100
-#define VLV_CLK_CTL2 0x101104
+#define CHV_CLK_CTL1 _MMIO(0x101100)
+#define VLV_CLK_CTL2 _MMIO(0x101104)
#define CLK_CTL2_CZCOUNT_30NS_SHIFT 28
/*
* Overlay regs
*/
-#define OVADD 0x30000
-#define DOVSTA 0x30008
+#define OVADD _MMIO(0x30000)
+#define DOVSTA _MMIO(0x30008)
#define OC_BUF (0x3<<20)
-#define OGAMC5 0x30010
-#define OGAMC4 0x30014
-#define OGAMC3 0x30018
-#define OGAMC2 0x3001c
-#define OGAMC1 0x30020
-#define OGAMC0 0x30024
+#define OGAMC5 _MMIO(0x30010)
+#define OGAMC4 _MMIO(0x30014)
+#define OGAMC3 _MMIO(0x30018)
+#define OGAMC2 _MMIO(0x3001c)
+#define OGAMC1 _MMIO(0x30020)
+#define OGAMC0 _MMIO(0x30024)
/*
* Display engine regs
@@ -2970,28 +3030,18 @@ enum skl_disp_power_wells {
#define _PIPE_CRC_RES_4_B_IVB 0x61070
#define _PIPE_CRC_RES_5_B_IVB 0x61074
-#define PIPE_CRC_CTL(pipe) _TRANSCODER2(pipe, _PIPE_CRC_CTL_A)
-#define PIPE_CRC_RES_1_IVB(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_1_A_IVB)
-#define PIPE_CRC_RES_2_IVB(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_2_A_IVB)
-#define PIPE_CRC_RES_3_IVB(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_3_A_IVB)
-#define PIPE_CRC_RES_4_IVB(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_4_A_IVB)
-#define PIPE_CRC_RES_5_IVB(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_5_A_IVB)
-
-#define PIPE_CRC_RES_RED(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_RED_A)
-#define PIPE_CRC_RES_GREEN(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_GREEN_A)
-#define PIPE_CRC_RES_BLUE(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_BLUE_A)
-#define PIPE_CRC_RES_RES1_I915(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_RES1_A_I915)
-#define PIPE_CRC_RES_RES2_G4X(pipe) \
- _TRANSCODER2(pipe, _PIPE_CRC_RES_RES2_A_G4X)
+#define PIPE_CRC_CTL(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_CTL_A)
+#define PIPE_CRC_RES_1_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_1_A_IVB)
+#define PIPE_CRC_RES_2_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_2_A_IVB)
+#define PIPE_CRC_RES_3_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_3_A_IVB)
+#define PIPE_CRC_RES_4_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_4_A_IVB)
+#define PIPE_CRC_RES_5_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_5_A_IVB)
+
+#define PIPE_CRC_RES_RED(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_RED_A)
+#define PIPE_CRC_RES_GREEN(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_GREEN_A)
+#define PIPE_CRC_RES_BLUE(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_BLUE_A)
+#define PIPE_CRC_RES_RES1_I915(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_RES1_A_I915)
+#define PIPE_CRC_RES_RES2_G4X(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_RES2_A_G4X)
/* Pipe A timing regs */
#define _HTOTAL_A 0x60000
@@ -3023,20 +3073,20 @@ enum skl_disp_power_wells {
#define CHV_TRANSCODER_C_OFFSET 0x63000
#define TRANSCODER_EDP_OFFSET 0x6f000
-#define _TRANSCODER2(pipe, reg) (dev_priv->info.trans_offsets[(pipe)] - \
+#define _MMIO_TRANS2(pipe, reg) _MMIO(dev_priv->info.trans_offsets[(pipe)] - \
dev_priv->info.trans_offsets[TRANSCODER_A] + (reg) + \
dev_priv->info.display_mmio_offset)
-#define HTOTAL(trans) _TRANSCODER2(trans, _HTOTAL_A)
-#define HBLANK(trans) _TRANSCODER2(trans, _HBLANK_A)
-#define HSYNC(trans) _TRANSCODER2(trans, _HSYNC_A)
-#define VTOTAL(trans) _TRANSCODER2(trans, _VTOTAL_A)
-#define VBLANK(trans) _TRANSCODER2(trans, _VBLANK_A)
-#define VSYNC(trans) _TRANSCODER2(trans, _VSYNC_A)
-#define BCLRPAT(trans) _TRANSCODER2(trans, _BCLRPAT_A)
-#define VSYNCSHIFT(trans) _TRANSCODER2(trans, _VSYNCSHIFT_A)
-#define PIPESRC(trans) _TRANSCODER2(trans, _PIPEASRC)
-#define PIPE_MULT(trans) _TRANSCODER2(trans, _PIPE_MULT_A)
+#define HTOTAL(trans) _MMIO_TRANS2(trans, _HTOTAL_A)
+#define HBLANK(trans) _MMIO_TRANS2(trans, _HBLANK_A)
+#define HSYNC(trans) _MMIO_TRANS2(trans, _HSYNC_A)
+#define VTOTAL(trans) _MMIO_TRANS2(trans, _VTOTAL_A)
+#define VBLANK(trans) _MMIO_TRANS2(trans, _VBLANK_A)
+#define VSYNC(trans) _MMIO_TRANS2(trans, _VSYNC_A)
+#define BCLRPAT(trans) _MMIO_TRANS2(trans, _BCLRPAT_A)
+#define VSYNCSHIFT(trans) _MMIO_TRANS2(trans, _VSYNCSHIFT_A)
+#define PIPESRC(trans) _MMIO_TRANS2(trans, _PIPEASRC)
+#define PIPE_MULT(trans) _MMIO_TRANS2(trans, _PIPE_MULT_A)
/* VLV eDP PSR registers */
#define _PSRCTLA (VLV_DISPLAY_BASE + 0x60090)
@@ -3052,14 +3102,14 @@ enum skl_disp_power_wells {
#define VLV_EDP_PSR_DBL_FRAME (1<<10)
#define VLV_EDP_PSR_FRAME_COUNT_MASK (0xff<<16)
#define VLV_EDP_PSR_IDLE_FRAME_SHIFT 16
-#define VLV_PSRCTL(pipe) _PIPE(pipe, _PSRCTLA, _PSRCTLB)
+#define VLV_PSRCTL(pipe) _MMIO_PIPE(pipe, _PSRCTLA, _PSRCTLB)
#define _VSCSDPA (VLV_DISPLAY_BASE + 0x600a0)
#define _VSCSDPB (VLV_DISPLAY_BASE + 0x610a0)
#define VLV_EDP_PSR_SDP_FREQ_MASK (3<<30)
#define VLV_EDP_PSR_SDP_FREQ_ONCE (1<<31)
#define VLV_EDP_PSR_SDP_FREQ_EVFRAME (1<<30)
-#define VLV_VSCSDP(pipe) _PIPE(pipe, _VSCSDPA, _VSCSDPB)
+#define VLV_VSCSDP(pipe) _MMIO_PIPE(pipe, _VSCSDPA, _VSCSDPB)
#define _PSRSTATA (VLV_DISPLAY_BASE + 0x60094)
#define _PSRSTATB (VLV_DISPLAY_BASE + 0x61094)
@@ -3072,11 +3122,12 @@ enum skl_disp_power_wells {
#define VLV_EDP_PSR_ACTIVE_SF_UPDATE (4<<0)
#define VLV_EDP_PSR_EXIT (5<<0)
#define VLV_EDP_PSR_IN_TRANS (1<<7)
-#define VLV_PSRSTAT(pipe) _PIPE(pipe, _PSRSTATA, _PSRSTATB)
+#define VLV_PSRSTAT(pipe) _MMIO_PIPE(pipe, _PSRSTATA, _PSRSTATB)
/* HSW+ eDP PSR registers */
-#define EDP_PSR_BASE(dev) (IS_HASWELL(dev) ? 0x64800 : 0x6f800)
-#define EDP_PSR_CTL(dev) (EDP_PSR_BASE(dev) + 0)
+#define HSW_EDP_PSR_BASE 0x64800
+#define BDW_EDP_PSR_BASE 0x6f800
+#define EDP_PSR_CTL _MMIO(dev_priv->psr_mmio_base + 0)
#define EDP_PSR_ENABLE (1<<31)
#define BDW_PSR_SINGLE_FRAME (1<<30)
#define EDP_PSR_LINK_STANDBY (1<<27)
@@ -3099,14 +3150,10 @@ enum skl_disp_power_wells {
#define EDP_PSR_TP1_TIME_0us (3<<4)
#define EDP_PSR_IDLE_FRAME_SHIFT 0
-#define EDP_PSR_AUX_CTL(dev) (EDP_PSR_BASE(dev) + 0x10)
-#define EDP_PSR_AUX_DATA1(dev) (EDP_PSR_BASE(dev) + 0x14)
-#define EDP_PSR_AUX_DATA2(dev) (EDP_PSR_BASE(dev) + 0x18)
-#define EDP_PSR_AUX_DATA3(dev) (EDP_PSR_BASE(dev) + 0x1c)
-#define EDP_PSR_AUX_DATA4(dev) (EDP_PSR_BASE(dev) + 0x20)
-#define EDP_PSR_AUX_DATA5(dev) (EDP_PSR_BASE(dev) + 0x24)
+#define EDP_PSR_AUX_CTL _MMIO(dev_priv->psr_mmio_base + 0x10)
+#define EDP_PSR_AUX_DATA(i) _MMIO(dev_priv->psr_mmio_base + 0x14 + (i) * 4) /* 5 registers */
-#define EDP_PSR_STATUS_CTL(dev) (EDP_PSR_BASE(dev) + 0x40)
+#define EDP_PSR_STATUS_CTL _MMIO(dev_priv->psr_mmio_base + 0x40)
#define EDP_PSR_STATUS_STATE_MASK (7<<29)
#define EDP_PSR_STATUS_STATE_IDLE (0<<29)
#define EDP_PSR_STATUS_STATE_SRDONACK (1<<29)
@@ -3130,15 +3177,15 @@ enum skl_disp_power_wells {
#define EDP_PSR_STATUS_SENDING_TP1 (1<<4)
#define EDP_PSR_STATUS_IDLE_MASK 0xf
-#define EDP_PSR_PERF_CNT(dev) (EDP_PSR_BASE(dev) + 0x44)
+#define EDP_PSR_PERF_CNT _MMIO(dev_priv->psr_mmio_base + 0x44)
#define EDP_PSR_PERF_CNT_MASK 0xffffff
-#define EDP_PSR_DEBUG_CTL(dev) (EDP_PSR_BASE(dev) + 0x60)
+#define EDP_PSR_DEBUG_CTL _MMIO(dev_priv->psr_mmio_base + 0x60)
#define EDP_PSR_DEBUG_MASK_LPSP (1<<27)
#define EDP_PSR_DEBUG_MASK_MEMUP (1<<26)
#define EDP_PSR_DEBUG_MASK_HPD (1<<25)
-#define EDP_PSR2_CTL 0x6f900
+#define EDP_PSR2_CTL _MMIO(0x6f900)
#define EDP_PSR2_ENABLE (1<<31)
#define EDP_SU_TRACK_ENABLE (1<<30)
#define EDP_MAX_SU_DISABLE_TIME(t) ((t)<<20)
@@ -3153,9 +3200,9 @@ enum skl_disp_power_wells {
#define EDP_PSR2_IDLE_MASK 0xf
/* VGA port control */
-#define ADPA 0x61100
-#define PCH_ADPA 0xe1100
-#define VLV_ADPA (VLV_DISPLAY_BASE + ADPA)
+#define ADPA _MMIO(0x61100)
+#define PCH_ADPA _MMIO(0xe1100)
+#define VLV_ADPA _MMIO(VLV_DISPLAY_BASE + 0x61100)
#define ADPA_DAC_ENABLE (1<<31)
#define ADPA_DAC_DISABLE 0
@@ -3201,7 +3248,7 @@ enum skl_disp_power_wells {
/* Hotplug control (945+ only) */
-#define PORT_HOTPLUG_EN (dev_priv->info.display_mmio_offset + 0x61110)
+#define PORT_HOTPLUG_EN _MMIO(dev_priv->info.display_mmio_offset + 0x61110)
#define PORTB_HOTPLUG_INT_EN (1 << 29)
#define PORTC_HOTPLUG_INT_EN (1 << 28)
#define PORTD_HOTPLUG_INT_EN (1 << 27)
@@ -3231,7 +3278,7 @@ enum skl_disp_power_wells {
#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
-#define PORT_HOTPLUG_STAT (dev_priv->info.display_mmio_offset + 0x61114)
+#define PORT_HOTPLUG_STAT _MMIO(dev_priv->info.display_mmio_offset + 0x61114)
/*
* HDMI/DP bits are gen4+
*
@@ -3296,21 +3343,23 @@ enum skl_disp_power_wells {
/* SDVO and HDMI port control.
* The same register may be used for SDVO or HDMI */
-#define GEN3_SDVOB 0x61140
-#define GEN3_SDVOC 0x61160
+#define _GEN3_SDVOB 0x61140
+#define _GEN3_SDVOC 0x61160
+#define GEN3_SDVOB _MMIO(_GEN3_SDVOB)
+#define GEN3_SDVOC _MMIO(_GEN3_SDVOC)
#define GEN4_HDMIB GEN3_SDVOB
#define GEN4_HDMIC GEN3_SDVOC
-#define VLV_HDMIB (VLV_DISPLAY_BASE + GEN4_HDMIB)
-#define VLV_HDMIC (VLV_DISPLAY_BASE + GEN4_HDMIC)
-#define CHV_HDMID (VLV_DISPLAY_BASE + 0x6116C)
-#define PCH_SDVOB 0xe1140
+#define VLV_HDMIB _MMIO(VLV_DISPLAY_BASE + 0x61140)
+#define VLV_HDMIC _MMIO(VLV_DISPLAY_BASE + 0x61160)
+#define CHV_HDMID _MMIO(VLV_DISPLAY_BASE + 0x6116C)
+#define PCH_SDVOB _MMIO(0xe1140)
#define PCH_HDMIB PCH_SDVOB
-#define PCH_HDMIC 0xe1150
-#define PCH_HDMID 0xe1160
+#define PCH_HDMIC _MMIO(0xe1150)
+#define PCH_HDMID _MMIO(0xe1160)
-#define PORT_DFT_I9XX 0x61150
+#define PORT_DFT_I9XX _MMIO(0x61150)
#define DC_BALANCE_RESET (1 << 25)
-#define PORT_DFT2_G4X (dev_priv->info.display_mmio_offset + 0x61154)
+#define PORT_DFT2_G4X _MMIO(dev_priv->info.display_mmio_offset + 0x61154)
#define DC_BALANCE_RESET_VLV (1 << 31)
#define PIPE_SCRAMBLE_RESET_MASK ((1 << 14) | (0x3 << 0))
#define PIPE_C_SCRAMBLE_RESET (1 << 14) /* chv */
@@ -3370,9 +3419,12 @@ enum skl_disp_power_wells {
/* DVO port control */
-#define DVOA 0x61120
-#define DVOB 0x61140
-#define DVOC 0x61160
+#define _DVOA 0x61120
+#define DVOA _MMIO(_DVOA)
+#define _DVOB 0x61140
+#define DVOB _MMIO(_DVOB)
+#define _DVOC 0x61160
+#define DVOC _MMIO(_DVOC)
#define DVO_ENABLE (1 << 31)
#define DVO_PIPE_B_SELECT (1 << 30)
#define DVO_PIPE_STALL_UNUSED (0 << 28)
@@ -3397,14 +3449,14 @@ enum skl_disp_power_wells {
#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */
#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */
#define DVO_PRESERVE_MASK (0x7<<24)
-#define DVOA_SRCDIM 0x61124
-#define DVOB_SRCDIM 0x61144
-#define DVOC_SRCDIM 0x61164
+#define DVOA_SRCDIM _MMIO(0x61124)
+#define DVOB_SRCDIM _MMIO(0x61144)
+#define DVOC_SRCDIM _MMIO(0x61164)
#define DVO_SRCDIM_HORIZONTAL_SHIFT 12
#define DVO_SRCDIM_VERTICAL_SHIFT 0
/* LVDS port control */
-#define LVDS 0x61180
+#define LVDS _MMIO(0x61180)
/*
* Enables the LVDS port. This bit must be set before DPLLs are enabled, as
* the DPLL semantics change when the LVDS is assigned to that pipe.
@@ -3454,13 +3506,13 @@ enum skl_disp_power_wells {
#define LVDS_B0B3_POWER_UP (3 << 2)
/* Video Data Island Packet control */
-#define VIDEO_DIP_DATA 0x61178
+#define VIDEO_DIP_DATA _MMIO(0x61178)
/* Read the description of VIDEO_DIP_DATA (before Haswell) or VIDEO_DIP_ECC
* (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte
* of the infoframe structure specified by CEA-861. */
#define VIDEO_DIP_DATA_SIZE 32
#define VIDEO_DIP_VSC_DATA_SIZE 36
-#define VIDEO_DIP_CTL 0x61170
+#define VIDEO_DIP_CTL _MMIO(0x61170)
/* Pre HSW: */
#define VIDEO_DIP_ENABLE (1 << 31)
#define VIDEO_DIP_PORT(port) ((port) << 29)
@@ -3487,7 +3539,7 @@ enum skl_disp_power_wells {
#define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0)
/* Panel power sequencing */
-#define PP_STATUS 0x61200
+#define PP_STATUS _MMIO(0x61200)
#define PP_ON (1 << 31)
/*
* Indicates that all dependencies of the panel are on:
@@ -3513,14 +3565,14 @@ enum skl_disp_power_wells {
#define PP_SEQUENCE_STATE_ON_S1_2 (0xa << 0)
#define PP_SEQUENCE_STATE_ON_S1_3 (0xb << 0)
#define PP_SEQUENCE_STATE_RESET (0xf << 0)
-#define PP_CONTROL 0x61204
+#define PP_CONTROL _MMIO(0x61204)
#define POWER_TARGET_ON (1 << 0)
-#define PP_ON_DELAYS 0x61208
-#define PP_OFF_DELAYS 0x6120c
-#define PP_DIVISOR 0x61210
+#define PP_ON_DELAYS _MMIO(0x61208)
+#define PP_OFF_DELAYS _MMIO(0x6120c)
+#define PP_DIVISOR _MMIO(0x61210)
/* Panel fitting */
-#define PFIT_CONTROL (dev_priv->info.display_mmio_offset + 0x61230)
+#define PFIT_CONTROL _MMIO(dev_priv->info.display_mmio_offset + 0x61230)
#define PFIT_ENABLE (1 << 31)
#define PFIT_PIPE_MASK (3 << 29)
#define PFIT_PIPE_SHIFT 29
@@ -3538,7 +3590,7 @@ enum skl_disp_power_wells {
#define PFIT_SCALING_PROGRAMMED (1 << 26)
#define PFIT_SCALING_PILLAR (2 << 26)
#define PFIT_SCALING_LETTER (3 << 26)
-#define PFIT_PGM_RATIOS (dev_priv->info.display_mmio_offset + 0x61234)
+#define PFIT_PGM_RATIOS _MMIO(dev_priv->info.display_mmio_offset + 0x61234)
/* Pre-965 */
#define PFIT_VERT_SCALE_SHIFT 20
#define PFIT_VERT_SCALE_MASK 0xfff00000
@@ -3550,25 +3602,25 @@ enum skl_disp_power_wells {
#define PFIT_HORIZ_SCALE_SHIFT_965 0
#define PFIT_HORIZ_SCALE_MASK_965 0x00001fff
-#define PFIT_AUTO_RATIOS (dev_priv->info.display_mmio_offset + 0x61238)
+#define PFIT_AUTO_RATIOS _MMIO(dev_priv->info.display_mmio_offset + 0x61238)
#define _VLV_BLC_PWM_CTL2_A (dev_priv->info.display_mmio_offset + 0x61250)
#define _VLV_BLC_PWM_CTL2_B (dev_priv->info.display_mmio_offset + 0x61350)
-#define VLV_BLC_PWM_CTL2(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \
- _VLV_BLC_PWM_CTL2_B)
+#define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \
+ _VLV_BLC_PWM_CTL2_B)
#define _VLV_BLC_PWM_CTL_A (dev_priv->info.display_mmio_offset + 0x61254)
#define _VLV_BLC_PWM_CTL_B (dev_priv->info.display_mmio_offset + 0x61354)
-#define VLV_BLC_PWM_CTL(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL_A, \
- _VLV_BLC_PWM_CTL_B)
+#define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, \
+ _VLV_BLC_PWM_CTL_B)
#define _VLV_BLC_HIST_CTL_A (dev_priv->info.display_mmio_offset + 0x61260)
#define _VLV_BLC_HIST_CTL_B (dev_priv->info.display_mmio_offset + 0x61360)
-#define VLV_BLC_HIST_CTL(pipe) _PIPE(pipe, _VLV_BLC_HIST_CTL_A, \
- _VLV_BLC_HIST_CTL_B)
+#define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, \
+ _VLV_BLC_HIST_CTL_B)
/* Backlight control */
-#define BLC_PWM_CTL2 (dev_priv->info.display_mmio_offset + 0x61250) /* 965+ only */
+#define BLC_PWM_CTL2 _MMIO(dev_priv->info.display_mmio_offset + 0x61250) /* 965+ only */
#define BLM_PWM_ENABLE (1 << 31)
#define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */
#define BLM_PIPE_SELECT (1 << 29)
@@ -3591,7 +3643,7 @@ enum skl_disp_power_wells {
#define BLM_PHASE_IN_COUNT_MASK (0xff << 8)
#define BLM_PHASE_IN_INCR_SHIFT (0)
#define BLM_PHASE_IN_INCR_MASK (0xff << 0)
-#define BLC_PWM_CTL (dev_priv->info.display_mmio_offset + 0x61254)
+#define BLC_PWM_CTL _MMIO(dev_priv->info.display_mmio_offset + 0x61254)
/*
* This is the most significant 15 bits of the number of backlight cycles in a
* complete cycle of the modulated backlight control.
@@ -3613,25 +3665,25 @@ enum skl_disp_power_wells {
#define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe)
#define BLM_POLARITY_PNV (1 << 0) /* pnv only */
-#define BLC_HIST_CTL (dev_priv->info.display_mmio_offset + 0x61260)
+#define BLC_HIST_CTL _MMIO(dev_priv->info.display_mmio_offset + 0x61260)
#define BLM_HISTOGRAM_ENABLE (1 << 31)
/* New registers for PCH-split platforms. Safe where new bits show up, the
* register layout machtes with gen4 BLC_PWM_CTL[12]. */
-#define BLC_PWM_CPU_CTL2 0x48250
-#define BLC_PWM_CPU_CTL 0x48254
+#define BLC_PWM_CPU_CTL2 _MMIO(0x48250)
+#define BLC_PWM_CPU_CTL _MMIO(0x48254)
-#define HSW_BLC_PWM2_CTL 0x48350
+#define HSW_BLC_PWM2_CTL _MMIO(0x48350)
/* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is
* like the normal CTL from gen4 and earlier. Hooray for confusing naming. */
-#define BLC_PWM_PCH_CTL1 0xc8250
+#define BLC_PWM_PCH_CTL1 _MMIO(0xc8250)
#define BLM_PCH_PWM_ENABLE (1 << 31)
#define BLM_PCH_OVERRIDE_ENABLE (1 << 30)
#define BLM_PCH_POLARITY (1 << 29)
-#define BLC_PWM_PCH_CTL2 0xc8254
+#define BLC_PWM_PCH_CTL2 _MMIO(0xc8254)
-#define UTIL_PIN_CTL 0x48400
+#define UTIL_PIN_CTL _MMIO(0x48400)
#define UTIL_PIN_ENABLE (1 << 31)
#define UTIL_PIN_PIPE(x) ((x) << 29)
@@ -3651,18 +3703,18 @@ enum skl_disp_power_wells {
#define _BXT_BLC_PWM_FREQ2 0xC8354
#define _BXT_BLC_PWM_DUTY2 0xC8358
-#define BXT_BLC_PWM_CTL(controller) _PIPE(controller, \
+#define BXT_BLC_PWM_CTL(controller) _MMIO_PIPE(controller, \
_BXT_BLC_PWM_CTL1, _BXT_BLC_PWM_CTL2)
-#define BXT_BLC_PWM_FREQ(controller) _PIPE(controller, \
+#define BXT_BLC_PWM_FREQ(controller) _MMIO_PIPE(controller, \
_BXT_BLC_PWM_FREQ1, _BXT_BLC_PWM_FREQ2)
-#define BXT_BLC_PWM_DUTY(controller) _PIPE(controller, \
+#define BXT_BLC_PWM_DUTY(controller) _MMIO_PIPE(controller, \
_BXT_BLC_PWM_DUTY1, _BXT_BLC_PWM_DUTY2)
-#define PCH_GTC_CTL 0xe7000
+#define PCH_GTC_CTL _MMIO(0xe7000)
#define PCH_GTC_ENABLE (1 << 31)
/* TV port control */
-#define TV_CTL 0x68000
+#define TV_CTL _MMIO(0x68000)
/* Enables the TV encoder */
# define TV_ENC_ENABLE (1 << 31)
/* Sources the TV encoder input from pipe B instead of A. */
@@ -3729,7 +3781,7 @@ enum skl_disp_power_wells {
# define TV_TEST_MODE_MONITOR_DETECT (7 << 0)
# define TV_TEST_MODE_MASK (7 << 0)
-#define TV_DAC 0x68004
+#define TV_DAC _MMIO(0x68004)
# define TV_DAC_SAVE 0x00ffff00
/*
* Reports that DAC state change logic has reported change (RO).
@@ -3780,13 +3832,13 @@ enum skl_disp_power_wells {
* where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
* -1 (0x3) being the only legal negative value.
*/
-#define TV_CSC_Y 0x68010
+#define TV_CSC_Y _MMIO(0x68010)
# define TV_RY_MASK 0x07ff0000
# define TV_RY_SHIFT 16
# define TV_GY_MASK 0x00000fff
# define TV_GY_SHIFT 0
-#define TV_CSC_Y2 0x68014
+#define TV_CSC_Y2 _MMIO(0x68014)
# define TV_BY_MASK 0x07ff0000
# define TV_BY_SHIFT 16
/*
@@ -3797,13 +3849,13 @@ enum skl_disp_power_wells {
# define TV_AY_MASK 0x000003ff
# define TV_AY_SHIFT 0
-#define TV_CSC_U 0x68018
+#define TV_CSC_U _MMIO(0x68018)
# define TV_RU_MASK 0x07ff0000
# define TV_RU_SHIFT 16
# define TV_GU_MASK 0x000007ff
# define TV_GU_SHIFT 0
-#define TV_CSC_U2 0x6801c
+#define TV_CSC_U2 _MMIO(0x6801c)
# define TV_BU_MASK 0x07ff0000
# define TV_BU_SHIFT 16
/*
@@ -3814,13 +3866,13 @@ enum skl_disp_power_wells {
# define TV_AU_MASK 0x000003ff
# define TV_AU_SHIFT 0
-#define TV_CSC_V 0x68020
+#define TV_CSC_V _MMIO(0x68020)
# define TV_RV_MASK 0x0fff0000
# define TV_RV_SHIFT 16
# define TV_GV_MASK 0x000007ff
# define TV_GV_SHIFT 0
-#define TV_CSC_V2 0x68024
+#define TV_CSC_V2 _MMIO(0x68024)
# define TV_BV_MASK 0x07ff0000
# define TV_BV_SHIFT 16
/*
@@ -3831,7 +3883,7 @@ enum skl_disp_power_wells {
# define TV_AV_MASK 0x000007ff
# define TV_AV_SHIFT 0
-#define TV_CLR_KNOBS 0x68028
+#define TV_CLR_KNOBS _MMIO(0x68028)
/* 2s-complement brightness adjustment */
# define TV_BRIGHTNESS_MASK 0xff000000
# define TV_BRIGHTNESS_SHIFT 24
@@ -3845,7 +3897,7 @@ enum skl_disp_power_wells {
# define TV_HUE_MASK 0x000000ff
# define TV_HUE_SHIFT 0
-#define TV_CLR_LEVEL 0x6802c
+#define TV_CLR_LEVEL _MMIO(0x6802c)
/* Controls the DAC level for black */
# define TV_BLACK_LEVEL_MASK 0x01ff0000
# define TV_BLACK_LEVEL_SHIFT 16
@@ -3853,7 +3905,7 @@ enum skl_disp_power_wells {
# define TV_BLANK_LEVEL_MASK 0x000001ff
# define TV_BLANK_LEVEL_SHIFT 0
-#define TV_H_CTL_1 0x68030
+#define TV_H_CTL_1 _MMIO(0x68030)
/* Number of pixels in the hsync. */
# define TV_HSYNC_END_MASK 0x1fff0000
# define TV_HSYNC_END_SHIFT 16
@@ -3861,7 +3913,7 @@ enum skl_disp_power_wells {
# define TV_HTOTAL_MASK 0x00001fff
# define TV_HTOTAL_SHIFT 0
-#define TV_H_CTL_2 0x68034
+#define TV_H_CTL_2 _MMIO(0x68034)
/* Enables the colorburst (needed for non-component color) */
# define TV_BURST_ENA (1 << 31)
/* Offset of the colorburst from the start of hsync, in pixels minus one. */
@@ -3871,7 +3923,7 @@ enum skl_disp_power_wells {
# define TV_HBURST_LEN_SHIFT 0
# define TV_HBURST_LEN_MASK 0x0001fff
-#define TV_H_CTL_3 0x68038
+#define TV_H_CTL_3 _MMIO(0x68038)
/* End of hblank, measured in pixels minus one from start of hsync */
# define TV_HBLANK_END_SHIFT 16
# define TV_HBLANK_END_MASK 0x1fff0000
@@ -3879,7 +3931,7 @@ enum skl_disp_power_wells {
# define TV_HBLANK_START_SHIFT 0
# define TV_HBLANK_START_MASK 0x0001fff
-#define TV_V_CTL_1 0x6803c
+#define TV_V_CTL_1 _MMIO(0x6803c)
/* XXX */
# define TV_NBR_END_SHIFT 16
# define TV_NBR_END_MASK 0x07ff0000
@@ -3890,7 +3942,7 @@ enum skl_disp_power_wells {
# define TV_VI_END_F2_SHIFT 0
# define TV_VI_END_F2_MASK 0x0000003f
-#define TV_V_CTL_2 0x68040
+#define TV_V_CTL_2 _MMIO(0x68040)
/* Length of vsync, in half lines */
# define TV_VSYNC_LEN_MASK 0x07ff0000
# define TV_VSYNC_LEN_SHIFT 16
@@ -3906,7 +3958,7 @@ enum skl_disp_power_wells {
# define TV_VSYNC_START_F2_MASK 0x0000007f
# define TV_VSYNC_START_F2_SHIFT 0
-#define TV_V_CTL_3 0x68044
+#define TV_V_CTL_3 _MMIO(0x68044)
/* Enables generation of the equalization signal */
# define TV_EQUAL_ENA (1 << 31)
/* Length of vsync, in half lines */
@@ -3924,7 +3976,7 @@ enum skl_disp_power_wells {
# define TV_VEQ_START_F2_MASK 0x000007f
# define TV_VEQ_START_F2_SHIFT 0
-#define TV_V_CTL_4 0x68048
+#define TV_V_CTL_4 _MMIO(0x68048)
/*
* Offset to start of vertical colorburst, measured in one less than the
* number of lines from vertical start.
@@ -3938,7 +3990,7 @@ enum skl_disp_power_wells {
# define TV_VBURST_END_F1_MASK 0x000000ff
# define TV_VBURST_END_F1_SHIFT 0
-#define TV_V_CTL_5 0x6804c
+#define TV_V_CTL_5 _MMIO(0x6804c)
/*
* Offset to start of vertical colorburst, measured in one less than the
* number of lines from vertical start.
@@ -3952,7 +4004,7 @@ enum skl_disp_power_wells {
# define TV_VBURST_END_F2_MASK 0x000000ff
# define TV_VBURST_END_F2_SHIFT 0
-#define TV_V_CTL_6 0x68050
+#define TV_V_CTL_6 _MMIO(0x68050)
/*
* Offset to start of vertical colorburst, measured in one less than the
* number of lines from vertical start.
@@ -3966,7 +4018,7 @@ enum skl_disp_power_wells {
# define TV_VBURST_END_F3_MASK 0x000000ff
# define TV_VBURST_END_F3_SHIFT 0
-#define TV_V_CTL_7 0x68054
+#define TV_V_CTL_7 _MMIO(0x68054)
/*
* Offset to start of vertical colorburst, measured in one less than the
* number of lines from vertical start.
@@ -3980,7 +4032,7 @@ enum skl_disp_power_wells {
# define TV_VBURST_END_F4_MASK 0x000000ff
# define TV_VBURST_END_F4_SHIFT 0
-#define TV_SC_CTL_1 0x68060
+#define TV_SC_CTL_1 _MMIO(0x68060)
/* Turns on the first subcarrier phase generation DDA */
# define TV_SC_DDA1_EN (1 << 31)
/* Turns on the first subcarrier phase generation DDA */
@@ -4002,7 +4054,7 @@ enum skl_disp_power_wells {
# define TV_SCDDA1_INC_MASK 0x00000fff
# define TV_SCDDA1_INC_SHIFT 0
-#define TV_SC_CTL_2 0x68064
+#define TV_SC_CTL_2 _MMIO(0x68064)
/* Sets the rollover for the second subcarrier phase generation DDA */
# define TV_SCDDA2_SIZE_MASK 0x7fff0000
# define TV_SCDDA2_SIZE_SHIFT 16
@@ -4010,7 +4062,7 @@ enum skl_disp_power_wells {
# define TV_SCDDA2_INC_MASK 0x00007fff
# define TV_SCDDA2_INC_SHIFT 0
-#define TV_SC_CTL_3 0x68068
+#define TV_SC_CTL_3 _MMIO(0x68068)
/* Sets the rollover for the third subcarrier phase generation DDA */
# define TV_SCDDA3_SIZE_MASK 0x7fff0000
# define TV_SCDDA3_SIZE_SHIFT 16
@@ -4018,7 +4070,7 @@ enum skl_disp_power_wells {
# define TV_SCDDA3_INC_MASK 0x00007fff
# define TV_SCDDA3_INC_SHIFT 0
-#define TV_WIN_POS 0x68070
+#define TV_WIN_POS _MMIO(0x68070)
/* X coordinate of the display from the start of horizontal active */
# define TV_XPOS_MASK 0x1fff0000
# define TV_XPOS_SHIFT 16
@@ -4026,7 +4078,7 @@ enum skl_disp_power_wells {
# define TV_YPOS_MASK 0x00000fff
# define TV_YPOS_SHIFT 0
-#define TV_WIN_SIZE 0x68074
+#define TV_WIN_SIZE _MMIO(0x68074)
/* Horizontal size of the display window, measured in pixels*/
# define TV_XSIZE_MASK 0x1fff0000
# define TV_XSIZE_SHIFT 16
@@ -4038,7 +4090,7 @@ enum skl_disp_power_wells {
# define TV_YSIZE_MASK 0x00000fff
# define TV_YSIZE_SHIFT 0
-#define TV_FILTER_CTL_1 0x68080
+#define TV_FILTER_CTL_1 _MMIO(0x68080)
/*
* Enables automatic scaling calculation.
*
@@ -4071,7 +4123,7 @@ enum skl_disp_power_wells {
# define TV_HSCALE_FRAC_MASK 0x00003fff
# define TV_HSCALE_FRAC_SHIFT 0
-#define TV_FILTER_CTL_2 0x68084
+#define TV_FILTER_CTL_2 _MMIO(0x68084)
/*
* Sets the integer part of the 3.15 fixed-point vertical scaling factor.
*
@@ -4087,7 +4139,7 @@ enum skl_disp_power_wells {
# define TV_VSCALE_FRAC_MASK 0x00007fff
# define TV_VSCALE_FRAC_SHIFT 0
-#define TV_FILTER_CTL_3 0x68088
+#define TV_FILTER_CTL_3 _MMIO(0x68088)
/*
* Sets the integer part of the 3.15 fixed-point vertical scaling factor.
*
@@ -4107,7 +4159,7 @@ enum skl_disp_power_wells {
# define TV_VSCALE_IP_FRAC_MASK 0x00007fff
# define TV_VSCALE_IP_FRAC_SHIFT 0
-#define TV_CC_CONTROL 0x68090
+#define TV_CC_CONTROL _MMIO(0x68090)
# define TV_CC_ENABLE (1 << 31)
/*
* Specifies which field to send the CC data in.
@@ -4123,7 +4175,7 @@ enum skl_disp_power_wells {
# define TV_CC_LINE_MASK 0x0000003f
# define TV_CC_LINE_SHIFT 0
-#define TV_CC_DATA 0x68094
+#define TV_CC_DATA _MMIO(0x68094)
# define TV_CC_RDY (1 << 31)
/* Second word of CC data to be transmitted. */
# define TV_CC_DATA_2_MASK 0x007f0000
@@ -4132,20 +4184,20 @@ enum skl_disp_power_wells {
# define TV_CC_DATA_1_MASK 0x0000007f
# define TV_CC_DATA_1_SHIFT 0
-#define TV_H_LUMA(i) (0x68100 + (i) * 4) /* 60 registers */
-#define TV_H_CHROMA(i) (0x68200 + (i) * 4) /* 60 registers */
-#define TV_V_LUMA(i) (0x68300 + (i) * 4) /* 43 registers */
-#define TV_V_CHROMA(i) (0x68400 + (i) * 4) /* 43 registers */
+#define TV_H_LUMA(i) _MMIO(0x68100 + (i) * 4) /* 60 registers */
+#define TV_H_CHROMA(i) _MMIO(0x68200 + (i) * 4) /* 60 registers */
+#define TV_V_LUMA(i) _MMIO(0x68300 + (i) * 4) /* 43 registers */
+#define TV_V_CHROMA(i) _MMIO(0x68400 + (i) * 4) /* 43 registers */
/* Display Port */
-#define DP_A 0x64000 /* eDP */
-#define DP_B 0x64100
-#define DP_C 0x64200
-#define DP_D 0x64300
+#define DP_A _MMIO(0x64000) /* eDP */
+#define DP_B _MMIO(0x64100)
+#define DP_C _MMIO(0x64200)
+#define DP_D _MMIO(0x64300)
-#define VLV_DP_B (VLV_DISPLAY_BASE + DP_B)
-#define VLV_DP_C (VLV_DISPLAY_BASE + DP_C)
-#define CHV_DP_D (VLV_DISPLAY_BASE + DP_D)
+#define VLV_DP_B _MMIO(VLV_DISPLAY_BASE + 0x64100)
+#define VLV_DP_C _MMIO(VLV_DISPLAY_BASE + 0x64200)
+#define CHV_DP_D _MMIO(VLV_DISPLAY_BASE + 0x64300)
#define DP_PORT_EN (1 << 31)
#define DP_PIPEB_SELECT (1 << 30)
@@ -4199,7 +4251,7 @@ enum skl_disp_power_wells {
/* eDP */
#define DP_PLL_FREQ_270MHZ (0 << 16)
-#define DP_PLL_FREQ_160MHZ (1 << 16)
+#define DP_PLL_FREQ_162MHZ (1 << 16)
#define DP_PLL_FREQ_MASK (3 << 16)
/* locked once port is enabled */
@@ -4232,33 +4284,36 @@ enum skl_disp_power_wells {
* is 20 bytes in each direction, hence the 5 fixed
* data registers
*/
-#define DPA_AUX_CH_CTL 0x64010
-#define DPA_AUX_CH_DATA1 0x64014
-#define DPA_AUX_CH_DATA2 0x64018
-#define DPA_AUX_CH_DATA3 0x6401c
-#define DPA_AUX_CH_DATA4 0x64020
-#define DPA_AUX_CH_DATA5 0x64024
-
-#define DPB_AUX_CH_CTL 0x64110
-#define DPB_AUX_CH_DATA1 0x64114
-#define DPB_AUX_CH_DATA2 0x64118
-#define DPB_AUX_CH_DATA3 0x6411c
-#define DPB_AUX_CH_DATA4 0x64120
-#define DPB_AUX_CH_DATA5 0x64124
-
-#define DPC_AUX_CH_CTL 0x64210
-#define DPC_AUX_CH_DATA1 0x64214
-#define DPC_AUX_CH_DATA2 0x64218
-#define DPC_AUX_CH_DATA3 0x6421c
-#define DPC_AUX_CH_DATA4 0x64220
-#define DPC_AUX_CH_DATA5 0x64224
-
-#define DPD_AUX_CH_CTL 0x64310
-#define DPD_AUX_CH_DATA1 0x64314
-#define DPD_AUX_CH_DATA2 0x64318
-#define DPD_AUX_CH_DATA3 0x6431c
-#define DPD_AUX_CH_DATA4 0x64320
-#define DPD_AUX_CH_DATA5 0x64324
+#define _DPA_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64010)
+#define _DPA_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64014)
+#define _DPA_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64018)
+#define _DPA_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6401c)
+#define _DPA_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64020)
+#define _DPA_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64024)
+
+#define _DPB_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64110)
+#define _DPB_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64114)
+#define _DPB_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64118)
+#define _DPB_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6411c)
+#define _DPB_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64120)
+#define _DPB_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64124)
+
+#define _DPC_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64210)
+#define _DPC_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64214)
+#define _DPC_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64218)
+#define _DPC_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6421c)
+#define _DPC_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64220)
+#define _DPC_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64224)
+
+#define _DPD_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64310)
+#define _DPD_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64314)
+#define _DPD_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64318)
+#define _DPD_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6431c)
+#define _DPD_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64320)
+#define _DPD_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64324)
+
+#define DP_AUX_CH_CTL(port) _MMIO_PORT(port, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL)
+#define DP_AUX_CH_DATA(port, i) _MMIO(_PORT(port, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
#define DP_AUX_CH_CTL_SEND_BUSY (1 << 31)
#define DP_AUX_CH_CTL_DONE (1 << 30)
@@ -4335,10 +4390,10 @@ enum skl_disp_power_wells {
#define _PIPEB_LINK_N_G4X 0x71064
#define PIPEA_DP_LINK_N_MASK (0xffffff)
-#define PIPE_DATA_M_G4X(pipe) _PIPE(pipe, _PIPEA_DATA_M_G4X, _PIPEB_DATA_M_G4X)
-#define PIPE_DATA_N_G4X(pipe) _PIPE(pipe, _PIPEA_DATA_N_G4X, _PIPEB_DATA_N_G4X)
-#define PIPE_LINK_M_G4X(pipe) _PIPE(pipe, _PIPEA_LINK_M_G4X, _PIPEB_LINK_M_G4X)
-#define PIPE_LINK_N_G4X(pipe) _PIPE(pipe, _PIPEA_LINK_N_G4X, _PIPEB_LINK_N_G4X)
+#define PIPE_DATA_M_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_DATA_M_G4X, _PIPEB_DATA_M_G4X)
+#define PIPE_DATA_N_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_DATA_N_G4X, _PIPEB_DATA_N_G4X)
+#define PIPE_LINK_M_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_LINK_M_G4X, _PIPEB_LINK_M_G4X)
+#define PIPE_LINK_N_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_LINK_N_G4X, _PIPEB_LINK_N_G4X)
/* Display & cursor control */
@@ -4454,15 +4509,15 @@ enum skl_disp_power_wells {
*/
#define PIPE_EDP_OFFSET 0x7f000
-#define _PIPE2(pipe, reg) (dev_priv->info.pipe_offsets[pipe] - \
+#define _MMIO_PIPE2(pipe, reg) _MMIO(dev_priv->info.pipe_offsets[pipe] - \
dev_priv->info.pipe_offsets[PIPE_A] + (reg) + \
dev_priv->info.display_mmio_offset)
-#define PIPECONF(pipe) _PIPE2(pipe, _PIPEACONF)
-#define PIPEDSL(pipe) _PIPE2(pipe, _PIPEADSL)
-#define PIPEFRAME(pipe) _PIPE2(pipe, _PIPEAFRAMEHIGH)
-#define PIPEFRAMEPIXEL(pipe) _PIPE2(pipe, _PIPEAFRAMEPIXEL)
-#define PIPESTAT(pipe) _PIPE2(pipe, _PIPEASTAT)
+#define PIPECONF(pipe) _MMIO_PIPE2(pipe, _PIPEACONF)
+#define PIPEDSL(pipe) _MMIO_PIPE2(pipe, _PIPEADSL)
+#define PIPEFRAME(pipe) _MMIO_PIPE2(pipe, _PIPEAFRAMEHIGH)
+#define PIPEFRAMEPIXEL(pipe) _MMIO_PIPE2(pipe, _PIPEAFRAMEPIXEL)
+#define PIPESTAT(pipe) _MMIO_PIPE2(pipe, _PIPEASTAT)
#define _PIPE_MISC_A 0x70030
#define _PIPE_MISC_B 0x71030
@@ -4474,9 +4529,9 @@ enum skl_disp_power_wells {
#define PIPEMISC_DITHER_ENABLE (1<<4)
#define PIPEMISC_DITHER_TYPE_MASK (3<<2)
#define PIPEMISC_DITHER_TYPE_SP (0<<2)
-#define PIPEMISC(pipe) _PIPE2(pipe, _PIPE_MISC_A)
+#define PIPEMISC(pipe) _MMIO_PIPE2(pipe, _PIPE_MISC_A)
-#define VLV_DPFLIPSTAT (VLV_DISPLAY_BASE + 0x70028)
+#define VLV_DPFLIPSTAT _MMIO(VLV_DISPLAY_BASE + 0x70028)
#define PIPEB_LINE_COMPARE_INT_EN (1<<29)
#define PIPEB_HLINE_INT_EN (1<<28)
#define PIPEB_VBLANK_INT_EN (1<<27)
@@ -4497,7 +4552,7 @@ enum skl_disp_power_wells {
#define SPRITEE_FLIPDONE_INT_EN (1<<9)
#define PLANEC_FLIPDONE_INT_EN (1<<8)
-#define DPINVGTT (VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
+#define DPINVGTT _MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */
#define SPRITEF_INVALID_GTT_INT_EN (1<<27)
#define SPRITEE_INVALID_GTT_INT_EN (1<<26)
#define PLANEC_INVALID_GTT_INT_EN (1<<25)
@@ -4527,7 +4582,7 @@ enum skl_disp_power_wells {
#define DPINVGTT_STATUS_MASK 0xff
#define DPINVGTT_STATUS_MASK_CHV 0xfff
-#define DSPARB (dev_priv->info.display_mmio_offset + 0x70030)
+#define DSPARB _MMIO(dev_priv->info.display_mmio_offset + 0x70030)
#define DSPARB_CSTART_MASK (0x7f << 7)
#define DSPARB_CSTART_SHIFT 7
#define DSPARB_BSTART_MASK (0x7f)
@@ -4542,7 +4597,7 @@ enum skl_disp_power_wells {
#define DSPARB_SPRITEC_MASK_VLV (0xff << 16)
#define DSPARB_SPRITED_SHIFT_VLV 24
#define DSPARB_SPRITED_MASK_VLV (0xff << 24)
-#define DSPARB2 (VLV_DISPLAY_BASE + 0x70060) /* vlv/chv */
+#define DSPARB2 _MMIO(VLV_DISPLAY_BASE + 0x70060) /* vlv/chv */
#define DSPARB_SPRITEA_HI_SHIFT_VLV 0
#define DSPARB_SPRITEA_HI_MASK_VLV (0x1 << 0)
#define DSPARB_SPRITEB_HI_SHIFT_VLV 4
@@ -4555,14 +4610,14 @@ enum skl_disp_power_wells {
#define DSPARB_SPRITEE_HI_MASK_VLV (0x1 << 16)
#define DSPARB_SPRITEF_HI_SHIFT_VLV 20
#define DSPARB_SPRITEF_HI_MASK_VLV (0x1 << 20)
-#define DSPARB3 (VLV_DISPLAY_BASE + 0x7006c) /* chv */
+#define DSPARB3 _MMIO(VLV_DISPLAY_BASE + 0x7006c) /* chv */
#define DSPARB_SPRITEE_SHIFT_VLV 0
#define DSPARB_SPRITEE_MASK_VLV (0xff << 0)
#define DSPARB_SPRITEF_SHIFT_VLV 8
#define DSPARB_SPRITEF_MASK_VLV (0xff << 8)
/* pnv/gen4/g4x/vlv/chv */
-#define DSPFW1 (dev_priv->info.display_mmio_offset + 0x70034)
+#define DSPFW1 _MMIO(dev_priv->info.display_mmio_offset + 0x70034)
#define DSPFW_SR_SHIFT 23
#define DSPFW_SR_MASK (0x1ff<<23)
#define DSPFW_CURSORB_SHIFT 16
@@ -4573,7 +4628,7 @@ enum skl_disp_power_wells {
#define DSPFW_PLANEA_SHIFT 0
#define DSPFW_PLANEA_MASK (0x7f<<0)
#define DSPFW_PLANEA_MASK_VLV (0xff<<0) /* vlv/chv */
-#define DSPFW2 (dev_priv->info.display_mmio_offset + 0x70038)
+#define DSPFW2 _MMIO(dev_priv->info.display_mmio_offset + 0x70038)
#define DSPFW_FBC_SR_EN (1<<31) /* g4x */
#define DSPFW_FBC_SR_SHIFT 28
#define DSPFW_FBC_SR_MASK (0x7<<28) /* g4x */
@@ -4589,7 +4644,7 @@ enum skl_disp_power_wells {
#define DSPFW_SPRITEA_SHIFT 0
#define DSPFW_SPRITEA_MASK (0x7f<<0) /* g4x */
#define DSPFW_SPRITEA_MASK_VLV (0xff<<0) /* vlv/chv */
-#define DSPFW3 (dev_priv->info.display_mmio_offset + 0x7003c)
+#define DSPFW3 _MMIO(dev_priv->info.display_mmio_offset + 0x7003c)
#define DSPFW_HPLL_SR_EN (1<<31)
#define PINEVIEW_SELF_REFRESH_EN (1<<30)
#define DSPFW_CURSOR_SR_SHIFT 24
@@ -4600,14 +4655,14 @@ enum skl_disp_power_wells {
#define DSPFW_HPLL_SR_MASK (0x1ff<<0)
/* vlv/chv */
-#define DSPFW4 (VLV_DISPLAY_BASE + 0x70070)
+#define DSPFW4 _MMIO(VLV_DISPLAY_BASE + 0x70070)
#define DSPFW_SPRITEB_WM1_SHIFT 16
#define DSPFW_SPRITEB_WM1_MASK (0xff<<16)
#define DSPFW_CURSORA_WM1_SHIFT 8
#define DSPFW_CURSORA_WM1_MASK (0x3f<<8)
#define DSPFW_SPRITEA_WM1_SHIFT 0
#define DSPFW_SPRITEA_WM1_MASK (0xff<<0)
-#define DSPFW5 (VLV_DISPLAY_BASE + 0x70074)
+#define DSPFW5 _MMIO(VLV_DISPLAY_BASE + 0x70074)
#define DSPFW_PLANEB_WM1_SHIFT 24
#define DSPFW_PLANEB_WM1_MASK (0xff<<24)
#define DSPFW_PLANEA_WM1_SHIFT 16
@@ -4616,11 +4671,11 @@ enum skl_disp_power_wells {
#define DSPFW_CURSORB_WM1_MASK (0x3f<<8)
#define DSPFW_CURSOR_SR_WM1_SHIFT 0
#define DSPFW_CURSOR_SR_WM1_MASK (0x3f<<0)
-#define DSPFW6 (VLV_DISPLAY_BASE + 0x70078)
+#define DSPFW6 _MMIO(VLV_DISPLAY_BASE + 0x70078)
#define DSPFW_SR_WM1_SHIFT 0
#define DSPFW_SR_WM1_MASK (0x1ff<<0)
-#define DSPFW7 (VLV_DISPLAY_BASE + 0x7007c)
-#define DSPFW7_CHV (VLV_DISPLAY_BASE + 0x700b4) /* wtf #1? */
+#define DSPFW7 _MMIO(VLV_DISPLAY_BASE + 0x7007c)
+#define DSPFW7_CHV _MMIO(VLV_DISPLAY_BASE + 0x700b4) /* wtf #1? */
#define DSPFW_SPRITED_WM1_SHIFT 24
#define DSPFW_SPRITED_WM1_MASK (0xff<<24)
#define DSPFW_SPRITED_SHIFT 16
@@ -4629,7 +4684,7 @@ enum skl_disp_power_wells {
#define DSPFW_SPRITEC_WM1_MASK (0xff<<8)
#define DSPFW_SPRITEC_SHIFT 0
#define DSPFW_SPRITEC_MASK_VLV (0xff<<0)
-#define DSPFW8_CHV (VLV_DISPLAY_BASE + 0x700b8)
+#define DSPFW8_CHV _MMIO(VLV_DISPLAY_BASE + 0x700b8)
#define DSPFW_SPRITEF_WM1_SHIFT 24
#define DSPFW_SPRITEF_WM1_MASK (0xff<<24)
#define DSPFW_SPRITEF_SHIFT 16
@@ -4638,7 +4693,7 @@ enum skl_disp_power_wells {
#define DSPFW_SPRITEE_WM1_MASK (0xff<<8)
#define DSPFW_SPRITEE_SHIFT 0
#define DSPFW_SPRITEE_MASK_VLV (0xff<<0)
-#define DSPFW9_CHV (VLV_DISPLAY_BASE + 0x7007c) /* wtf #2? */
+#define DSPFW9_CHV _MMIO(VLV_DISPLAY_BASE + 0x7007c) /* wtf #2? */
#define DSPFW_PLANEC_WM1_SHIFT 24
#define DSPFW_PLANEC_WM1_MASK (0xff<<24)
#define DSPFW_PLANEC_SHIFT 16
@@ -4649,7 +4704,7 @@ enum skl_disp_power_wells {
#define DSPFW_CURSORC_MASK (0x3f<<0)
/* vlv/chv high order bits */
-#define DSPHOWM (VLV_DISPLAY_BASE + 0x70064)
+#define DSPHOWM _MMIO(VLV_DISPLAY_BASE + 0x70064)
#define DSPFW_SR_HI_SHIFT 24
#define DSPFW_SR_HI_MASK (3<<24) /* 2 bits for chv, 1 for vlv */
#define DSPFW_SPRITEF_HI_SHIFT 23
@@ -4670,7 +4725,7 @@ enum skl_disp_power_wells {
#define DSPFW_SPRITEA_HI_MASK (1<<4)
#define DSPFW_PLANEA_HI_SHIFT 0
#define DSPFW_PLANEA_HI_MASK (1<<0)
-#define DSPHOWM1 (VLV_DISPLAY_BASE + 0x70068)
+#define DSPHOWM1 _MMIO(VLV_DISPLAY_BASE + 0x70068)
#define DSPFW_SR_WM1_HI_SHIFT 24
#define DSPFW_SR_WM1_HI_MASK (3<<24) /* 2 bits for chv, 1 for vlv */
#define DSPFW_SPRITEF_WM1_HI_SHIFT 23
@@ -4693,7 +4748,7 @@ enum skl_disp_power_wells {
#define DSPFW_PLANEA_WM1_HI_MASK (1<<0)
/* drain latency register values*/
-#define VLV_DDL(pipe) (VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe))
+#define VLV_DDL(pipe) _MMIO(VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe))
#define DDL_CURSOR_SHIFT 24
#define DDL_SPRITE_SHIFT(sprite) (8+8*(sprite))
#define DDL_PLANE_SHIFT 0
@@ -4701,7 +4756,7 @@ enum skl_disp_power_wells {
#define DDL_PRECISION_LOW (0<<7)
#define DRAIN_LATENCY_MASK 0x7f
-#define CBR1_VLV (VLV_DISPLAY_BASE + 0x70400)
+#define CBR1_VLV _MMIO(VLV_DISPLAY_BASE + 0x70400)
#define CBR_PND_DEADLINE_DISABLE (1<<31)
#define CBR_PWM_CLOCK_MUX_SELECT (1<<30)
@@ -4739,51 +4794,51 @@ enum skl_disp_power_wells {
#define I965_CURSOR_DFT_WM 8
/* Watermark register definitions for SKL */
-#define CUR_WM_A_0 0x70140
-#define CUR_WM_B_0 0x71140
-#define PLANE_WM_1_A_0 0x70240
-#define PLANE_WM_1_B_0 0x71240
-#define PLANE_WM_2_A_0 0x70340
-#define PLANE_WM_2_B_0 0x71340
-#define PLANE_WM_TRANS_1_A_0 0x70268
-#define PLANE_WM_TRANS_1_B_0 0x71268
-#define PLANE_WM_TRANS_2_A_0 0x70368
-#define PLANE_WM_TRANS_2_B_0 0x71368
-#define CUR_WM_TRANS_A_0 0x70168
-#define CUR_WM_TRANS_B_0 0x71168
+#define _CUR_WM_A_0 0x70140
+#define _CUR_WM_B_0 0x71140
+#define _PLANE_WM_1_A_0 0x70240
+#define _PLANE_WM_1_B_0 0x71240
+#define _PLANE_WM_2_A_0 0x70340
+#define _PLANE_WM_2_B_0 0x71340
+#define _PLANE_WM_TRANS_1_A_0 0x70268
+#define _PLANE_WM_TRANS_1_B_0 0x71268
+#define _PLANE_WM_TRANS_2_A_0 0x70368
+#define _PLANE_WM_TRANS_2_B_0 0x71368
+#define _CUR_WM_TRANS_A_0 0x70168
+#define _CUR_WM_TRANS_B_0 0x71168
#define PLANE_WM_EN (1 << 31)
#define PLANE_WM_LINES_SHIFT 14
#define PLANE_WM_LINES_MASK 0x1f
#define PLANE_WM_BLOCKS_MASK 0x3ff
-#define CUR_WM_0(pipe) _PIPE(pipe, CUR_WM_A_0, CUR_WM_B_0)
-#define CUR_WM(pipe, level) (CUR_WM_0(pipe) + ((4) * (level)))
-#define CUR_WM_TRANS(pipe) _PIPE(pipe, CUR_WM_TRANS_A_0, CUR_WM_TRANS_B_0)
+#define _CUR_WM_0(pipe) _PIPE(pipe, _CUR_WM_A_0, _CUR_WM_B_0)
+#define CUR_WM(pipe, level) _MMIO(_CUR_WM_0(pipe) + ((4) * (level)))
+#define CUR_WM_TRANS(pipe) _MMIO_PIPE(pipe, _CUR_WM_TRANS_A_0, _CUR_WM_TRANS_B_0)
-#define _PLANE_WM_1(pipe) _PIPE(pipe, PLANE_WM_1_A_0, PLANE_WM_1_B_0)
-#define _PLANE_WM_2(pipe) _PIPE(pipe, PLANE_WM_2_A_0, PLANE_WM_2_B_0)
+#define _PLANE_WM_1(pipe) _PIPE(pipe, _PLANE_WM_1_A_0, _PLANE_WM_1_B_0)
+#define _PLANE_WM_2(pipe) _PIPE(pipe, _PLANE_WM_2_A_0, _PLANE_WM_2_B_0)
#define _PLANE_WM_BASE(pipe, plane) \
_PLANE(plane, _PLANE_WM_1(pipe), _PLANE_WM_2(pipe))
#define PLANE_WM(pipe, plane, level) \
- (_PLANE_WM_BASE(pipe, plane) + ((4) * (level)))
+ _MMIO(_PLANE_WM_BASE(pipe, plane) + ((4) * (level)))
#define _PLANE_WM_TRANS_1(pipe) \
- _PIPE(pipe, PLANE_WM_TRANS_1_A_0, PLANE_WM_TRANS_1_B_0)
+ _PIPE(pipe, _PLANE_WM_TRANS_1_A_0, _PLANE_WM_TRANS_1_B_0)
#define _PLANE_WM_TRANS_2(pipe) \
- _PIPE(pipe, PLANE_WM_TRANS_2_A_0, PLANE_WM_TRANS_2_B_0)
+ _PIPE(pipe, _PLANE_WM_TRANS_2_A_0, _PLANE_WM_TRANS_2_B_0)
#define PLANE_WM_TRANS(pipe, plane) \
- _PLANE(plane, _PLANE_WM_TRANS_1(pipe), _PLANE_WM_TRANS_2(pipe))
+ _MMIO(_PLANE(plane, _PLANE_WM_TRANS_1(pipe), _PLANE_WM_TRANS_2(pipe)))
/* define the Watermark register on Ironlake */
-#define WM0_PIPEA_ILK 0x45100
+#define WM0_PIPEA_ILK _MMIO(0x45100)
#define WM0_PIPE_PLANE_MASK (0xffff<<16)
#define WM0_PIPE_PLANE_SHIFT 16
#define WM0_PIPE_SPRITE_MASK (0xff<<8)
#define WM0_PIPE_SPRITE_SHIFT 8
#define WM0_PIPE_CURSOR_MASK (0xff)
-#define WM0_PIPEB_ILK 0x45104
-#define WM0_PIPEC_IVB 0x45200
-#define WM1_LP_ILK 0x45108
+#define WM0_PIPEB_ILK _MMIO(0x45104)
+#define WM0_PIPEC_IVB _MMIO(0x45200)
+#define WM1_LP_ILK _MMIO(0x45108)
#define WM1_LP_SR_EN (1<<31)
#define WM1_LP_LATENCY_SHIFT 24
#define WM1_LP_LATENCY_MASK (0x7f<<24)
@@ -4793,13 +4848,13 @@ enum skl_disp_power_wells {
#define WM1_LP_SR_MASK (0x7ff<<8)
#define WM1_LP_SR_SHIFT 8
#define WM1_LP_CURSOR_MASK (0xff)
-#define WM2_LP_ILK 0x4510c
+#define WM2_LP_ILK _MMIO(0x4510c)
#define WM2_LP_EN (1<<31)
-#define WM3_LP_ILK 0x45110
+#define WM3_LP_ILK _MMIO(0x45110)
#define WM3_LP_EN (1<<31)
-#define WM1S_LP_ILK 0x45120
-#define WM2S_LP_IVB 0x45124
-#define WM3S_LP_IVB 0x45128
+#define WM1S_LP_ILK _MMIO(0x45120)
+#define WM2S_LP_IVB _MMIO(0x45124)
+#define WM3S_LP_IVB _MMIO(0x45128)
#define WM1S_LP_EN (1<<31)
#define HSW_WM_LP_VAL(lat, fbc, pri, cur) \
@@ -4807,7 +4862,7 @@ enum skl_disp_power_wells {
((fbc) << WM1_LP_FBC_SHIFT) | ((pri) << WM1_LP_SR_SHIFT) | (cur))
/* Memory latency timer register */
-#define MLTR_ILK 0x11222
+#define MLTR_ILK _MMIO(0x11222)
#define MLTR_WM1_SHIFT 0
#define MLTR_WM2_SHIFT 8
/* the unit of memory self-refresh latency time is 0.5us */
@@ -4815,7 +4870,7 @@ enum skl_disp_power_wells {
/* the address where we get all kinds of latency value */
-#define SSKPD 0x5d10
+#define SSKPD _MMIO(0x5d10)
#define SSKPD_WM_MASK 0x3f
#define SSKPD_WM0_SHIFT 0
#define SSKPD_WM1_SHIFT 8
@@ -4848,8 +4903,8 @@ enum skl_disp_power_wells {
/* GM45+ just has to be different */
#define _PIPEA_FRMCOUNT_G4X 0x70040
#define _PIPEA_FLIPCOUNT_G4X 0x70044
-#define PIPE_FRMCOUNT_G4X(pipe) _PIPE2(pipe, _PIPEA_FRMCOUNT_G4X)
-#define PIPE_FLIPCOUNT_G4X(pipe) _PIPE2(pipe, _PIPEA_FLIPCOUNT_G4X)
+#define PIPE_FRMCOUNT_G4X(pipe) _MMIO_PIPE2(pipe, _PIPEA_FRMCOUNT_G4X)
+#define PIPE_FLIPCOUNT_G4X(pipe) _MMIO_PIPE2(pipe, _PIPEA_FLIPCOUNT_G4X)
/* Cursor A & B regs */
#define _CURACNTR 0x70080
@@ -4887,7 +4942,7 @@ enum skl_disp_power_wells {
#define CURSOR_POS_SIGN 0x8000
#define CURSOR_X_SHIFT 0
#define CURSOR_Y_SHIFT 16
-#define CURSIZE 0x700a0
+#define CURSIZE _MMIO(0x700a0)
#define _CURBCNTR 0x700c0
#define _CURBBASE 0x700c4
#define _CURBPOS 0x700c8
@@ -4896,7 +4951,7 @@ enum skl_disp_power_wells {
#define _CURBBASE_IVB 0x71084
#define _CURBPOS_IVB 0x71088
-#define _CURSOR2(pipe, reg) (dev_priv->info.cursor_offsets[(pipe)] - \
+#define _CURSOR2(pipe, reg) _MMIO(dev_priv->info.cursor_offsets[(pipe)] - \
dev_priv->info.cursor_offsets[PIPE_A] + (reg) + \
dev_priv->info.display_mmio_offset)
@@ -4957,16 +5012,16 @@ enum skl_disp_power_wells {
#define _DSPAOFFSET 0x701A4 /* HSW */
#define _DSPASURFLIVE 0x701AC
-#define DSPCNTR(plane) _PIPE2(plane, _DSPACNTR)
-#define DSPADDR(plane) _PIPE2(plane, _DSPAADDR)
-#define DSPSTRIDE(plane) _PIPE2(plane, _DSPASTRIDE)
-#define DSPPOS(plane) _PIPE2(plane, _DSPAPOS)
-#define DSPSIZE(plane) _PIPE2(plane, _DSPASIZE)
-#define DSPSURF(plane) _PIPE2(plane, _DSPASURF)
-#define DSPTILEOFF(plane) _PIPE2(plane, _DSPATILEOFF)
-#define DSPLINOFF(plane) DSPADDR(plane)
-#define DSPOFFSET(plane) _PIPE2(plane, _DSPAOFFSET)
-#define DSPSURFLIVE(plane) _PIPE2(plane, _DSPASURFLIVE)
+#define DSPCNTR(plane) _MMIO_PIPE2(plane, _DSPACNTR)
+#define DSPADDR(plane) _MMIO_PIPE2(plane, _DSPAADDR)
+#define DSPSTRIDE(plane) _MMIO_PIPE2(plane, _DSPASTRIDE)
+#define DSPPOS(plane) _MMIO_PIPE2(plane, _DSPAPOS)
+#define DSPSIZE(plane) _MMIO_PIPE2(plane, _DSPASIZE)
+#define DSPSURF(plane) _MMIO_PIPE2(plane, _DSPASURF)
+#define DSPTILEOFF(plane) _MMIO_PIPE2(plane, _DSPATILEOFF)
+#define DSPLINOFF(plane) DSPADDR(plane)
+#define DSPOFFSET(plane) _MMIO_PIPE2(plane, _DSPAOFFSET)
+#define DSPSURFLIVE(plane) _MMIO_PIPE2(plane, _DSPASURFLIVE)
/* CHV pipe B blender and primary plane */
#define _CHV_BLEND_A 0x60a00
@@ -4980,11 +5035,11 @@ enum skl_disp_power_wells {
#define _PRIMCNSTALPHA_A 0x60a10
#define PRIM_CONST_ALPHA_ENABLE (1<<31)
-#define CHV_BLEND(pipe) _TRANSCODER2(pipe, _CHV_BLEND_A)
-#define CHV_CANVAS(pipe) _TRANSCODER2(pipe, _CHV_CANVAS_A)
-#define PRIMPOS(plane) _TRANSCODER2(plane, _PRIMPOS_A)
-#define PRIMSIZE(plane) _TRANSCODER2(plane, _PRIMSIZE_A)
-#define PRIMCNSTALPHA(plane) _TRANSCODER2(plane, _PRIMCNSTALPHA_A)
+#define CHV_BLEND(pipe) _MMIO_TRANS2(pipe, _CHV_BLEND_A)
+#define CHV_CANVAS(pipe) _MMIO_TRANS2(pipe, _CHV_CANVAS_A)
+#define PRIMPOS(plane) _MMIO_TRANS2(plane, _PRIMPOS_A)
+#define PRIMSIZE(plane) _MMIO_TRANS2(plane, _PRIMSIZE_A)
+#define PRIMCNSTALPHA(plane) _MMIO_TRANS2(plane, _PRIMCNSTALPHA_A)
/* Display/Sprite base address macros */
#define DISP_BASEADDR_MASK (0xfffff000)
@@ -5002,9 +5057,10 @@ enum skl_disp_power_wells {
* [10:1f] all
* [30:32] all
*/
-#define SWF0(i) (dev_priv->info.display_mmio_offset + 0x70410 + (i) * 4)
-#define SWF1(i) (dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4)
-#define SWF3(i) (dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4)
+#define SWF0(i) _MMIO(dev_priv->info.display_mmio_offset + 0x70410 + (i) * 4)
+#define SWF1(i) _MMIO(dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4)
+#define SWF3(i) _MMIO(dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4)
+#define SWF_ILK(i) _MMIO(0x4F000 + (i) * 4)
/* Pipe B */
#define _PIPEBDSL (dev_priv->info.display_mmio_offset + 0x71000)
@@ -5086,18 +5142,18 @@ enum skl_disp_power_wells {
#define _DVSBSCALE 0x73204
#define _DVSBGAMC 0x73300
-#define DVSCNTR(pipe) _PIPE(pipe, _DVSACNTR, _DVSBCNTR)
-#define DVSLINOFF(pipe) _PIPE(pipe, _DVSALINOFF, _DVSBLINOFF)
-#define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE)
-#define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS)
-#define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF)
-#define DVSKEYMAX(pipe) _PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL)
-#define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE)
-#define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE)
-#define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF)
-#define DVSKEYVAL(pipe) _PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL)
-#define DVSKEYMSK(pipe) _PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK)
-#define DVSSURFLIVE(pipe) _PIPE(pipe, _DVSASURFLIVE, _DVSBSURFLIVE)
+#define DVSCNTR(pipe) _MMIO_PIPE(pipe, _DVSACNTR, _DVSBCNTR)
+#define DVSLINOFF(pipe) _MMIO_PIPE(pipe, _DVSALINOFF, _DVSBLINOFF)
+#define DVSSTRIDE(pipe) _MMIO_PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE)
+#define DVSPOS(pipe) _MMIO_PIPE(pipe, _DVSAPOS, _DVSBPOS)
+#define DVSSURF(pipe) _MMIO_PIPE(pipe, _DVSASURF, _DVSBSURF)
+#define DVSKEYMAX(pipe) _MMIO_PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL)
+#define DVSSIZE(pipe) _MMIO_PIPE(pipe, _DVSASIZE, _DVSBSIZE)
+#define DVSSCALE(pipe) _MMIO_PIPE(pipe, _DVSASCALE, _DVSBSCALE)
+#define DVSTILEOFF(pipe) _MMIO_PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF)
+#define DVSKEYVAL(pipe) _MMIO_PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL)
+#define DVSKEYMSK(pipe) _MMIO_PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK)
+#define DVSSURFLIVE(pipe) _MMIO_PIPE(pipe, _DVSASURFLIVE, _DVSBSURFLIVE)
#define _SPRA_CTL 0x70280
#define SPRITE_ENABLE (1<<31)
@@ -5160,20 +5216,20 @@ enum skl_disp_power_wells {
#define _SPRB_SCALE 0x71304
#define _SPRB_GAMC 0x71400
-#define SPRCTL(pipe) _PIPE(pipe, _SPRA_CTL, _SPRB_CTL)
-#define SPRLINOFF(pipe) _PIPE(pipe, _SPRA_LINOFF, _SPRB_LINOFF)
-#define SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE)
-#define SPRPOS(pipe) _PIPE(pipe, _SPRA_POS, _SPRB_POS)
-#define SPRSIZE(pipe) _PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE)
-#define SPRKEYVAL(pipe) _PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL)
-#define SPRKEYMSK(pipe) _PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK)
-#define SPRSURF(pipe) _PIPE(pipe, _SPRA_SURF, _SPRB_SURF)
-#define SPRKEYMAX(pipe) _PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX)
-#define SPRTILEOFF(pipe) _PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF)
-#define SPROFFSET(pipe) _PIPE(pipe, _SPRA_OFFSET, _SPRB_OFFSET)
-#define SPRSCALE(pipe) _PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE)
-#define SPRGAMC(pipe) _PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC)
-#define SPRSURFLIVE(pipe) _PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE)
+#define SPRCTL(pipe) _MMIO_PIPE(pipe, _SPRA_CTL, _SPRB_CTL)
+#define SPRLINOFF(pipe) _MMIO_PIPE(pipe, _SPRA_LINOFF, _SPRB_LINOFF)
+#define SPRSTRIDE(pipe) _MMIO_PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE)
+#define SPRPOS(pipe) _MMIO_PIPE(pipe, _SPRA_POS, _SPRB_POS)
+#define SPRSIZE(pipe) _MMIO_PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE)
+#define SPRKEYVAL(pipe) _MMIO_PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL)
+#define SPRKEYMSK(pipe) _MMIO_PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK)
+#define SPRSURF(pipe) _MMIO_PIPE(pipe, _SPRA_SURF, _SPRB_SURF)
+#define SPRKEYMAX(pipe) _MMIO_PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX)
+#define SPRTILEOFF(pipe) _MMIO_PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF)
+#define SPROFFSET(pipe) _MMIO_PIPE(pipe, _SPRA_OFFSET, _SPRB_OFFSET)
+#define SPRSCALE(pipe) _MMIO_PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE)
+#define SPRGAMC(pipe) _MMIO_PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC)
+#define SPRSURFLIVE(pipe) _MMIO_PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE)
#define _SPACNTR (VLV_DISPLAY_BASE + 0x72180)
#define SP_ENABLE (1<<31)
@@ -5223,18 +5279,18 @@ enum skl_disp_power_wells {
#define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8)
#define _SPBGAMC (VLV_DISPLAY_BASE + 0x722f4)
-#define SPCNTR(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPACNTR, _SPBCNTR)
-#define SPLINOFF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPALINOFF, _SPBLINOFF)
-#define SPSTRIDE(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASTRIDE, _SPBSTRIDE)
-#define SPPOS(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAPOS, _SPBPOS)
-#define SPSIZE(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASIZE, _SPBSIZE)
-#define SPKEYMINVAL(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMINVAL, _SPBKEYMINVAL)
-#define SPKEYMSK(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMSK, _SPBKEYMSK)
-#define SPSURF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASURF, _SPBSURF)
-#define SPKEYMAXVAL(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMAXVAL, _SPBKEYMAXVAL)
-#define SPTILEOFF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPATILEOFF, _SPBTILEOFF)
-#define SPCONSTALPHA(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPACONSTALPHA, _SPBCONSTALPHA)
-#define SPGAMC(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAGAMC, _SPBGAMC)
+#define SPCNTR(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPACNTR, _SPBCNTR)
+#define SPLINOFF(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPALINOFF, _SPBLINOFF)
+#define SPSTRIDE(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPASTRIDE, _SPBSTRIDE)
+#define SPPOS(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAPOS, _SPBPOS)
+#define SPSIZE(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPASIZE, _SPBSIZE)
+#define SPKEYMINVAL(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAKEYMINVAL, _SPBKEYMINVAL)
+#define SPKEYMSK(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAKEYMSK, _SPBKEYMSK)
+#define SPSURF(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPASURF, _SPBSURF)
+#define SPKEYMAXVAL(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAKEYMAXVAL, _SPBKEYMAXVAL)
+#define SPTILEOFF(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPATILEOFF, _SPBTILEOFF)
+#define SPCONSTALPHA(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPACONSTALPHA, _SPBCONSTALPHA)
+#define SPGAMC(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAGAMC, _SPBGAMC)
/*
* CHV pipe B sprite CSC
@@ -5243,29 +5299,29 @@ enum skl_disp_power_wells {
* |yg| = |c3 c4 c5| x |yg + yg_ioff| + |yg_ooff|
* |cb| |c6 c7 c8| |cb + cr_ioff| |cb_ooff|
*/
-#define SPCSCYGOFF(sprite) (VLV_DISPLAY_BASE + 0x6d900 + (sprite) * 0x1000)
-#define SPCSCCBOFF(sprite) (VLV_DISPLAY_BASE + 0x6d904 + (sprite) * 0x1000)
-#define SPCSCCROFF(sprite) (VLV_DISPLAY_BASE + 0x6d908 + (sprite) * 0x1000)
+#define SPCSCYGOFF(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d900 + (sprite) * 0x1000)
+#define SPCSCCBOFF(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d904 + (sprite) * 0x1000)
+#define SPCSCCROFF(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d908 + (sprite) * 0x1000)
#define SPCSC_OOFF(x) (((x) & 0x7ff) << 16) /* s11 */
#define SPCSC_IOFF(x) (((x) & 0x7ff) << 0) /* s11 */
-#define SPCSCC01(sprite) (VLV_DISPLAY_BASE + 0x6d90c + (sprite) * 0x1000)
-#define SPCSCC23(sprite) (VLV_DISPLAY_BASE + 0x6d910 + (sprite) * 0x1000)
-#define SPCSCC45(sprite) (VLV_DISPLAY_BASE + 0x6d914 + (sprite) * 0x1000)
-#define SPCSCC67(sprite) (VLV_DISPLAY_BASE + 0x6d918 + (sprite) * 0x1000)
-#define SPCSCC8(sprite) (VLV_DISPLAY_BASE + 0x6d91c + (sprite) * 0x1000)
+#define SPCSCC01(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d90c + (sprite) * 0x1000)
+#define SPCSCC23(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d910 + (sprite) * 0x1000)
+#define SPCSCC45(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d914 + (sprite) * 0x1000)
+#define SPCSCC67(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d918 + (sprite) * 0x1000)
+#define SPCSCC8(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d91c + (sprite) * 0x1000)
#define SPCSC_C1(x) (((x) & 0x7fff) << 16) /* s3.12 */
#define SPCSC_C0(x) (((x) & 0x7fff) << 0) /* s3.12 */
-#define SPCSCYGICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d920 + (sprite) * 0x1000)
-#define SPCSCCBICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d924 + (sprite) * 0x1000)
-#define SPCSCCRICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d928 + (sprite) * 0x1000)
+#define SPCSCYGICLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d920 + (sprite) * 0x1000)
+#define SPCSCCBICLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d924 + (sprite) * 0x1000)
+#define SPCSCCRICLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d928 + (sprite) * 0x1000)
#define SPCSC_IMAX(x) (((x) & 0x7ff) << 16) /* s11 */
#define SPCSC_IMIN(x) (((x) & 0x7ff) << 0) /* s11 */
-#define SPCSCYGOCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d92c + (sprite) * 0x1000)
-#define SPCSCCBOCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d930 + (sprite) * 0x1000)
-#define SPCSCCROCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d934 + (sprite) * 0x1000)
+#define SPCSCYGOCLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d92c + (sprite) * 0x1000)
+#define SPCSCCBOCLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d930 + (sprite) * 0x1000)
+#define SPCSCCROCLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d934 + (sprite) * 0x1000)
#define SPCSC_OMAX(x) ((x) << 16) /* u10 */
#define SPCSC_OMIN(x) ((x) << 0) /* u10 */
@@ -5346,7 +5402,7 @@ enum skl_disp_power_wells {
#define _PLANE_CTL_2(pipe) _PIPE(pipe, _PLANE_CTL_2_A, _PLANE_CTL_2_B)
#define _PLANE_CTL_3(pipe) _PIPE(pipe, _PLANE_CTL_3_A, _PLANE_CTL_3_B)
#define PLANE_CTL(pipe, plane) \
- _PLANE(plane, _PLANE_CTL_1(pipe), _PLANE_CTL_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_CTL_1(pipe), _PLANE_CTL_2(pipe))
#define _PLANE_STRIDE_1_B 0x71188
#define _PLANE_STRIDE_2_B 0x71288
@@ -5358,7 +5414,7 @@ enum skl_disp_power_wells {
#define _PLANE_STRIDE_3(pipe) \
_PIPE(pipe, _PLANE_STRIDE_3_A, _PLANE_STRIDE_3_B)
#define PLANE_STRIDE(pipe, plane) \
- _PLANE(plane, _PLANE_STRIDE_1(pipe), _PLANE_STRIDE_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_STRIDE_1(pipe), _PLANE_STRIDE_2(pipe))
#define _PLANE_POS_1_B 0x7118c
#define _PLANE_POS_2_B 0x7128c
@@ -5367,7 +5423,7 @@ enum skl_disp_power_wells {
#define _PLANE_POS_2(pipe) _PIPE(pipe, _PLANE_POS_2_A, _PLANE_POS_2_B)
#define _PLANE_POS_3(pipe) _PIPE(pipe, _PLANE_POS_3_A, _PLANE_POS_3_B)
#define PLANE_POS(pipe, plane) \
- _PLANE(plane, _PLANE_POS_1(pipe), _PLANE_POS_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_POS_1(pipe), _PLANE_POS_2(pipe))
#define _PLANE_SIZE_1_B 0x71190
#define _PLANE_SIZE_2_B 0x71290
@@ -5376,7 +5432,7 @@ enum skl_disp_power_wells {
#define _PLANE_SIZE_2(pipe) _PIPE(pipe, _PLANE_SIZE_2_A, _PLANE_SIZE_2_B)
#define _PLANE_SIZE_3(pipe) _PIPE(pipe, _PLANE_SIZE_3_A, _PLANE_SIZE_3_B)
#define PLANE_SIZE(pipe, plane) \
- _PLANE(plane, _PLANE_SIZE_1(pipe), _PLANE_SIZE_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_SIZE_1(pipe), _PLANE_SIZE_2(pipe))
#define _PLANE_SURF_1_B 0x7119c
#define _PLANE_SURF_2_B 0x7129c
@@ -5385,35 +5441,35 @@ enum skl_disp_power_wells {
#define _PLANE_SURF_2(pipe) _PIPE(pipe, _PLANE_SURF_2_A, _PLANE_SURF_2_B)
#define _PLANE_SURF_3(pipe) _PIPE(pipe, _PLANE_SURF_3_A, _PLANE_SURF_3_B)
#define PLANE_SURF(pipe, plane) \
- _PLANE(plane, _PLANE_SURF_1(pipe), _PLANE_SURF_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_SURF_1(pipe), _PLANE_SURF_2(pipe))
#define _PLANE_OFFSET_1_B 0x711a4
#define _PLANE_OFFSET_2_B 0x712a4
#define _PLANE_OFFSET_1(pipe) _PIPE(pipe, _PLANE_OFFSET_1_A, _PLANE_OFFSET_1_B)
#define _PLANE_OFFSET_2(pipe) _PIPE(pipe, _PLANE_OFFSET_2_A, _PLANE_OFFSET_2_B)
#define PLANE_OFFSET(pipe, plane) \
- _PLANE(plane, _PLANE_OFFSET_1(pipe), _PLANE_OFFSET_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_OFFSET_1(pipe), _PLANE_OFFSET_2(pipe))
#define _PLANE_KEYVAL_1_B 0x71194
#define _PLANE_KEYVAL_2_B 0x71294
#define _PLANE_KEYVAL_1(pipe) _PIPE(pipe, _PLANE_KEYVAL_1_A, _PLANE_KEYVAL_1_B)
#define _PLANE_KEYVAL_2(pipe) _PIPE(pipe, _PLANE_KEYVAL_2_A, _PLANE_KEYVAL_2_B)
#define PLANE_KEYVAL(pipe, plane) \
- _PLANE(plane, _PLANE_KEYVAL_1(pipe), _PLANE_KEYVAL_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_KEYVAL_1(pipe), _PLANE_KEYVAL_2(pipe))
#define _PLANE_KEYMSK_1_B 0x71198
#define _PLANE_KEYMSK_2_B 0x71298
#define _PLANE_KEYMSK_1(pipe) _PIPE(pipe, _PLANE_KEYMSK_1_A, _PLANE_KEYMSK_1_B)
#define _PLANE_KEYMSK_2(pipe) _PIPE(pipe, _PLANE_KEYMSK_2_A, _PLANE_KEYMSK_2_B)
#define PLANE_KEYMSK(pipe, plane) \
- _PLANE(plane, _PLANE_KEYMSK_1(pipe), _PLANE_KEYMSK_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_KEYMSK_1(pipe), _PLANE_KEYMSK_2(pipe))
#define _PLANE_KEYMAX_1_B 0x711a0
#define _PLANE_KEYMAX_2_B 0x712a0
#define _PLANE_KEYMAX_1(pipe) _PIPE(pipe, _PLANE_KEYMAX_1_A, _PLANE_KEYMAX_1_B)
#define _PLANE_KEYMAX_2(pipe) _PIPE(pipe, _PLANE_KEYMAX_2_A, _PLANE_KEYMAX_2_B)
#define PLANE_KEYMAX(pipe, plane) \
- _PLANE(plane, _PLANE_KEYMAX_1(pipe), _PLANE_KEYMAX_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_KEYMAX_1(pipe), _PLANE_KEYMAX_2(pipe))
#define _PLANE_BUF_CFG_1_B 0x7127c
#define _PLANE_BUF_CFG_2_B 0x7137c
@@ -5422,7 +5478,7 @@ enum skl_disp_power_wells {
#define _PLANE_BUF_CFG_2(pipe) \
_PIPE(pipe, _PLANE_BUF_CFG_2_A, _PLANE_BUF_CFG_2_B)
#define PLANE_BUF_CFG(pipe, plane) \
- _PLANE(plane, _PLANE_BUF_CFG_1(pipe), _PLANE_BUF_CFG_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_BUF_CFG_1(pipe), _PLANE_BUF_CFG_2(pipe))
#define _PLANE_NV12_BUF_CFG_1_B 0x71278
#define _PLANE_NV12_BUF_CFG_2_B 0x71378
@@ -5431,26 +5487,26 @@ enum skl_disp_power_wells {
#define _PLANE_NV12_BUF_CFG_2(pipe) \
_PIPE(pipe, _PLANE_NV12_BUF_CFG_2_A, _PLANE_NV12_BUF_CFG_2_B)
#define PLANE_NV12_BUF_CFG(pipe, plane) \
- _PLANE(plane, _PLANE_NV12_BUF_CFG_1(pipe), _PLANE_NV12_BUF_CFG_2(pipe))
+ _MMIO_PLANE(plane, _PLANE_NV12_BUF_CFG_1(pipe), _PLANE_NV12_BUF_CFG_2(pipe))
/* SKL new cursor registers */
#define _CUR_BUF_CFG_A 0x7017c
#define _CUR_BUF_CFG_B 0x7117c
-#define CUR_BUF_CFG(pipe) _PIPE(pipe, _CUR_BUF_CFG_A, _CUR_BUF_CFG_B)
+#define CUR_BUF_CFG(pipe) _MMIO_PIPE(pipe, _CUR_BUF_CFG_A, _CUR_BUF_CFG_B)
/* VBIOS regs */
-#define VGACNTRL 0x71400
+#define VGACNTRL _MMIO(0x71400)
# define VGA_DISP_DISABLE (1 << 31)
# define VGA_2X_MODE (1 << 30)
# define VGA_PIPE_B_SELECT (1 << 29)
-#define VLV_VGACNTRL (VLV_DISPLAY_BASE + 0x71400)
+#define VLV_VGACNTRL _MMIO(VLV_DISPLAY_BASE + 0x71400)
/* Ironlake */
-#define CPU_VGACNTRL 0x41000
+#define CPU_VGACNTRL _MMIO(0x41000)
-#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030
+#define DIGITAL_PORT_HOTPLUG_CNTRL _MMIO(0x44030)
#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4)
#define DIGITAL_PORTA_PULSE_DURATION_2ms (0 << 2) /* pre-HSW */
#define DIGITAL_PORTA_PULSE_DURATION_4_5ms (1 << 2) /* pre-HSW */
@@ -5463,26 +5519,26 @@ enum skl_disp_power_wells {
#define DIGITAL_PORTA_HOTPLUG_LONG_DETECT (2 << 0)
/* refresh rate hardware control */
-#define RR_HW_CTL 0x45300
+#define RR_HW_CTL _MMIO(0x45300)
#define RR_HW_LOW_POWER_FRAMES_MASK 0xff
#define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00
-#define FDI_PLL_BIOS_0 0x46000
+#define FDI_PLL_BIOS_0 _MMIO(0x46000)
#define FDI_PLL_FB_CLOCK_MASK 0xff
-#define FDI_PLL_BIOS_1 0x46004
-#define FDI_PLL_BIOS_2 0x46008
-#define DISPLAY_PORT_PLL_BIOS_0 0x4600c
-#define DISPLAY_PORT_PLL_BIOS_1 0x46010
-#define DISPLAY_PORT_PLL_BIOS_2 0x46014
+#define FDI_PLL_BIOS_1 _MMIO(0x46004)
+#define FDI_PLL_BIOS_2 _MMIO(0x46008)
+#define DISPLAY_PORT_PLL_BIOS_0 _MMIO(0x4600c)
+#define DISPLAY_PORT_PLL_BIOS_1 _MMIO(0x46010)
+#define DISPLAY_PORT_PLL_BIOS_2 _MMIO(0x46014)
-#define PCH_3DCGDIS0 0x46020
+#define PCH_3DCGDIS0 _MMIO(0x46020)
# define MARIUNIT_CLOCK_GATE_DISABLE (1 << 18)
# define SVSMUNIT_CLOCK_GATE_DISABLE (1 << 1)
-#define PCH_3DCGDIS1 0x46024
+#define PCH_3DCGDIS1 _MMIO(0x46024)
# define VFMUNIT_CLOCK_GATE_DISABLE (1 << 11)
-#define FDI_PLL_FREQ_CTL 0x46030
+#define FDI_PLL_FREQ_CTL _MMIO(0x46030)
#define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24)
#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00
#define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff
@@ -5519,14 +5575,14 @@ enum skl_disp_power_wells {
#define _PIPEB_LINK_M2 0x61048
#define _PIPEB_LINK_N2 0x6104c
-#define PIPE_DATA_M1(tran) _TRANSCODER2(tran, _PIPEA_DATA_M1)
-#define PIPE_DATA_N1(tran) _TRANSCODER2(tran, _PIPEA_DATA_N1)
-#define PIPE_DATA_M2(tran) _TRANSCODER2(tran, _PIPEA_DATA_M2)
-#define PIPE_DATA_N2(tran) _TRANSCODER2(tran, _PIPEA_DATA_N2)
-#define PIPE_LINK_M1(tran) _TRANSCODER2(tran, _PIPEA_LINK_M1)
-#define PIPE_LINK_N1(tran) _TRANSCODER2(tran, _PIPEA_LINK_N1)
-#define PIPE_LINK_M2(tran) _TRANSCODER2(tran, _PIPEA_LINK_M2)
-#define PIPE_LINK_N2(tran) _TRANSCODER2(tran, _PIPEA_LINK_N2)
+#define PIPE_DATA_M1(tran) _MMIO_TRANS2(tran, _PIPEA_DATA_M1)
+#define PIPE_DATA_N1(tran) _MMIO_TRANS2(tran, _PIPEA_DATA_N1)
+#define PIPE_DATA_M2(tran) _MMIO_TRANS2(tran, _PIPEA_DATA_M2)
+#define PIPE_DATA_N2(tran) _MMIO_TRANS2(tran, _PIPEA_DATA_N2)
+#define PIPE_LINK_M1(tran) _MMIO_TRANS2(tran, _PIPEA_LINK_M1)
+#define PIPE_LINK_N1(tran) _MMIO_TRANS2(tran, _PIPEA_LINK_N1)
+#define PIPE_LINK_M2(tran) _MMIO_TRANS2(tran, _PIPEA_LINK_M2)
+#define PIPE_LINK_N2(tran) _MMIO_TRANS2(tran, _PIPEA_LINK_N2)
/* CPU panel fitter */
/* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */
@@ -5549,11 +5605,11 @@ enum skl_disp_power_wells {
#define _PFA_HSCALE 0x68090
#define _PFB_HSCALE 0x68890
-#define PF_CTL(pipe) _PIPE(pipe, _PFA_CTL_1, _PFB_CTL_1)
-#define PF_WIN_SZ(pipe) _PIPE(pipe, _PFA_WIN_SZ, _PFB_WIN_SZ)
-#define PF_WIN_POS(pipe) _PIPE(pipe, _PFA_WIN_POS, _PFB_WIN_POS)
-#define PF_VSCALE(pipe) _PIPE(pipe, _PFA_VSCALE, _PFB_VSCALE)
-#define PF_HSCALE(pipe) _PIPE(pipe, _PFA_HSCALE, _PFB_HSCALE)
+#define PF_CTL(pipe) _MMIO_PIPE(pipe, _PFA_CTL_1, _PFB_CTL_1)
+#define PF_WIN_SZ(pipe) _MMIO_PIPE(pipe, _PFA_WIN_SZ, _PFB_WIN_SZ)
+#define PF_WIN_POS(pipe) _MMIO_PIPE(pipe, _PFA_WIN_POS, _PFB_WIN_POS)
+#define PF_VSCALE(pipe) _MMIO_PIPE(pipe, _PFA_VSCALE, _PFB_VSCALE)
+#define PF_HSCALE(pipe) _MMIO_PIPE(pipe, _PFA_HSCALE, _PFB_HSCALE)
#define _PSA_CTL 0x68180
#define _PSB_CTL 0x68980
@@ -5563,9 +5619,9 @@ enum skl_disp_power_wells {
#define _PSA_WIN_POS 0x68170
#define _PSB_WIN_POS 0x68970
-#define PS_CTL(pipe) _PIPE(pipe, _PSA_CTL, _PSB_CTL)
-#define PS_WIN_SZ(pipe) _PIPE(pipe, _PSA_WIN_SZ, _PSB_WIN_SZ)
-#define PS_WIN_POS(pipe) _PIPE(pipe, _PSA_WIN_POS, _PSB_WIN_POS)
+#define PS_CTL(pipe) _MMIO_PIPE(pipe, _PSA_CTL, _PSB_CTL)
+#define PS_WIN_SZ(pipe) _MMIO_PIPE(pipe, _PSA_WIN_SZ, _PSB_WIN_SZ)
+#define PS_WIN_POS(pipe) _MMIO_PIPE(pipe, _PSA_WIN_POS, _PSB_WIN_POS)
/*
* Skylake scalers
@@ -5654,48 +5710,63 @@ enum skl_disp_power_wells {
#define _PS_ECC_STAT_1C 0x691D0
#define _ID(id, a, b) ((a) + (id)*((b)-(a)))
-#define SKL_PS_CTRL(pipe, id) _PIPE(pipe, \
+#define SKL_PS_CTRL(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_1A_CTRL, _PS_2A_CTRL), \
_ID(id, _PS_1B_CTRL, _PS_2B_CTRL))
-#define SKL_PS_PWR_GATE(pipe, id) _PIPE(pipe, \
+#define SKL_PS_PWR_GATE(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_PWR_GATE_1A, _PS_PWR_GATE_2A), \
_ID(id, _PS_PWR_GATE_1B, _PS_PWR_GATE_2B))
-#define SKL_PS_WIN_POS(pipe, id) _PIPE(pipe, \
+#define SKL_PS_WIN_POS(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_WIN_POS_1A, _PS_WIN_POS_2A), \
_ID(id, _PS_WIN_POS_1B, _PS_WIN_POS_2B))
-#define SKL_PS_WIN_SZ(pipe, id) _PIPE(pipe, \
+#define SKL_PS_WIN_SZ(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_WIN_SZ_1A, _PS_WIN_SZ_2A), \
_ID(id, _PS_WIN_SZ_1B, _PS_WIN_SZ_2B))
-#define SKL_PS_VSCALE(pipe, id) _PIPE(pipe, \
+#define SKL_PS_VSCALE(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_VSCALE_1A, _PS_VSCALE_2A), \
_ID(id, _PS_VSCALE_1B, _PS_VSCALE_2B))
-#define SKL_PS_HSCALE(pipe, id) _PIPE(pipe, \
+#define SKL_PS_HSCALE(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_HSCALE_1A, _PS_HSCALE_2A), \
_ID(id, _PS_HSCALE_1B, _PS_HSCALE_2B))
-#define SKL_PS_VPHASE(pipe, id) _PIPE(pipe, \
+#define SKL_PS_VPHASE(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_VPHASE_1A, _PS_VPHASE_2A), \
_ID(id, _PS_VPHASE_1B, _PS_VPHASE_2B))
-#define SKL_PS_HPHASE(pipe, id) _PIPE(pipe, \
+#define SKL_PS_HPHASE(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_HPHASE_1A, _PS_HPHASE_2A), \
_ID(id, _PS_HPHASE_1B, _PS_HPHASE_2B))
-#define SKL_PS_ECC_STAT(pipe, id) _PIPE(pipe, \
+#define SKL_PS_ECC_STAT(pipe, id) _MMIO_PIPE(pipe, \
_ID(id, _PS_ECC_STAT_1A, _PS_ECC_STAT_2A), \
- _ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B)
+ _ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B))
/* legacy palette */
#define _LGC_PALETTE_A 0x4a000
#define _LGC_PALETTE_B 0x4a800
-#define LGC_PALETTE(pipe, i) (_PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) + (i) * 4)
+#define LGC_PALETTE(pipe, i) _MMIO(_PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) + (i) * 4)
#define _GAMMA_MODE_A 0x4a480
#define _GAMMA_MODE_B 0x4ac80
-#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
+#define GAMMA_MODE(pipe) _MMIO_PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
#define GAMMA_MODE_MODE_MASK (3 << 0)
#define GAMMA_MODE_MODE_8BIT (0 << 0)
#define GAMMA_MODE_MODE_10BIT (1 << 0)
#define GAMMA_MODE_MODE_12BIT (2 << 0)
#define GAMMA_MODE_MODE_SPLIT (3 << 0)
+/* DMC/CSR */
+#define CSR_PROGRAM(i) _MMIO(0x80000 + (i) * 4)
+#define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0
+#define CSR_HTP_ADDR_SKL 0x00500034
+#define CSR_SSP_BASE _MMIO(0x8F074)
+#define CSR_HTP_SKL _MMIO(0x8F004)
+#define CSR_LAST_WRITE _MMIO(0x8F034)
+#define CSR_LAST_WRITE_VALUE 0xc003b400
+/* MMIO address range for CSR program (0x80000 - 0x82FFF) */
+#define CSR_MMIO_START_RANGE 0x80000
+#define CSR_MMIO_END_RANGE 0x8FFFF
+#define SKL_CSR_DC3_DC5_COUNT _MMIO(0x80030)
+#define SKL_CSR_DC5_DC6_COUNT _MMIO(0x8002C)
+#define BXT_CSR_DC3_DC5_COUNT _MMIO(0x80038)
+
/* interrupts */
#define DE_MASTER_IRQ_CONTROL (1 << 31)
#define DE_SPRITEB_FLIP_DONE (1 << 29)
@@ -5747,20 +5818,20 @@ enum skl_disp_power_wells {
#define DE_PIPEA_VBLANK_IVB (1<<0)
#define DE_PIPE_VBLANK_IVB(pipe) (1 << ((pipe) * 5))
-#define VLV_MASTER_IER 0x4400c /* Gunit master IER */
+#define VLV_MASTER_IER _MMIO(0x4400c) /* Gunit master IER */
#define MASTER_INTERRUPT_ENABLE (1<<31)
-#define DEISR 0x44000
-#define DEIMR 0x44004
-#define DEIIR 0x44008
-#define DEIER 0x4400c
+#define DEISR _MMIO(0x44000)
+#define DEIMR _MMIO(0x44004)
+#define DEIIR _MMIO(0x44008)
+#define DEIER _MMIO(0x4400c)
-#define GTISR 0x44010
-#define GTIMR 0x44014
-#define GTIIR 0x44018
-#define GTIER 0x4401c
+#define GTISR _MMIO(0x44010)
+#define GTIMR _MMIO(0x44014)
+#define GTIIR _MMIO(0x44018)
+#define GTIER _MMIO(0x4401c)
-#define GEN8_MASTER_IRQ 0x44200
+#define GEN8_MASTER_IRQ _MMIO(0x44200)
#define GEN8_MASTER_IRQ_CONTROL (1<<31)
#define GEN8_PCU_IRQ (1<<30)
#define GEN8_DE_PCH_IRQ (1<<23)
@@ -5777,10 +5848,10 @@ enum skl_disp_power_wells {
#define GEN8_GT_BCS_IRQ (1<<1)
#define GEN8_GT_RCS_IRQ (1<<0)
-#define GEN8_GT_ISR(which) (0x44300 + (0x10 * (which)))
-#define GEN8_GT_IMR(which) (0x44304 + (0x10 * (which)))
-#define GEN8_GT_IIR(which) (0x44308 + (0x10 * (which)))
-#define GEN8_GT_IER(which) (0x4430c + (0x10 * (which)))
+#define GEN8_GT_ISR(which) _MMIO(0x44300 + (0x10 * (which)))
+#define GEN8_GT_IMR(which) _MMIO(0x44304 + (0x10 * (which)))
+#define GEN8_GT_IIR(which) _MMIO(0x44308 + (0x10 * (which)))
+#define GEN8_GT_IER(which) _MMIO(0x4430c + (0x10 * (which)))
#define GEN8_RCS_IRQ_SHIFT 0
#define GEN8_BCS_IRQ_SHIFT 16
@@ -5789,10 +5860,10 @@ enum skl_disp_power_wells {
#define GEN8_VECS_IRQ_SHIFT 0
#define GEN8_WD_IRQ_SHIFT 16
-#define GEN8_DE_PIPE_ISR(pipe) (0x44400 + (0x10 * (pipe)))
-#define GEN8_DE_PIPE_IMR(pipe) (0x44404 + (0x10 * (pipe)))
-#define GEN8_DE_PIPE_IIR(pipe) (0x44408 + (0x10 * (pipe)))
-#define GEN8_DE_PIPE_IER(pipe) (0x4440c + (0x10 * (pipe)))
+#define GEN8_DE_PIPE_ISR(pipe) _MMIO(0x44400 + (0x10 * (pipe)))
+#define GEN8_DE_PIPE_IMR(pipe) _MMIO(0x44404 + (0x10 * (pipe)))
+#define GEN8_DE_PIPE_IIR(pipe) _MMIO(0x44408 + (0x10 * (pipe)))
+#define GEN8_DE_PIPE_IER(pipe) _MMIO(0x4440c + (0x10 * (pipe)))
#define GEN8_PIPE_FIFO_UNDERRUN (1 << 31)
#define GEN8_PIPE_CDCLK_CRC_ERROR (1 << 29)
#define GEN8_PIPE_CDCLK_CRC_DONE (1 << 28)
@@ -5825,10 +5896,10 @@ enum skl_disp_power_wells {
GEN9_PIPE_PLANE2_FAULT | \
GEN9_PIPE_PLANE1_FAULT)
-#define GEN8_DE_PORT_ISR 0x44440
-#define GEN8_DE_PORT_IMR 0x44444
-#define GEN8_DE_PORT_IIR 0x44448
-#define GEN8_DE_PORT_IER 0x4444c
+#define GEN8_DE_PORT_ISR _MMIO(0x44440)
+#define GEN8_DE_PORT_IMR _MMIO(0x44444)
+#define GEN8_DE_PORT_IIR _MMIO(0x44448)
+#define GEN8_DE_PORT_IER _MMIO(0x4444c)
#define GEN9_AUX_CHANNEL_D (1 << 27)
#define GEN9_AUX_CHANNEL_C (1 << 26)
#define GEN9_AUX_CHANNEL_B (1 << 25)
@@ -5842,23 +5913,23 @@ enum skl_disp_power_wells {
#define BXT_DE_PORT_GMBUS (1 << 1)
#define GEN8_AUX_CHANNEL_A (1 << 0)
-#define GEN8_DE_MISC_ISR 0x44460
-#define GEN8_DE_MISC_IMR 0x44464
-#define GEN8_DE_MISC_IIR 0x44468
-#define GEN8_DE_MISC_IER 0x4446c
+#define GEN8_DE_MISC_ISR _MMIO(0x44460)
+#define GEN8_DE_MISC_IMR _MMIO(0x44464)
+#define GEN8_DE_MISC_IIR _MMIO(0x44468)
+#define GEN8_DE_MISC_IER _MMIO(0x4446c)
#define GEN8_DE_MISC_GSE (1 << 27)
-#define GEN8_PCU_ISR 0x444e0
-#define GEN8_PCU_IMR 0x444e4
-#define GEN8_PCU_IIR 0x444e8
-#define GEN8_PCU_IER 0x444ec
+#define GEN8_PCU_ISR _MMIO(0x444e0)
+#define GEN8_PCU_IMR _MMIO(0x444e4)
+#define GEN8_PCU_IIR _MMIO(0x444e8)
+#define GEN8_PCU_IER _MMIO(0x444ec)
-#define ILK_DISPLAY_CHICKEN2 0x42004
+#define ILK_DISPLAY_CHICKEN2 _MMIO(0x42004)
/* Required on all Ironlake and Sandybridge according to the B-Spec. */
#define ILK_ELPIN_409_SELECT (1 << 25)
#define ILK_DPARB_GATE (1<<22)
#define ILK_VSDPFD_FULL (1<<21)
-#define FUSE_STRAP 0x42014
+#define FUSE_STRAP _MMIO(0x42014)
#define ILK_INTERNAL_GRAPHICS_DISABLE (1 << 31)
#define ILK_INTERNAL_DISPLAY_DISABLE (1 << 30)
#define ILK_DISPLAY_DEBUG_DISABLE (1 << 29)
@@ -5867,18 +5938,18 @@ enum skl_disp_power_wells {
#define HSW_CDCLK_LIMIT (1 << 24)
#define ILK_DESKTOP (1 << 23)
-#define ILK_DSPCLK_GATE_D 0x42020
+#define ILK_DSPCLK_GATE_D _MMIO(0x42020)
#define ILK_VRHUNIT_CLOCK_GATE_DISABLE (1 << 28)
#define ILK_DPFCUNIT_CLOCK_GATE_DISABLE (1 << 9)
#define ILK_DPFCRUNIT_CLOCK_GATE_DISABLE (1 << 8)
#define ILK_DPFDUNIT_CLOCK_GATE_ENABLE (1 << 7)
#define ILK_DPARBUNIT_CLOCK_GATE_ENABLE (1 << 5)
-#define IVB_CHICKEN3 0x4200c
+#define IVB_CHICKEN3 _MMIO(0x4200c)
# define CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE (1 << 5)
# define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2)
-#define CHICKEN_PAR1_1 0x42080
+#define CHICKEN_PAR1_1 _MMIO(0x42080)
#define DPA_MASK_VBLANK_SRD (1 << 15)
#define FORCE_ARB_IDLE_PLANES (1 << 14)
@@ -5886,70 +5957,70 @@ enum skl_disp_power_wells {
#define _CHICKEN_PIPESL_1_B 0x420b4
#define HSW_FBCQ_DIS (1 << 22)
#define BDW_DPRS_MASK_VBLANK_SRD (1 << 0)
-#define CHICKEN_PIPESL_1(pipe) _PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B)
+#define CHICKEN_PIPESL_1(pipe) _MMIO_PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B)
-#define DISP_ARB_CTL 0x45000
+#define DISP_ARB_CTL _MMIO(0x45000)
#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
#define DISP_FBC_WM_DIS (1<<15)
-#define DISP_ARB_CTL2 0x45004
+#define DISP_ARB_CTL2 _MMIO(0x45004)
#define DISP_DATA_PARTITION_5_6 (1<<6)
-#define DBUF_CTL 0x45008
+#define DBUF_CTL _MMIO(0x45008)
#define DBUF_POWER_REQUEST (1<<31)
#define DBUF_POWER_STATE (1<<30)
-#define GEN7_MSG_CTL 0x45010
+#define GEN7_MSG_CTL _MMIO(0x45010)
#define WAIT_FOR_PCH_RESET_ACK (1<<1)
#define WAIT_FOR_PCH_FLR_ACK (1<<0)
-#define HSW_NDE_RSTWRN_OPT 0x46408
+#define HSW_NDE_RSTWRN_OPT _MMIO(0x46408)
#define RESET_PCH_HANDSHAKE_ENABLE (1<<4)
-#define SKL_DFSM 0x51000
+#define SKL_DFSM _MMIO(0x51000)
#define SKL_DFSM_CDCLK_LIMIT_MASK (3 << 23)
#define SKL_DFSM_CDCLK_LIMIT_675 (0 << 23)
#define SKL_DFSM_CDCLK_LIMIT_540 (1 << 23)
#define SKL_DFSM_CDCLK_LIMIT_450 (2 << 23)
#define SKL_DFSM_CDCLK_LIMIT_337_5 (3 << 23)
-#define FF_SLICE_CS_CHICKEN2 0x20e4
+#define FF_SLICE_CS_CHICKEN2 _MMIO(0x20e4)
#define GEN9_TSG_BARRIER_ACK_DISABLE (1<<8)
/* GEN7 chicken */
-#define GEN7_COMMON_SLICE_CHICKEN1 0x7010
+#define GEN7_COMMON_SLICE_CHICKEN1 _MMIO(0x7010)
# define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26))
# define GEN9_RHWO_OPTIMIZATION_DISABLE (1<<14)
-#define COMMON_SLICE_CHICKEN2 0x7014
+#define COMMON_SLICE_CHICKEN2 _MMIO(0x7014)
# define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE (1<<0)
-#define HIZ_CHICKEN 0x7018
+#define HIZ_CHICKEN _MMIO(0x7018)
# define CHV_HZ_8X8_MODE_IN_1X (1<<15)
# define BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE (1<<3)
-#define GEN9_SLICE_COMMON_ECO_CHICKEN0 0x7308
+#define GEN9_SLICE_COMMON_ECO_CHICKEN0 _MMIO(0x7308)
#define DISABLE_PIXEL_MASK_CAMMING (1<<14)
-#define GEN7_L3SQCREG1 0xB010
+#define GEN7_L3SQCREG1 _MMIO(0xB010)
#define VLV_B0_WA_L3SQCREG1_VALUE 0x00D30000
-#define GEN8_L3SQCREG1 0xB100
+#define GEN8_L3SQCREG1 _MMIO(0xB100)
#define BDW_WA_L3SQCREG1_DEFAULT 0x784000
-#define GEN7_L3CNTLREG1 0xB01C
+#define GEN7_L3CNTLREG1 _MMIO(0xB01C)
#define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C
#define GEN7_L3AGDIS (1<<19)
-#define GEN7_L3CNTLREG2 0xB020
-#define GEN7_L3CNTLREG3 0xB024
+#define GEN7_L3CNTLREG2 _MMIO(0xB020)
+#define GEN7_L3CNTLREG3 _MMIO(0xB024)
-#define GEN7_L3_CHICKEN_MODE_REGISTER 0xB030
+#define GEN7_L3_CHICKEN_MODE_REGISTER _MMIO(0xB030)
#define GEN7_WA_L3_CHICKEN_MODE 0x20000000
-#define GEN7_L3SQCREG4 0xb034
+#define GEN7_L3SQCREG4 _MMIO(0xb034)
#define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27)
-#define GEN8_L3SQCREG4 0xb118
+#define GEN8_L3SQCREG4 _MMIO(0xb118)
#define GEN8_LQSC_RO_PERF_DIS (1<<27)
#define GEN8_LQSC_FLUSH_COHERENT_LINES (1<<21)
/* GEN8 chicken */
-#define HDC_CHICKEN0 0x7300
+#define HDC_CHICKEN0 _MMIO(0x7300)
#define HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE (1<<15)
#define HDC_FENCE_DEST_SLM_DISABLE (1<<14)
#define HDC_DONOT_FETCH_MEM_WHEN_MASKED (1<<11)
@@ -5958,17 +6029,17 @@ enum skl_disp_power_wells {
#define HDC_BARRIER_PERFORMANCE_DISABLE (1<<10)
/* GEN9 chicken */
-#define SLICE_ECO_CHICKEN0 0x7308
+#define SLICE_ECO_CHICKEN0 _MMIO(0x7308)
#define PIXEL_MASK_CAMMING_DISABLE (1 << 14)
/* WaCatErrorRejectionIssue */
-#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030
+#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG _MMIO(0x9030)
#define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11)
-#define HSW_SCRATCH1 0xb038
+#define HSW_SCRATCH1 _MMIO(0xb038)
#define HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE (1<<27)
-#define BDW_SCRATCH1 0xb11c
+#define BDW_SCRATCH1 _MMIO(0xb11c)
#define GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE (1<<2)
/* PCH */
@@ -6062,12 +6133,12 @@ enum skl_disp_power_wells {
SDE_FDI_RXB_CPT | \
SDE_FDI_RXA_CPT)
-#define SDEISR 0xc4000
-#define SDEIMR 0xc4004
-#define SDEIIR 0xc4008
-#define SDEIER 0xc400c
+#define SDEISR _MMIO(0xc4000)
+#define SDEIMR _MMIO(0xc4004)
+#define SDEIIR _MMIO(0xc4008)
+#define SDEIER _MMIO(0xc400c)
-#define SERR_INT 0xc4040
+#define SERR_INT _MMIO(0xc4040)
#define SERR_INT_POISON (1<<31)
#define SERR_INT_TRANS_C_FIFO_UNDERRUN (1<<6)
#define SERR_INT_TRANS_B_FIFO_UNDERRUN (1<<3)
@@ -6075,7 +6146,7 @@ enum skl_disp_power_wells {
#define SERR_INT_TRANS_FIFO_UNDERRUN(pipe) (1<<((pipe)*3))
/* digital port hotplug */
-#define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */
+#define PCH_PORT_HOTPLUG _MMIO(0xc4030) /* SHOTPLUG_CTL */
#define PORTA_HOTPLUG_ENABLE (1 << 28) /* LPT:LP+ & BXT */
#define PORTA_HOTPLUG_STATUS_MASK (3 << 24) /* SPT+ & BXT */
#define PORTA_HOTPLUG_NO_DETECT (0 << 24) /* SPT+ & BXT */
@@ -6112,42 +6183,42 @@ enum skl_disp_power_wells {
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (2 << 0)
-#define PCH_PORT_HOTPLUG2 0xc403C /* SHOTPLUG_CTL2 SPT+ */
+#define PCH_PORT_HOTPLUG2 _MMIO(0xc403C) /* SHOTPLUG_CTL2 SPT+ */
#define PORTE_HOTPLUG_ENABLE (1 << 4)
#define PORTE_HOTPLUG_STATUS_MASK (3 << 0)
#define PORTE_HOTPLUG_NO_DETECT (0 << 0)
#define PORTE_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTE_HOTPLUG_LONG_DETECT (2 << 0)
-#define PCH_GPIOA 0xc5010
-#define PCH_GPIOB 0xc5014
-#define PCH_GPIOC 0xc5018
-#define PCH_GPIOD 0xc501c
-#define PCH_GPIOE 0xc5020
-#define PCH_GPIOF 0xc5024
+#define PCH_GPIOA _MMIO(0xc5010)
+#define PCH_GPIOB _MMIO(0xc5014)
+#define PCH_GPIOC _MMIO(0xc5018)
+#define PCH_GPIOD _MMIO(0xc501c)
+#define PCH_GPIOE _MMIO(0xc5020)
+#define PCH_GPIOF _MMIO(0xc5024)
-#define PCH_GMBUS0 0xc5100
-#define PCH_GMBUS1 0xc5104
-#define PCH_GMBUS2 0xc5108
-#define PCH_GMBUS3 0xc510c
-#define PCH_GMBUS4 0xc5110
-#define PCH_GMBUS5 0xc5120
+#define PCH_GMBUS0 _MMIO(0xc5100)
+#define PCH_GMBUS1 _MMIO(0xc5104)
+#define PCH_GMBUS2 _MMIO(0xc5108)
+#define PCH_GMBUS3 _MMIO(0xc510c)
+#define PCH_GMBUS4 _MMIO(0xc5110)
+#define PCH_GMBUS5 _MMIO(0xc5120)
#define _PCH_DPLL_A 0xc6014
#define _PCH_DPLL_B 0xc6018
-#define PCH_DPLL(pll) (pll == 0 ? _PCH_DPLL_A : _PCH_DPLL_B)
+#define PCH_DPLL(pll) _MMIO(pll == 0 ? _PCH_DPLL_A : _PCH_DPLL_B)
#define _PCH_FPA0 0xc6040
#define FP_CB_TUNE (0x3<<22)
#define _PCH_FPA1 0xc6044
#define _PCH_FPB0 0xc6048
#define _PCH_FPB1 0xc604c
-#define PCH_FP0(pll) (pll == 0 ? _PCH_FPA0 : _PCH_FPB0)
-#define PCH_FP1(pll) (pll == 0 ? _PCH_FPA1 : _PCH_FPB1)
+#define PCH_FP0(pll) _MMIO(pll == 0 ? _PCH_FPA0 : _PCH_FPB0)
+#define PCH_FP1(pll) _MMIO(pll == 0 ? _PCH_FPA1 : _PCH_FPB1)
-#define PCH_DPLL_TEST 0xc606c
+#define PCH_DPLL_TEST _MMIO(0xc606c)
-#define PCH_DREF_CONTROL 0xC6200
+#define PCH_DREF_CONTROL _MMIO(0xC6200)
#define DREF_CONTROL_MASK 0x7fc3
#define DREF_CPU_SOURCE_OUTPUT_DISABLE (0<<13)
#define DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD (2<<13)
@@ -6170,19 +6241,19 @@ enum skl_disp_power_wells {
#define DREF_SSC4_DISABLE (0)
#define DREF_SSC4_ENABLE (1)
-#define PCH_RAWCLK_FREQ 0xc6204
+#define PCH_RAWCLK_FREQ _MMIO(0xc6204)
#define FDL_TP1_TIMER_SHIFT 12
#define FDL_TP1_TIMER_MASK (3<<12)
#define FDL_TP2_TIMER_SHIFT 10
#define FDL_TP2_TIMER_MASK (3<<10)
#define RAWCLK_FREQ_MASK 0x3ff
-#define PCH_DPLL_TMR_CFG 0xc6208
+#define PCH_DPLL_TMR_CFG _MMIO(0xc6208)
-#define PCH_SSC4_PARMS 0xc6210
-#define PCH_SSC4_AUX_PARMS 0xc6214
+#define PCH_SSC4_PARMS _MMIO(0xc6210)
+#define PCH_SSC4_AUX_PARMS _MMIO(0xc6214)
-#define PCH_DPLL_SEL 0xc7000
+#define PCH_DPLL_SEL _MMIO(0xc7000)
#define TRANS_DPLLB_SEL(pipe) (1 << ((pipe) * 4))
#define TRANS_DPLLA_SEL(pipe) 0
#define TRANS_DPLL_ENABLE(pipe) (1 << ((pipe) * 4 + 3))
@@ -6230,79 +6301,73 @@ enum skl_disp_power_wells {
#define _VIDEO_DIP_DATA_B 0xe1208
#define _VIDEO_DIP_GCP_B 0xe1210
-#define TVIDEO_DIP_CTL(pipe) _PIPE(pipe, _VIDEO_DIP_CTL_A, _VIDEO_DIP_CTL_B)
-#define TVIDEO_DIP_DATA(pipe) _PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B)
-#define TVIDEO_DIP_GCP(pipe) _PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B)
+#define TVIDEO_DIP_CTL(pipe) _MMIO_PIPE(pipe, _VIDEO_DIP_CTL_A, _VIDEO_DIP_CTL_B)
+#define TVIDEO_DIP_DATA(pipe) _MMIO_PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B)
+#define TVIDEO_DIP_GCP(pipe) _MMIO_PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B)
/* Per-transcoder DIP controls (VLV) */
-#define VLV_VIDEO_DIP_CTL_A (VLV_DISPLAY_BASE + 0x60200)
-#define VLV_VIDEO_DIP_DATA_A (VLV_DISPLAY_BASE + 0x60208)
-#define VLV_VIDEO_DIP_GDCP_PAYLOAD_A (VLV_DISPLAY_BASE + 0x60210)
+#define _VLV_VIDEO_DIP_CTL_A (VLV_DISPLAY_BASE + 0x60200)
+#define _VLV_VIDEO_DIP_DATA_A (VLV_DISPLAY_BASE + 0x60208)
+#define _VLV_VIDEO_DIP_GDCP_PAYLOAD_A (VLV_DISPLAY_BASE + 0x60210)
-#define VLV_VIDEO_DIP_CTL_B (VLV_DISPLAY_BASE + 0x61170)
-#define VLV_VIDEO_DIP_DATA_B (VLV_DISPLAY_BASE + 0x61174)
-#define VLV_VIDEO_DIP_GDCP_PAYLOAD_B (VLV_DISPLAY_BASE + 0x61178)
+#define _VLV_VIDEO_DIP_CTL_B (VLV_DISPLAY_BASE + 0x61170)
+#define _VLV_VIDEO_DIP_DATA_B (VLV_DISPLAY_BASE + 0x61174)
+#define _VLV_VIDEO_DIP_GDCP_PAYLOAD_B (VLV_DISPLAY_BASE + 0x61178)
-#define CHV_VIDEO_DIP_CTL_C (VLV_DISPLAY_BASE + 0x611f0)
-#define CHV_VIDEO_DIP_DATA_C (VLV_DISPLAY_BASE + 0x611f4)
-#define CHV_VIDEO_DIP_GDCP_PAYLOAD_C (VLV_DISPLAY_BASE + 0x611f8)
+#define _CHV_VIDEO_DIP_CTL_C (VLV_DISPLAY_BASE + 0x611f0)
+#define _CHV_VIDEO_DIP_DATA_C (VLV_DISPLAY_BASE + 0x611f4)
+#define _CHV_VIDEO_DIP_GDCP_PAYLOAD_C (VLV_DISPLAY_BASE + 0x611f8)
#define VLV_TVIDEO_DIP_CTL(pipe) \
- _PIPE3((pipe), VLV_VIDEO_DIP_CTL_A, \
- VLV_VIDEO_DIP_CTL_B, CHV_VIDEO_DIP_CTL_C)
+ _MMIO_PIPE3((pipe), _VLV_VIDEO_DIP_CTL_A, \
+ _VLV_VIDEO_DIP_CTL_B, _CHV_VIDEO_DIP_CTL_C)
#define VLV_TVIDEO_DIP_DATA(pipe) \
- _PIPE3((pipe), VLV_VIDEO_DIP_DATA_A, \
- VLV_VIDEO_DIP_DATA_B, CHV_VIDEO_DIP_DATA_C)
+ _MMIO_PIPE3((pipe), _VLV_VIDEO_DIP_DATA_A, \
+ _VLV_VIDEO_DIP_DATA_B, _CHV_VIDEO_DIP_DATA_C)
#define VLV_TVIDEO_DIP_GCP(pipe) \
- _PIPE3((pipe), VLV_VIDEO_DIP_GDCP_PAYLOAD_A, \
- VLV_VIDEO_DIP_GDCP_PAYLOAD_B, CHV_VIDEO_DIP_GDCP_PAYLOAD_C)
+ _MMIO_PIPE3((pipe), _VLV_VIDEO_DIP_GDCP_PAYLOAD_A, \
+ _VLV_VIDEO_DIP_GDCP_PAYLOAD_B, _CHV_VIDEO_DIP_GDCP_PAYLOAD_C)
/* Haswell DIP controls */
-#define HSW_VIDEO_DIP_CTL_A 0x60200
-#define HSW_VIDEO_DIP_AVI_DATA_A 0x60220
-#define HSW_VIDEO_DIP_VS_DATA_A 0x60260
-#define HSW_VIDEO_DIP_SPD_DATA_A 0x602A0
-#define HSW_VIDEO_DIP_GMP_DATA_A 0x602E0
-#define HSW_VIDEO_DIP_VSC_DATA_A 0x60320
-#define HSW_VIDEO_DIP_AVI_ECC_A 0x60240
-#define HSW_VIDEO_DIP_VS_ECC_A 0x60280
-#define HSW_VIDEO_DIP_SPD_ECC_A 0x602C0
-#define HSW_VIDEO_DIP_GMP_ECC_A 0x60300
-#define HSW_VIDEO_DIP_VSC_ECC_A 0x60344
-#define HSW_VIDEO_DIP_GCP_A 0x60210
-
-#define HSW_VIDEO_DIP_CTL_B 0x61200
-#define HSW_VIDEO_DIP_AVI_DATA_B 0x61220
-#define HSW_VIDEO_DIP_VS_DATA_B 0x61260
-#define HSW_VIDEO_DIP_SPD_DATA_B 0x612A0
-#define HSW_VIDEO_DIP_GMP_DATA_B 0x612E0
-#define HSW_VIDEO_DIP_VSC_DATA_B 0x61320
-#define HSW_VIDEO_DIP_BVI_ECC_B 0x61240
-#define HSW_VIDEO_DIP_VS_ECC_B 0x61280
-#define HSW_VIDEO_DIP_SPD_ECC_B 0x612C0
-#define HSW_VIDEO_DIP_GMP_ECC_B 0x61300
-#define HSW_VIDEO_DIP_VSC_ECC_B 0x61344
-#define HSW_VIDEO_DIP_GCP_B 0x61210
-
-#define HSW_TVIDEO_DIP_CTL(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_CTL_A)
-#define HSW_TVIDEO_DIP_AVI_DATA(trans, i) \
- (_TRANSCODER2(trans, HSW_VIDEO_DIP_AVI_DATA_A) + (i) * 4)
-#define HSW_TVIDEO_DIP_VS_DATA(trans, i) \
- (_TRANSCODER2(trans, HSW_VIDEO_DIP_VS_DATA_A) + (i) * 4)
-#define HSW_TVIDEO_DIP_SPD_DATA(trans, i) \
- (_TRANSCODER2(trans, HSW_VIDEO_DIP_SPD_DATA_A) + (i) * 4)
-#define HSW_TVIDEO_DIP_GCP(trans) \
- _TRANSCODER2(trans, HSW_VIDEO_DIP_GCP_A)
-#define HSW_TVIDEO_DIP_VSC_DATA(trans, i) \
- (_TRANSCODER2(trans, HSW_VIDEO_DIP_VSC_DATA_A) + (i) * 4)
-
-#define HSW_STEREO_3D_CTL_A 0x70020
-#define S3D_ENABLE (1<<31)
-#define HSW_STEREO_3D_CTL_B 0x71020
-
-#define HSW_STEREO_3D_CTL(trans) \
- _PIPE2(trans, HSW_STEREO_3D_CTL_A)
+
+#define _HSW_VIDEO_DIP_CTL_A 0x60200
+#define _HSW_VIDEO_DIP_AVI_DATA_A 0x60220
+#define _HSW_VIDEO_DIP_VS_DATA_A 0x60260
+#define _HSW_VIDEO_DIP_SPD_DATA_A 0x602A0
+#define _HSW_VIDEO_DIP_GMP_DATA_A 0x602E0
+#define _HSW_VIDEO_DIP_VSC_DATA_A 0x60320
+#define _HSW_VIDEO_DIP_AVI_ECC_A 0x60240
+#define _HSW_VIDEO_DIP_VS_ECC_A 0x60280
+#define _HSW_VIDEO_DIP_SPD_ECC_A 0x602C0
+#define _HSW_VIDEO_DIP_GMP_ECC_A 0x60300
+#define _HSW_VIDEO_DIP_VSC_ECC_A 0x60344
+#define _HSW_VIDEO_DIP_GCP_A 0x60210
+
+#define _HSW_VIDEO_DIP_CTL_B 0x61200
+#define _HSW_VIDEO_DIP_AVI_DATA_B 0x61220
+#define _HSW_VIDEO_DIP_VS_DATA_B 0x61260
+#define _HSW_VIDEO_DIP_SPD_DATA_B 0x612A0
+#define _HSW_VIDEO_DIP_GMP_DATA_B 0x612E0
+#define _HSW_VIDEO_DIP_VSC_DATA_B 0x61320
+#define _HSW_VIDEO_DIP_BVI_ECC_B 0x61240
+#define _HSW_VIDEO_DIP_VS_ECC_B 0x61280
+#define _HSW_VIDEO_DIP_SPD_ECC_B 0x612C0
+#define _HSW_VIDEO_DIP_GMP_ECC_B 0x61300
+#define _HSW_VIDEO_DIP_VSC_ECC_B 0x61344
+#define _HSW_VIDEO_DIP_GCP_B 0x61210
+
+#define HSW_TVIDEO_DIP_CTL(trans) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_CTL_A)
+#define HSW_TVIDEO_DIP_AVI_DATA(trans, i) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_AVI_DATA_A + (i) * 4)
+#define HSW_TVIDEO_DIP_VS_DATA(trans, i) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_VS_DATA_A + (i) * 4)
+#define HSW_TVIDEO_DIP_SPD_DATA(trans, i) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_SPD_DATA_A + (i) * 4)
+#define HSW_TVIDEO_DIP_GCP(trans) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_GCP_A)
+#define HSW_TVIDEO_DIP_VSC_DATA(trans, i) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_VSC_DATA_A + (i) * 4)
+
+#define _HSW_STEREO_3D_CTL_A 0x70020
+#define S3D_ENABLE (1<<31)
+#define _HSW_STEREO_3D_CTL_B 0x71020
+
+#define HSW_STEREO_3D_CTL(trans) _MMIO_PIPE2(trans, _HSW_STEREO_3D_CTL_A)
#define _PCH_TRANS_HTOTAL_B 0xe1000
#define _PCH_TRANS_HBLANK_B 0xe1004
@@ -6310,16 +6375,15 @@ enum skl_disp_power_wells {
#define _PCH_TRANS_VTOTAL_B 0xe100c
#define _PCH_TRANS_VBLANK_B 0xe1010
#define _PCH_TRANS_VSYNC_B 0xe1014
-#define _PCH_TRANS_VSYNCSHIFT_B 0xe1028
+#define _PCH_TRANS_VSYNCSHIFT_B 0xe1028
-#define PCH_TRANS_HTOTAL(pipe) _PIPE(pipe, _PCH_TRANS_HTOTAL_A, _PCH_TRANS_HTOTAL_B)
-#define PCH_TRANS_HBLANK(pipe) _PIPE(pipe, _PCH_TRANS_HBLANK_A, _PCH_TRANS_HBLANK_B)
-#define PCH_TRANS_HSYNC(pipe) _PIPE(pipe, _PCH_TRANS_HSYNC_A, _PCH_TRANS_HSYNC_B)
-#define PCH_TRANS_VTOTAL(pipe) _PIPE(pipe, _PCH_TRANS_VTOTAL_A, _PCH_TRANS_VTOTAL_B)
-#define PCH_TRANS_VBLANK(pipe) _PIPE(pipe, _PCH_TRANS_VBLANK_A, _PCH_TRANS_VBLANK_B)
-#define PCH_TRANS_VSYNC(pipe) _PIPE(pipe, _PCH_TRANS_VSYNC_A, _PCH_TRANS_VSYNC_B)
-#define PCH_TRANS_VSYNCSHIFT(pipe) _PIPE(pipe, _PCH_TRANS_VSYNCSHIFT_A, \
- _PCH_TRANS_VSYNCSHIFT_B)
+#define PCH_TRANS_HTOTAL(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_HTOTAL_A, _PCH_TRANS_HTOTAL_B)
+#define PCH_TRANS_HBLANK(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_HBLANK_A, _PCH_TRANS_HBLANK_B)
+#define PCH_TRANS_HSYNC(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_HSYNC_A, _PCH_TRANS_HSYNC_B)
+#define PCH_TRANS_VTOTAL(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VTOTAL_A, _PCH_TRANS_VTOTAL_B)
+#define PCH_TRANS_VBLANK(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VBLANK_A, _PCH_TRANS_VBLANK_B)
+#define PCH_TRANS_VSYNC(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VSYNC_A, _PCH_TRANS_VSYNC_B)
+#define PCH_TRANS_VSYNCSHIFT(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VSYNCSHIFT_A, _PCH_TRANS_VSYNCSHIFT_B)
#define _PCH_TRANSB_DATA_M1 0xe1030
#define _PCH_TRANSB_DATA_N1 0xe1034
@@ -6330,19 +6394,19 @@ enum skl_disp_power_wells {
#define _PCH_TRANSB_LINK_M2 0xe1048
#define _PCH_TRANSB_LINK_N2 0xe104c
-#define PCH_TRANS_DATA_M1(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_M1, _PCH_TRANSB_DATA_M1)
-#define PCH_TRANS_DATA_N1(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_N1, _PCH_TRANSB_DATA_N1)
-#define PCH_TRANS_DATA_M2(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_M2, _PCH_TRANSB_DATA_M2)
-#define PCH_TRANS_DATA_N2(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_N2, _PCH_TRANSB_DATA_N2)
-#define PCH_TRANS_LINK_M1(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_M1, _PCH_TRANSB_LINK_M1)
-#define PCH_TRANS_LINK_N1(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_N1, _PCH_TRANSB_LINK_N1)
-#define PCH_TRANS_LINK_M2(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_M2, _PCH_TRANSB_LINK_M2)
-#define PCH_TRANS_LINK_N2(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_N2, _PCH_TRANSB_LINK_N2)
+#define PCH_TRANS_DATA_M1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_M1, _PCH_TRANSB_DATA_M1)
+#define PCH_TRANS_DATA_N1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_N1, _PCH_TRANSB_DATA_N1)
+#define PCH_TRANS_DATA_M2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_M2, _PCH_TRANSB_DATA_M2)
+#define PCH_TRANS_DATA_N2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_N2, _PCH_TRANSB_DATA_N2)
+#define PCH_TRANS_LINK_M1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_M1, _PCH_TRANSB_LINK_M1)
+#define PCH_TRANS_LINK_N1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_N1, _PCH_TRANSB_LINK_N1)
+#define PCH_TRANS_LINK_M2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_M2, _PCH_TRANSB_LINK_M2)
+#define PCH_TRANS_LINK_N2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_N2, _PCH_TRANSB_LINK_N2)
#define _PCH_TRANSACONF 0xf0008
#define _PCH_TRANSBCONF 0xf1008
-#define PCH_TRANSCONF(pipe) _PIPE(pipe, _PCH_TRANSACONF, _PCH_TRANSBCONF)
-#define LPT_TRANSCONF _PCH_TRANSACONF /* lpt has only one transcoder */
+#define PCH_TRANSCONF(pipe) _MMIO_PIPE(pipe, _PCH_TRANSACONF, _PCH_TRANSBCONF)
+#define LPT_TRANSCONF PCH_TRANSCONF(PIPE_A) /* lpt has only one transcoder */
#define TRANS_DISABLE (0<<31)
#define TRANS_ENABLE (1<<31)
#define TRANS_STATE_MASK (1<<30)
@@ -6363,47 +6427,47 @@ enum skl_disp_power_wells {
#define _TRANSA_CHICKEN1 0xf0060
#define _TRANSB_CHICKEN1 0xf1060
-#define TRANS_CHICKEN1(pipe) _PIPE(pipe, _TRANSA_CHICKEN1, _TRANSB_CHICKEN1)
+#define TRANS_CHICKEN1(pipe) _MMIO_PIPE(pipe, _TRANSA_CHICKEN1, _TRANSB_CHICKEN1)
#define TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE (1<<10)
#define TRANS_CHICKEN1_DP0UNIT_GC_DISABLE (1<<4)
#define _TRANSA_CHICKEN2 0xf0064
#define _TRANSB_CHICKEN2 0xf1064
-#define TRANS_CHICKEN2(pipe) _PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
+#define TRANS_CHICKEN2(pipe) _MMIO_PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
#define TRANS_CHICKEN2_TIMING_OVERRIDE (1<<31)
#define TRANS_CHICKEN2_FDI_POLARITY_REVERSED (1<<29)
#define TRANS_CHICKEN2_FRAME_START_DELAY_MASK (3<<27)
#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER (1<<26)
#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH (1<<25)
-#define SOUTH_CHICKEN1 0xc2000
+#define SOUTH_CHICKEN1 _MMIO(0xc2000)
#define FDIA_PHASE_SYNC_SHIFT_OVR 19
#define FDIA_PHASE_SYNC_SHIFT_EN 18
#define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
#define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
#define FDI_BC_BIFURCATION_SELECT (1 << 12)
#define SPT_PWM_GRANULARITY (1<<0)
-#define SOUTH_CHICKEN2 0xc2004
+#define SOUTH_CHICKEN2 _MMIO(0xc2004)
#define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13)
#define FDI_MPHY_IOSFSB_RESET_CTL (1<<12)
#define LPT_PWM_GRANULARITY (1<<5)
#define DPLS_EDP_PPS_FIX_DIS (1<<0)
-#define _FDI_RXA_CHICKEN 0xc200c
-#define _FDI_RXB_CHICKEN 0xc2010
+#define _FDI_RXA_CHICKEN 0xc200c
+#define _FDI_RXB_CHICKEN 0xc2010
#define FDI_RX_PHASE_SYNC_POINTER_OVR (1<<1)
#define FDI_RX_PHASE_SYNC_POINTER_EN (1<<0)
-#define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN)
+#define FDI_RX_CHICKEN(pipe) _MMIO_PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN)
-#define SOUTH_DSPCLK_GATE_D 0xc2020
+#define SOUTH_DSPCLK_GATE_D _MMIO(0xc2020)
#define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1<<30)
#define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29)
#define PCH_CPUNIT_CLOCK_GATE_DISABLE (1<<14)
#define PCH_LP_PARTITION_LEVEL_DISABLE (1<<12)
/* CPU: FDI_TX */
-#define _FDI_TXA_CTL 0x60100
-#define _FDI_TXB_CTL 0x61100
-#define FDI_TX_CTL(pipe) _PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL)
+#define _FDI_TXA_CTL 0x60100
+#define _FDI_TXB_CTL 0x61100
+#define FDI_TX_CTL(pipe) _MMIO_PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL)
#define FDI_TX_DISABLE (0<<31)
#define FDI_TX_ENABLE (1<<31)
#define FDI_LINK_TRAIN_PATTERN_1 (0<<28)
@@ -6453,7 +6517,7 @@ enum skl_disp_power_wells {
/* FDI_RX, FDI_X is hard-wired to Transcoder_X */
#define _FDI_RXA_CTL 0xf000c
#define _FDI_RXB_CTL 0xf100c
-#define FDI_RX_CTL(pipe) _PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL)
+#define FDI_RX_CTL(pipe) _MMIO_PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL)
#define FDI_RX_ENABLE (1<<31)
/* train, dp width same as FDI_TX */
#define FDI_FS_ERRC_ENABLE (1<<27)
@@ -6489,14 +6553,14 @@ enum skl_disp_power_wells {
#define FDI_RX_TP1_TO_TP2_48 (2<<20)
#define FDI_RX_TP1_TO_TP2_64 (3<<20)
#define FDI_RX_FDI_DELAY_90 (0x90<<0)
-#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
+#define FDI_RX_MISC(pipe) _MMIO_PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
-#define _FDI_RXA_TUSIZE1 0xf0030
-#define _FDI_RXA_TUSIZE2 0xf0038
-#define _FDI_RXB_TUSIZE1 0xf1030
-#define _FDI_RXB_TUSIZE2 0xf1038
-#define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1)
-#define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2)
+#define _FDI_RXA_TUSIZE1 0xf0030
+#define _FDI_RXA_TUSIZE2 0xf0038
+#define _FDI_RXB_TUSIZE1 0xf1030
+#define _FDI_RXB_TUSIZE2 0xf1038
+#define FDI_RX_TUSIZE1(pipe) _MMIO_PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1)
+#define FDI_RX_TUSIZE2(pipe) _MMIO_PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2)
/* FDI_RX interrupt register format */
#define FDI_RX_INTER_LANE_ALIGN (1<<10)
@@ -6511,44 +6575,41 @@ enum skl_disp_power_wells {
#define FDI_RX_CROSS_CLOCK_OVERFLOW (1<<1)
#define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1<<0)
-#define _FDI_RXA_IIR 0xf0014
-#define _FDI_RXA_IMR 0xf0018
-#define _FDI_RXB_IIR 0xf1014
-#define _FDI_RXB_IMR 0xf1018
-#define FDI_RX_IIR(pipe) _PIPE(pipe, _FDI_RXA_IIR, _FDI_RXB_IIR)
-#define FDI_RX_IMR(pipe) _PIPE(pipe, _FDI_RXA_IMR, _FDI_RXB_IMR)
+#define _FDI_RXA_IIR 0xf0014
+#define _FDI_RXA_IMR 0xf0018
+#define _FDI_RXB_IIR 0xf1014
+#define _FDI_RXB_IMR 0xf1018
+#define FDI_RX_IIR(pipe) _MMIO_PIPE(pipe, _FDI_RXA_IIR, _FDI_RXB_IIR)
+#define FDI_RX_IMR(pipe) _MMIO_PIPE(pipe, _FDI_RXA_IMR, _FDI_RXB_IMR)
-#define FDI_PLL_CTL_1 0xfe000
-#define FDI_PLL_CTL_2 0xfe004
+#define FDI_PLL_CTL_1 _MMIO(0xfe000)
+#define FDI_PLL_CTL_2 _MMIO(0xfe004)
-#define PCH_LVDS 0xe1180
+#define PCH_LVDS _MMIO(0xe1180)
#define LVDS_DETECTED (1 << 1)
/* vlv has 2 sets of panel control regs. */
-#define PIPEA_PP_STATUS (VLV_DISPLAY_BASE + 0x61200)
-#define PIPEA_PP_CONTROL (VLV_DISPLAY_BASE + 0x61204)
-#define PIPEA_PP_ON_DELAYS (VLV_DISPLAY_BASE + 0x61208)
+#define _PIPEA_PP_STATUS (VLV_DISPLAY_BASE + 0x61200)
+#define _PIPEA_PP_CONTROL (VLV_DISPLAY_BASE + 0x61204)
+#define _PIPEA_PP_ON_DELAYS (VLV_DISPLAY_BASE + 0x61208)
#define PANEL_PORT_SELECT_VLV(port) ((port) << 30)
-#define PIPEA_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6120c)
-#define PIPEA_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61210)
-
-#define PIPEB_PP_STATUS (VLV_DISPLAY_BASE + 0x61300)
-#define PIPEB_PP_CONTROL (VLV_DISPLAY_BASE + 0x61304)
-#define PIPEB_PP_ON_DELAYS (VLV_DISPLAY_BASE + 0x61308)
-#define PIPEB_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6130c)
-#define PIPEB_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61310)
-
-#define VLV_PIPE_PP_STATUS(pipe) _PIPE(pipe, PIPEA_PP_STATUS, PIPEB_PP_STATUS)
-#define VLV_PIPE_PP_CONTROL(pipe) _PIPE(pipe, PIPEA_PP_CONTROL, PIPEB_PP_CONTROL)
-#define VLV_PIPE_PP_ON_DELAYS(pipe) \
- _PIPE(pipe, PIPEA_PP_ON_DELAYS, PIPEB_PP_ON_DELAYS)
-#define VLV_PIPE_PP_OFF_DELAYS(pipe) \
- _PIPE(pipe, PIPEA_PP_OFF_DELAYS, PIPEB_PP_OFF_DELAYS)
-#define VLV_PIPE_PP_DIVISOR(pipe) \
- _PIPE(pipe, PIPEA_PP_DIVISOR, PIPEB_PP_DIVISOR)
-
-#define PCH_PP_STATUS 0xc7200
-#define PCH_PP_CONTROL 0xc7204
+#define _PIPEA_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6120c)
+#define _PIPEA_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61210)
+
+#define _PIPEB_PP_STATUS (VLV_DISPLAY_BASE + 0x61300)
+#define _PIPEB_PP_CONTROL (VLV_DISPLAY_BASE + 0x61304)
+#define _PIPEB_PP_ON_DELAYS (VLV_DISPLAY_BASE + 0x61308)
+#define _PIPEB_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6130c)
+#define _PIPEB_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61310)
+
+#define VLV_PIPE_PP_STATUS(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_STATUS, _PIPEB_PP_STATUS)
+#define VLV_PIPE_PP_CONTROL(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_CONTROL, _PIPEB_PP_CONTROL)
+#define VLV_PIPE_PP_ON_DELAYS(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_ON_DELAYS, _PIPEB_PP_ON_DELAYS)
+#define VLV_PIPE_PP_OFF_DELAYS(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_OFF_DELAYS, _PIPEB_PP_OFF_DELAYS)
+#define VLV_PIPE_PP_DIVISOR(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_DIVISOR, _PIPEB_PP_DIVISOR)
+
+#define _PCH_PP_STATUS 0xc7200
+#define _PCH_PP_CONTROL 0xc7204
#define PANEL_UNLOCK_REGS (0xabcd << 16)
#define PANEL_UNLOCK_MASK (0xffff << 16)
#define BXT_POWER_CYCLE_DELAY_MASK (0x1f0)
@@ -6558,7 +6619,7 @@ enum skl_disp_power_wells {
#define PANEL_POWER_RESET (1 << 1)
#define PANEL_POWER_OFF (0 << 0)
#define PANEL_POWER_ON (1 << 0)
-#define PCH_PP_ON_DELAYS 0xc7208
+#define _PCH_PP_ON_DELAYS 0xc7208
#define PANEL_PORT_SELECT_MASK (3 << 30)
#define PANEL_PORT_SELECT_LVDS (0 << 30)
#define PANEL_PORT_SELECT_DPA (1 << 30)
@@ -6569,52 +6630,64 @@ enum skl_disp_power_wells {
#define PANEL_LIGHT_ON_DELAY_MASK (0x1fff)
#define PANEL_LIGHT_ON_DELAY_SHIFT 0
-#define PCH_PP_OFF_DELAYS 0xc720c
+#define _PCH_PP_OFF_DELAYS 0xc720c
#define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000)
#define PANEL_POWER_DOWN_DELAY_SHIFT 16
#define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff)
#define PANEL_LIGHT_OFF_DELAY_SHIFT 0
-#define PCH_PP_DIVISOR 0xc7210
+#define _PCH_PP_DIVISOR 0xc7210
#define PP_REFERENCE_DIVIDER_MASK (0xffffff00)
#define PP_REFERENCE_DIVIDER_SHIFT 8
#define PANEL_POWER_CYCLE_DELAY_MASK (0x1f)
#define PANEL_POWER_CYCLE_DELAY_SHIFT 0
+#define PCH_PP_STATUS _MMIO(_PCH_PP_STATUS)
+#define PCH_PP_CONTROL _MMIO(_PCH_PP_CONTROL)
+#define PCH_PP_ON_DELAYS _MMIO(_PCH_PP_ON_DELAYS)
+#define PCH_PP_OFF_DELAYS _MMIO(_PCH_PP_OFF_DELAYS)
+#define PCH_PP_DIVISOR _MMIO(_PCH_PP_DIVISOR)
+
/* BXT PPS changes - 2nd set of PPS registers */
#define _BXT_PP_STATUS2 0xc7300
#define _BXT_PP_CONTROL2 0xc7304
#define _BXT_PP_ON_DELAYS2 0xc7308
#define _BXT_PP_OFF_DELAYS2 0xc730c
-#define BXT_PP_STATUS(n) _PIPE(n, PCH_PP_STATUS, _BXT_PP_STATUS2)
-#define BXT_PP_CONTROL(n) _PIPE(n, PCH_PP_CONTROL, _BXT_PP_CONTROL2)
-#define BXT_PP_ON_DELAYS(n) _PIPE(n, PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
-#define BXT_PP_OFF_DELAYS(n) _PIPE(n, PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)
-
-#define PCH_DP_B 0xe4100
-#define PCH_DPB_AUX_CH_CTL 0xe4110
-#define PCH_DPB_AUX_CH_DATA1 0xe4114
-#define PCH_DPB_AUX_CH_DATA2 0xe4118
-#define PCH_DPB_AUX_CH_DATA3 0xe411c
-#define PCH_DPB_AUX_CH_DATA4 0xe4120
-#define PCH_DPB_AUX_CH_DATA5 0xe4124
-
-#define PCH_DP_C 0xe4200
-#define PCH_DPC_AUX_CH_CTL 0xe4210
-#define PCH_DPC_AUX_CH_DATA1 0xe4214
-#define PCH_DPC_AUX_CH_DATA2 0xe4218
-#define PCH_DPC_AUX_CH_DATA3 0xe421c
-#define PCH_DPC_AUX_CH_DATA4 0xe4220
-#define PCH_DPC_AUX_CH_DATA5 0xe4224
-
-#define PCH_DP_D 0xe4300
-#define PCH_DPD_AUX_CH_CTL 0xe4310
-#define PCH_DPD_AUX_CH_DATA1 0xe4314
-#define PCH_DPD_AUX_CH_DATA2 0xe4318
-#define PCH_DPD_AUX_CH_DATA3 0xe431c
-#define PCH_DPD_AUX_CH_DATA4 0xe4320
-#define PCH_DPD_AUX_CH_DATA5 0xe4324
+#define BXT_PP_STATUS(n) _MMIO_PIPE(n, _PCH_PP_STATUS, _BXT_PP_STATUS2)
+#define BXT_PP_CONTROL(n) _MMIO_PIPE(n, _PCH_PP_CONTROL, _BXT_PP_CONTROL2)
+#define BXT_PP_ON_DELAYS(n) _MMIO_PIPE(n, _PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
+#define BXT_PP_OFF_DELAYS(n) _MMIO_PIPE(n, _PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)
+
+#define _PCH_DP_B 0xe4100
+#define PCH_DP_B _MMIO(_PCH_DP_B)
+#define _PCH_DPB_AUX_CH_CTL 0xe4110
+#define _PCH_DPB_AUX_CH_DATA1 0xe4114
+#define _PCH_DPB_AUX_CH_DATA2 0xe4118
+#define _PCH_DPB_AUX_CH_DATA3 0xe411c
+#define _PCH_DPB_AUX_CH_DATA4 0xe4120
+#define _PCH_DPB_AUX_CH_DATA5 0xe4124
+
+#define _PCH_DP_C 0xe4200
+#define PCH_DP_C _MMIO(_PCH_DP_C)
+#define _PCH_DPC_AUX_CH_CTL 0xe4210
+#define _PCH_DPC_AUX_CH_DATA1 0xe4214
+#define _PCH_DPC_AUX_CH_DATA2 0xe4218
+#define _PCH_DPC_AUX_CH_DATA3 0xe421c
+#define _PCH_DPC_AUX_CH_DATA4 0xe4220
+#define _PCH_DPC_AUX_CH_DATA5 0xe4224
+
+#define _PCH_DP_D 0xe4300
+#define PCH_DP_D _MMIO(_PCH_DP_D)
+#define _PCH_DPD_AUX_CH_CTL 0xe4310
+#define _PCH_DPD_AUX_CH_DATA1 0xe4314
+#define _PCH_DPD_AUX_CH_DATA2 0xe4318
+#define _PCH_DPD_AUX_CH_DATA3 0xe431c
+#define _PCH_DPD_AUX_CH_DATA4 0xe4320
+#define _PCH_DPD_AUX_CH_DATA5 0xe4324
+
+#define PCH_DP_AUX_CH_CTL(port) _MMIO_PORT((port) - PORT_B, _PCH_DPB_AUX_CH_CTL, _PCH_DPC_AUX_CH_CTL)
+#define PCH_DP_AUX_CH_DATA(port, i) _MMIO(_PORT((port) - PORT_B, _PCH_DPB_AUX_CH_DATA1, _PCH_DPC_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
/* CPT */
#define PORT_TRANS_A_SEL_CPT 0
@@ -6627,10 +6700,10 @@ enum skl_disp_power_wells {
#define SDVO_PORT_TO_PIPE_CHV(val) (((val) & (3<<24)) >> 24)
#define DP_PORT_TO_PIPE_CHV(val) (((val) & (3<<16)) >> 16)
-#define TRANS_DP_CTL_A 0xe0300
-#define TRANS_DP_CTL_B 0xe1300
-#define TRANS_DP_CTL_C 0xe2300
-#define TRANS_DP_CTL(pipe) _PIPE(pipe, TRANS_DP_CTL_A, TRANS_DP_CTL_B)
+#define _TRANS_DP_CTL_A 0xe0300
+#define _TRANS_DP_CTL_B 0xe1300
+#define _TRANS_DP_CTL_C 0xe2300
+#define TRANS_DP_CTL(pipe) _MMIO_PIPE(pipe, _TRANS_DP_CTL_A, _TRANS_DP_CTL_B)
#define TRANS_DP_OUTPUT_ENABLE (1<<31)
#define TRANS_DP_PORT_SEL_B (0<<29)
#define TRANS_DP_PORT_SEL_C (1<<29)
@@ -6683,40 +6756,40 @@ enum skl_disp_power_wells {
#define EDP_LINK_TRAIN_VOL_EMP_MASK_IVB (0x3f<<22)
-#define VLV_PMWGICZ 0x1300a4
+#define VLV_PMWGICZ _MMIO(0x1300a4)
-#define FORCEWAKE 0xA18C
-#define FORCEWAKE_VLV 0x1300b0
-#define FORCEWAKE_ACK_VLV 0x1300b4
-#define FORCEWAKE_MEDIA_VLV 0x1300b8
-#define FORCEWAKE_ACK_MEDIA_VLV 0x1300bc
-#define FORCEWAKE_ACK_HSW 0x130044
-#define FORCEWAKE_ACK 0x130090
-#define VLV_GTLC_WAKE_CTRL 0x130090
+#define FORCEWAKE _MMIO(0xA18C)
+#define FORCEWAKE_VLV _MMIO(0x1300b0)
+#define FORCEWAKE_ACK_VLV _MMIO(0x1300b4)
+#define FORCEWAKE_MEDIA_VLV _MMIO(0x1300b8)
+#define FORCEWAKE_ACK_MEDIA_VLV _MMIO(0x1300bc)
+#define FORCEWAKE_ACK_HSW _MMIO(0x130044)
+#define FORCEWAKE_ACK _MMIO(0x130090)
+#define VLV_GTLC_WAKE_CTRL _MMIO(0x130090)
#define VLV_GTLC_RENDER_CTX_EXISTS (1 << 25)
#define VLV_GTLC_MEDIA_CTX_EXISTS (1 << 24)
#define VLV_GTLC_ALLOWWAKEREQ (1 << 0)
-#define VLV_GTLC_PW_STATUS 0x130094
+#define VLV_GTLC_PW_STATUS _MMIO(0x130094)
#define VLV_GTLC_ALLOWWAKEACK (1 << 0)
#define VLV_GTLC_ALLOWWAKEERR (1 << 1)
#define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5)
#define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7)
-#define FORCEWAKE_MT 0xa188 /* multi-threaded */
-#define FORCEWAKE_MEDIA_GEN9 0xa270
-#define FORCEWAKE_RENDER_GEN9 0xa278
-#define FORCEWAKE_BLITTER_GEN9 0xa188
-#define FORCEWAKE_ACK_MEDIA_GEN9 0x0D88
-#define FORCEWAKE_ACK_RENDER_GEN9 0x0D84
-#define FORCEWAKE_ACK_BLITTER_GEN9 0x130044
+#define FORCEWAKE_MT _MMIO(0xa188) /* multi-threaded */
+#define FORCEWAKE_MEDIA_GEN9 _MMIO(0xa270)
+#define FORCEWAKE_RENDER_GEN9 _MMIO(0xa278)
+#define FORCEWAKE_BLITTER_GEN9 _MMIO(0xa188)
+#define FORCEWAKE_ACK_MEDIA_GEN9 _MMIO(0x0D88)
+#define FORCEWAKE_ACK_RENDER_GEN9 _MMIO(0x0D84)
+#define FORCEWAKE_ACK_BLITTER_GEN9 _MMIO(0x130044)
#define FORCEWAKE_KERNEL 0x1
#define FORCEWAKE_USER 0x2
-#define FORCEWAKE_MT_ACK 0x130040
-#define ECOBUS 0xa180
+#define FORCEWAKE_MT_ACK _MMIO(0x130040)
+#define ECOBUS _MMIO(0xa180)
#define FORCEWAKE_MT_ENABLE (1<<5)
-#define VLV_SPAREG2H 0xA194
+#define VLV_SPAREG2H _MMIO(0xA194)
-#define GTFIFODBG 0x120000
+#define GTFIFODBG _MMIO(0x120000)
#define GT_FIFO_SBDROPERR (1<<6)
#define GT_FIFO_BLOBDROPERR (1<<5)
#define GT_FIFO_SB_READ_ABORTERR (1<<4)
@@ -6725,23 +6798,23 @@ enum skl_disp_power_wells {
#define GT_FIFO_IAWRERR (1<<1)
#define GT_FIFO_IARDERR (1<<0)
-#define GTFIFOCTL 0x120008
+#define GTFIFOCTL _MMIO(0x120008)
#define GT_FIFO_FREE_ENTRIES_MASK 0x7f
#define GT_FIFO_NUM_RESERVED_ENTRIES 20
#define GT_FIFO_CTL_BLOCK_ALL_POLICY_STALL (1 << 12)
#define GT_FIFO_CTL_RC6_POLICY_STALL (1 << 11)
-#define HSW_IDICR 0x9008
+#define HSW_IDICR _MMIO(0x9008)
#define IDIHASHMSK(x) (((x) & 0x3f) << 16)
-#define HSW_EDRAM_PRESENT 0x120010
+#define HSW_EDRAM_PRESENT _MMIO(0x120010)
#define EDRAM_ENABLED 0x1
-#define GEN6_UCGCTL1 0x9400
+#define GEN6_UCGCTL1 _MMIO(0x9400)
# define GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE (1 << 16)
# define GEN6_BLBUNIT_CLOCK_GATE_DISABLE (1 << 5)
# define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7)
-#define GEN6_UCGCTL2 0x9404
+#define GEN6_UCGCTL2 _MMIO(0x9404)
# define GEN6_VFUNIT_CLOCK_GATE_DISABLE (1 << 31)
# define GEN7_VDSUNIT_CLOCK_GATE_DISABLE (1 << 30)
# define GEN7_TDLUNIT_CLOCK_GATE_DISABLE (1 << 22)
@@ -6749,30 +6822,30 @@ enum skl_disp_power_wells {
# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12)
# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11)
-#define GEN6_UCGCTL3 0x9408
+#define GEN6_UCGCTL3 _MMIO(0x9408)
-#define GEN7_UCGCTL4 0x940c
+#define GEN7_UCGCTL4 _MMIO(0x940c)
#define GEN7_L3BANK2X_CLOCK_GATE_DISABLE (1<<25)
-#define GEN6_RCGCTL1 0x9410
-#define GEN6_RCGCTL2 0x9414
-#define GEN6_RSTCTL 0x9420
+#define GEN6_RCGCTL1 _MMIO(0x9410)
+#define GEN6_RCGCTL2 _MMIO(0x9414)
+#define GEN6_RSTCTL _MMIO(0x9420)
-#define GEN8_UCGCTL6 0x9430
+#define GEN8_UCGCTL6 _MMIO(0x9430)
#define GEN8_GAPSUNIT_CLOCK_GATE_DISABLE (1<<24)
#define GEN8_SDEUNIT_CLOCK_GATE_DISABLE (1<<14)
#define GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ (1<<28)
-#define GEN6_GFXPAUSE 0xA000
-#define GEN6_RPNSWREQ 0xA008
+#define GEN6_GFXPAUSE _MMIO(0xA000)
+#define GEN6_RPNSWREQ _MMIO(0xA008)
#define GEN6_TURBO_DISABLE (1<<31)
#define GEN6_FREQUENCY(x) ((x)<<25)
#define HSW_FREQUENCY(x) ((x)<<24)
#define GEN9_FREQUENCY(x) ((x)<<23)
#define GEN6_OFFSET(x) ((x)<<19)
#define GEN6_AGGRESSIVE_TURBO (0<<15)
-#define GEN6_RC_VIDEO_FREQ 0xA00C
-#define GEN6_RC_CONTROL 0xA090
+#define GEN6_RC_VIDEO_FREQ _MMIO(0xA00C)
+#define GEN6_RC_CONTROL _MMIO(0xA090)
#define GEN6_RC_CTL_RC6pp_ENABLE (1<<16)
#define GEN6_RC_CTL_RC6p_ENABLE (1<<17)
#define GEN6_RC_CTL_RC6_ENABLE (1<<18)
@@ -6782,16 +6855,16 @@ enum skl_disp_power_wells {
#define GEN7_RC_CTL_TO_MODE (1<<28)
#define GEN6_RC_CTL_EI_MODE(x) ((x)<<27)
#define GEN6_RC_CTL_HW_ENABLE (1<<31)
-#define GEN6_RP_DOWN_TIMEOUT 0xA010
-#define GEN6_RP_INTERRUPT_LIMITS 0xA014
-#define GEN6_RPSTAT1 0xA01C
+#define GEN6_RP_DOWN_TIMEOUT _MMIO(0xA010)
+#define GEN6_RP_INTERRUPT_LIMITS _MMIO(0xA014)
+#define GEN6_RPSTAT1 _MMIO(0xA01C)
#define GEN6_CAGF_SHIFT 8
#define HSW_CAGF_SHIFT 7
#define GEN9_CAGF_SHIFT 23
#define GEN6_CAGF_MASK (0x7f << GEN6_CAGF_SHIFT)
#define HSW_CAGF_MASK (0x7f << HSW_CAGF_SHIFT)
#define GEN9_CAGF_MASK (0x1ff << GEN9_CAGF_SHIFT)
-#define GEN6_RP_CONTROL 0xA024
+#define GEN6_RP_CONTROL _MMIO(0xA024)
#define GEN6_RP_MEDIA_TURBO (1<<11)
#define GEN6_RP_MEDIA_MODE_MASK (3<<9)
#define GEN6_RP_MEDIA_HW_TURBO_MODE (3<<9)
@@ -6805,53 +6878,53 @@ enum skl_disp_power_wells {
#define GEN6_RP_UP_BUSY_CONT (0x4<<3)
#define GEN6_RP_DOWN_IDLE_AVG (0x2<<0)
#define GEN6_RP_DOWN_IDLE_CONT (0x1<<0)
-#define GEN6_RP_UP_THRESHOLD 0xA02C
-#define GEN6_RP_DOWN_THRESHOLD 0xA030
-#define GEN6_RP_CUR_UP_EI 0xA050
+#define GEN6_RP_UP_THRESHOLD _MMIO(0xA02C)
+#define GEN6_RP_DOWN_THRESHOLD _MMIO(0xA030)
+#define GEN6_RP_CUR_UP_EI _MMIO(0xA050)
#define GEN6_CURICONT_MASK 0xffffff
-#define GEN6_RP_CUR_UP 0xA054
+#define GEN6_RP_CUR_UP _MMIO(0xA054)
#define GEN6_CURBSYTAVG_MASK 0xffffff
-#define GEN6_RP_PREV_UP 0xA058
-#define GEN6_RP_CUR_DOWN_EI 0xA05C
+#define GEN6_RP_PREV_UP _MMIO(0xA058)
+#define GEN6_RP_CUR_DOWN_EI _MMIO(0xA05C)
#define GEN6_CURIAVG_MASK 0xffffff
-#define GEN6_RP_CUR_DOWN 0xA060
-#define GEN6_RP_PREV_DOWN 0xA064
-#define GEN6_RP_UP_EI 0xA068
-#define GEN6_RP_DOWN_EI 0xA06C
-#define GEN6_RP_IDLE_HYSTERSIS 0xA070
-#define GEN6_RPDEUHWTC 0xA080
-#define GEN6_RPDEUC 0xA084
-#define GEN6_RPDEUCSW 0xA088
-#define GEN6_RC_STATE 0xA094
-#define GEN6_RC1_WAKE_RATE_LIMIT 0xA098
-#define GEN6_RC6_WAKE_RATE_LIMIT 0xA09C
-#define GEN6_RC6pp_WAKE_RATE_LIMIT 0xA0A0
-#define GEN6_RC_EVALUATION_INTERVAL 0xA0A8
-#define GEN6_RC_IDLE_HYSTERSIS 0xA0AC
-#define GEN6_RC_SLEEP 0xA0B0
-#define GEN6_RCUBMABDTMR 0xA0B0
-#define GEN6_RC1e_THRESHOLD 0xA0B4
-#define GEN6_RC6_THRESHOLD 0xA0B8
-#define GEN6_RC6p_THRESHOLD 0xA0BC
-#define VLV_RCEDATA 0xA0BC
-#define GEN6_RC6pp_THRESHOLD 0xA0C0
-#define GEN6_PMINTRMSK 0xA168
+#define GEN6_RP_CUR_DOWN _MMIO(0xA060)
+#define GEN6_RP_PREV_DOWN _MMIO(0xA064)
+#define GEN6_RP_UP_EI _MMIO(0xA068)
+#define GEN6_RP_DOWN_EI _MMIO(0xA06C)
+#define GEN6_RP_IDLE_HYSTERSIS _MMIO(0xA070)
+#define GEN6_RPDEUHWTC _MMIO(0xA080)
+#define GEN6_RPDEUC _MMIO(0xA084)
+#define GEN6_RPDEUCSW _MMIO(0xA088)
+#define GEN6_RC_STATE _MMIO(0xA094)
+#define GEN6_RC1_WAKE_RATE_LIMIT _MMIO(0xA098)
+#define GEN6_RC6_WAKE_RATE_LIMIT _MMIO(0xA09C)
+#define GEN6_RC6pp_WAKE_RATE_LIMIT _MMIO(0xA0A0)
+#define GEN6_RC_EVALUATION_INTERVAL _MMIO(0xA0A8)
+#define GEN6_RC_IDLE_HYSTERSIS _MMIO(0xA0AC)
+#define GEN6_RC_SLEEP _MMIO(0xA0B0)
+#define GEN6_RCUBMABDTMR _MMIO(0xA0B0)
+#define GEN6_RC1e_THRESHOLD _MMIO(0xA0B4)
+#define GEN6_RC6_THRESHOLD _MMIO(0xA0B8)
+#define GEN6_RC6p_THRESHOLD _MMIO(0xA0BC)
+#define VLV_RCEDATA _MMIO(0xA0BC)
+#define GEN6_RC6pp_THRESHOLD _MMIO(0xA0C0)
+#define GEN6_PMINTRMSK _MMIO(0xA168)
#define GEN8_PMINTR_REDIRECT_TO_NON_DISP (1<<31)
-#define VLV_PWRDWNUPCTL 0xA294
-#define GEN9_MEDIA_PG_IDLE_HYSTERESIS 0xA0C4
-#define GEN9_RENDER_PG_IDLE_HYSTERESIS 0xA0C8
-#define GEN9_PG_ENABLE 0xA210
+#define VLV_PWRDWNUPCTL _MMIO(0xA294)
+#define GEN9_MEDIA_PG_IDLE_HYSTERESIS _MMIO(0xA0C4)
+#define GEN9_RENDER_PG_IDLE_HYSTERESIS _MMIO(0xA0C8)
+#define GEN9_PG_ENABLE _MMIO(0xA210)
#define GEN9_RENDER_PG_ENABLE (1<<0)
#define GEN9_MEDIA_PG_ENABLE (1<<1)
-#define VLV_CHICKEN_3 (VLV_DISPLAY_BASE + 0x7040C)
+#define VLV_CHICKEN_3 _MMIO(VLV_DISPLAY_BASE + 0x7040C)
#define PIXEL_OVERLAP_CNT_MASK (3 << 30)
#define PIXEL_OVERLAP_CNT_SHIFT 30
-#define GEN6_PMISR 0x44020
-#define GEN6_PMIMR 0x44024 /* rps_lock */
-#define GEN6_PMIIR 0x44028
-#define GEN6_PMIER 0x4402C
+#define GEN6_PMISR _MMIO(0x44020)
+#define GEN6_PMIMR _MMIO(0x44024) /* rps_lock */
+#define GEN6_PMIIR _MMIO(0x44028)
+#define GEN6_PMIER _MMIO(0x4402C)
#define GEN6_PM_MBOX_EVENT (1<<25)
#define GEN6_PM_THERMAL_EVENT (1<<24)
#define GEN6_PM_RP_DOWN_TIMEOUT (1<<6)
@@ -6863,30 +6936,30 @@ enum skl_disp_power_wells {
GEN6_PM_RP_DOWN_THRESHOLD | \
GEN6_PM_RP_DOWN_TIMEOUT)
-#define GEN7_GT_SCRATCH(i) (0x4F100 + (i) * 4)
+#define GEN7_GT_SCRATCH(i) _MMIO(0x4F100 + (i) * 4)
#define GEN7_GT_SCRATCH_REG_NUM 8
-#define VLV_GTLC_SURVIVABILITY_REG 0x130098
+#define VLV_GTLC_SURVIVABILITY_REG _MMIO(0x130098)
#define VLV_GFX_CLK_STATUS_BIT (1<<3)
#define VLV_GFX_CLK_FORCE_ON_BIT (1<<2)
-#define GEN6_GT_GFX_RC6_LOCKED 0x138104
-#define VLV_COUNTER_CONTROL 0x138104
+#define GEN6_GT_GFX_RC6_LOCKED _MMIO(0x138104)
+#define VLV_COUNTER_CONTROL _MMIO(0x138104)
#define VLV_COUNT_RANGE_HIGH (1<<15)
#define VLV_MEDIA_RC0_COUNT_EN (1<<5)
#define VLV_RENDER_RC0_COUNT_EN (1<<4)
#define VLV_MEDIA_RC6_COUNT_EN (1<<1)
#define VLV_RENDER_RC6_COUNT_EN (1<<0)
-#define GEN6_GT_GFX_RC6 0x138108
-#define VLV_GT_RENDER_RC6 0x138108
-#define VLV_GT_MEDIA_RC6 0x13810C
+#define GEN6_GT_GFX_RC6 _MMIO(0x138108)
+#define VLV_GT_RENDER_RC6 _MMIO(0x138108)
+#define VLV_GT_MEDIA_RC6 _MMIO(0x13810C)
-#define GEN6_GT_GFX_RC6p 0x13810C
-#define GEN6_GT_GFX_RC6pp 0x138110
-#define VLV_RENDER_C0_COUNT 0x138118
-#define VLV_MEDIA_C0_COUNT 0x13811C
+#define GEN6_GT_GFX_RC6p _MMIO(0x13810C)
+#define GEN6_GT_GFX_RC6pp _MMIO(0x138110)
+#define VLV_RENDER_C0_COUNT _MMIO(0x138118)
+#define VLV_MEDIA_C0_COUNT _MMIO(0x13811C)
-#define GEN6_PCODE_MAILBOX 0x138124
+#define GEN6_PCODE_MAILBOX _MMIO(0x138124)
#define GEN6_PCODE_READY (1<<31)
#define GEN6_PCODE_WRITE_RC6VIDS 0x4
#define GEN6_PCODE_READ_RC6VIDS 0x5
@@ -6909,12 +6982,12 @@ enum skl_disp_power_wells {
#define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17
#define DISPLAY_IPS_CONTROL 0x19
#define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A
-#define GEN6_PCODE_DATA 0x138128
+#define GEN6_PCODE_DATA _MMIO(0x138128)
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
#define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16
-#define GEN6_PCODE_DATA1 0x13812C
+#define GEN6_PCODE_DATA1 _MMIO(0x13812C)
-#define GEN6_GT_CORE_STATUS 0x138060
+#define GEN6_GT_CORE_STATUS _MMIO(0x138060)
#define GEN6_CORE_CPD_STATE_MASK (7<<4)
#define GEN6_RCn_MASK 7
#define GEN6_RC0 0
@@ -6922,26 +6995,26 @@ enum skl_disp_power_wells {
#define GEN6_RC6 3
#define GEN6_RC7 4
-#define GEN8_GT_SLICE_INFO 0x138064
+#define GEN8_GT_SLICE_INFO _MMIO(0x138064)
#define GEN8_LSLICESTAT_MASK 0x7
-#define CHV_POWER_SS0_SIG1 0xa720
-#define CHV_POWER_SS1_SIG1 0xa728
+#define CHV_POWER_SS0_SIG1 _MMIO(0xa720)
+#define CHV_POWER_SS1_SIG1 _MMIO(0xa728)
#define CHV_SS_PG_ENABLE (1<<1)
#define CHV_EU08_PG_ENABLE (1<<9)
#define CHV_EU19_PG_ENABLE (1<<17)
#define CHV_EU210_PG_ENABLE (1<<25)
-#define CHV_POWER_SS0_SIG2 0xa724
-#define CHV_POWER_SS1_SIG2 0xa72c
+#define CHV_POWER_SS0_SIG2 _MMIO(0xa724)
+#define CHV_POWER_SS1_SIG2 _MMIO(0xa72c)
#define CHV_EU311_PG_ENABLE (1<<1)
-#define GEN9_SLICE_PGCTL_ACK(slice) (0x804c + (slice)*0x4)
+#define GEN9_SLICE_PGCTL_ACK(slice) _MMIO(0x804c + (slice)*0x4)
#define GEN9_PGCTL_SLICE_ACK (1 << 0)
#define GEN9_PGCTL_SS_ACK(subslice) (1 << (2 + (subslice)*2))
-#define GEN9_SS01_EU_PGCTL_ACK(slice) (0x805c + (slice)*0x8)
-#define GEN9_SS23_EU_PGCTL_ACK(slice) (0x8060 + (slice)*0x8)
+#define GEN9_SS01_EU_PGCTL_ACK(slice) _MMIO(0x805c + (slice)*0x8)
+#define GEN9_SS23_EU_PGCTL_ACK(slice) _MMIO(0x8060 + (slice)*0x8)
#define GEN9_PGCTL_SSA_EU08_ACK (1 << 0)
#define GEN9_PGCTL_SSA_EU19_ACK (1 << 2)
#define GEN9_PGCTL_SSA_EU210_ACK (1 << 4)
@@ -6951,18 +7024,17 @@ enum skl_disp_power_wells {
#define GEN9_PGCTL_SSB_EU210_ACK (1 << 12)
#define GEN9_PGCTL_SSB_EU311_ACK (1 << 14)
-#define GEN7_MISCCPCTL (0x9424)
+#define GEN7_MISCCPCTL _MMIO(0x9424)
#define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0)
#define GEN8_DOP_CLOCK_GATE_CFCLK_ENABLE (1<<2)
#define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1<<4)
#define GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE (1<<6)
-#define GEN8_GARBCNTL 0xB004
+#define GEN8_GARBCNTL _MMIO(0xB004)
#define GEN9_GAPS_TSV_CREDIT_DISABLE (1<<7)
/* IVYBRIDGE DPF */
-#define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */
-#define HSW_L3CDERRST11 0xB208 /* L3CD Error Status register 1 slice 1 */
+#define GEN7_L3CDERRST1(slice) _MMIO(0xB008 + (slice) * 0x200) /* L3CD Error Status 1 */
#define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14)
#define GEN7_PARITY_ERROR_VALID (1<<13)
#define GEN7_L3CDERRST1_BANK_MASK (3<<11)
@@ -6975,119 +7047,102 @@ enum skl_disp_power_wells {
((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8)
#define GEN7_L3CDERRST1_ENABLE (1<<7)
-#define GEN7_L3LOG_BASE 0xB070
-#define HSW_L3LOG_BASE_SLICE1 0xB270
+#define GEN7_L3LOG(slice, i) _MMIO(0xB070 + (slice) * 0x200 + (i) * 4)
#define GEN7_L3LOG_SIZE 0x80
-#define GEN7_HALF_SLICE_CHICKEN1 0xe100 /* IVB GT1 + VLV */
-#define GEN7_HALF_SLICE_CHICKEN1_GT2 0xf100
+#define GEN7_HALF_SLICE_CHICKEN1 _MMIO(0xe100) /* IVB GT1 + VLV */
+#define GEN7_HALF_SLICE_CHICKEN1_GT2 _MMIO(0xf100)
#define GEN7_MAX_PS_THREAD_DEP (8<<12)
#define GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE (1<<10)
#define GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE (1<<4)
#define GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE (1<<3)
-#define GEN9_HALF_SLICE_CHICKEN5 0xe188
+#define GEN9_HALF_SLICE_CHICKEN5 _MMIO(0xe188)
#define GEN9_DG_MIRROR_FIX_ENABLE (1<<5)
#define GEN9_CCS_TLB_PREFETCH_ENABLE (1<<3)
-#define GEN8_ROW_CHICKEN 0xe4f0
+#define GEN8_ROW_CHICKEN _MMIO(0xe4f0)
#define PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE (1<<8)
#define STALL_DOP_GATING_DISABLE (1<<5)
-#define GEN7_ROW_CHICKEN2 0xe4f4
-#define GEN7_ROW_CHICKEN2_GT2 0xf4f4
+#define GEN7_ROW_CHICKEN2 _MMIO(0xe4f4)
+#define GEN7_ROW_CHICKEN2_GT2 _MMIO(0xf4f4)
#define DOP_CLOCK_GATING_DISABLE (1<<0)
-#define HSW_ROW_CHICKEN3 0xe49c
+#define HSW_ROW_CHICKEN3 _MMIO(0xe49c)
#define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6)
-#define HALF_SLICE_CHICKEN2 0xe180
+#define HALF_SLICE_CHICKEN2 _MMIO(0xe180)
#define GEN8_ST_PO_DISABLE (1<<13)
-#define HALF_SLICE_CHICKEN3 0xe184
+#define HALF_SLICE_CHICKEN3 _MMIO(0xe184)
#define HSW_SAMPLE_C_PERFORMANCE (1<<9)
#define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8)
#define GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC (1<<5)
#define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1)
-#define GEN9_HALF_SLICE_CHICKEN7 0xe194
+#define GEN9_HALF_SLICE_CHICKEN7 _MMIO(0xe194)
#define GEN9_ENABLE_YV12_BUGFIX (1<<4)
/* Audio */
-#define G4X_AUD_VID_DID (dev_priv->info.display_mmio_offset + 0x62020)
+#define G4X_AUD_VID_DID _MMIO(dev_priv->info.display_mmio_offset + 0x62020)
#define INTEL_AUDIO_DEVCL 0x808629FB
#define INTEL_AUDIO_DEVBLC 0x80862801
#define INTEL_AUDIO_DEVCTG 0x80862802
-#define G4X_AUD_CNTL_ST 0x620B4
+#define G4X_AUD_CNTL_ST _MMIO(0x620B4)
#define G4X_ELDV_DEVCL_DEVBLC (1 << 13)
#define G4X_ELDV_DEVCTG (1 << 14)
#define G4X_ELD_ADDR_MASK (0xf << 5)
#define G4X_ELD_ACK (1 << 4)
-#define G4X_HDMIW_HDMIEDID 0x6210C
+#define G4X_HDMIW_HDMIEDID _MMIO(0x6210C)
#define _IBX_HDMIW_HDMIEDID_A 0xE2050
#define _IBX_HDMIW_HDMIEDID_B 0xE2150
-#define IBX_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
- _IBX_HDMIW_HDMIEDID_A, \
- _IBX_HDMIW_HDMIEDID_B)
+#define IBX_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _IBX_HDMIW_HDMIEDID_A, \
+ _IBX_HDMIW_HDMIEDID_B)
#define _IBX_AUD_CNTL_ST_A 0xE20B4
#define _IBX_AUD_CNTL_ST_B 0xE21B4
-#define IBX_AUD_CNTL_ST(pipe) _PIPE(pipe, \
- _IBX_AUD_CNTL_ST_A, \
- _IBX_AUD_CNTL_ST_B)
+#define IBX_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CNTL_ST_A, \
+ _IBX_AUD_CNTL_ST_B)
#define IBX_ELD_BUFFER_SIZE_MASK (0x1f << 10)
#define IBX_ELD_ADDRESS_MASK (0x1f << 5)
#define IBX_ELD_ACK (1 << 4)
-#define IBX_AUD_CNTL_ST2 0xE20C0
+#define IBX_AUD_CNTL_ST2 _MMIO(0xE20C0)
#define IBX_CP_READY(port) ((1 << 1) << (((port) - 1) * 4))
#define IBX_ELD_VALID(port) ((1 << 0) << (((port) - 1) * 4))
#define _CPT_HDMIW_HDMIEDID_A 0xE5050
#define _CPT_HDMIW_HDMIEDID_B 0xE5150
-#define CPT_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
- _CPT_HDMIW_HDMIEDID_A, \
- _CPT_HDMIW_HDMIEDID_B)
+#define CPT_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _CPT_HDMIW_HDMIEDID_A, _CPT_HDMIW_HDMIEDID_B)
#define _CPT_AUD_CNTL_ST_A 0xE50B4
#define _CPT_AUD_CNTL_ST_B 0xE51B4
-#define CPT_AUD_CNTL_ST(pipe) _PIPE(pipe, \
- _CPT_AUD_CNTL_ST_A, \
- _CPT_AUD_CNTL_ST_B)
-#define CPT_AUD_CNTRL_ST2 0xE50C0
+#define CPT_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _CPT_AUD_CNTL_ST_A, _CPT_AUD_CNTL_ST_B)
+#define CPT_AUD_CNTRL_ST2 _MMIO(0xE50C0)
#define _VLV_HDMIW_HDMIEDID_A (VLV_DISPLAY_BASE + 0x62050)
#define _VLV_HDMIW_HDMIEDID_B (VLV_DISPLAY_BASE + 0x62150)
-#define VLV_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
- _VLV_HDMIW_HDMIEDID_A, \
- _VLV_HDMIW_HDMIEDID_B)
+#define VLV_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _VLV_HDMIW_HDMIEDID_A, _VLV_HDMIW_HDMIEDID_B)
#define _VLV_AUD_CNTL_ST_A (VLV_DISPLAY_BASE + 0x620B4)
#define _VLV_AUD_CNTL_ST_B (VLV_DISPLAY_BASE + 0x621B4)
-#define VLV_AUD_CNTL_ST(pipe) _PIPE(pipe, \
- _VLV_AUD_CNTL_ST_A, \
- _VLV_AUD_CNTL_ST_B)
-#define VLV_AUD_CNTL_ST2 (VLV_DISPLAY_BASE + 0x620C0)
+#define VLV_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _VLV_AUD_CNTL_ST_A, _VLV_AUD_CNTL_ST_B)
+#define VLV_AUD_CNTL_ST2 _MMIO(VLV_DISPLAY_BASE + 0x620C0)
/* These are the 4 32-bit write offset registers for each stream
* output buffer. It determines the offset from the
* 3DSTATE_SO_BUFFERs that the next streamed vertex output goes to.
*/
-#define GEN7_SO_WRITE_OFFSET(n) (0x5280 + (n) * 4)
+#define GEN7_SO_WRITE_OFFSET(n) _MMIO(0x5280 + (n) * 4)
#define _IBX_AUD_CONFIG_A 0xe2000
#define _IBX_AUD_CONFIG_B 0xe2100
-#define IBX_AUD_CFG(pipe) _PIPE(pipe, \
- _IBX_AUD_CONFIG_A, \
- _IBX_AUD_CONFIG_B)
+#define IBX_AUD_CFG(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CONFIG_A, _IBX_AUD_CONFIG_B)
#define _CPT_AUD_CONFIG_A 0xe5000
#define _CPT_AUD_CONFIG_B 0xe5100
-#define CPT_AUD_CFG(pipe) _PIPE(pipe, \
- _CPT_AUD_CONFIG_A, \
- _CPT_AUD_CONFIG_B)
+#define CPT_AUD_CFG(pipe) _MMIO_PIPE(pipe, _CPT_AUD_CONFIG_A, _CPT_AUD_CONFIG_B)
#define _VLV_AUD_CONFIG_A (VLV_DISPLAY_BASE + 0x62000)
#define _VLV_AUD_CONFIG_B (VLV_DISPLAY_BASE + 0x62100)
-#define VLV_AUD_CFG(pipe) _PIPE(pipe, \
- _VLV_AUD_CONFIG_A, \
- _VLV_AUD_CONFIG_B)
+#define VLV_AUD_CFG(pipe) _MMIO_PIPE(pipe, _VLV_AUD_CONFIG_A, _VLV_AUD_CONFIG_B)
#define AUD_CONFIG_N_VALUE_INDEX (1 << 29)
#define AUD_CONFIG_N_PROG_ENABLE (1 << 28)
@@ -7112,72 +7167,62 @@ enum skl_disp_power_wells {
/* HSW Audio */
#define _HSW_AUD_CONFIG_A 0x65000
#define _HSW_AUD_CONFIG_B 0x65100
-#define HSW_AUD_CFG(pipe) _PIPE(pipe, \
- _HSW_AUD_CONFIG_A, \
- _HSW_AUD_CONFIG_B)
+#define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe, _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
#define _HSW_AUD_MISC_CTRL_A 0x65010
#define _HSW_AUD_MISC_CTRL_B 0x65110
-#define HSW_AUD_MISC_CTRL(pipe) _PIPE(pipe, \
- _HSW_AUD_MISC_CTRL_A, \
- _HSW_AUD_MISC_CTRL_B)
+#define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
#define _HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4
#define _HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4
-#define HSW_AUD_DIP_ELD_CTRL(pipe) _PIPE(pipe, \
- _HSW_AUD_DIP_ELD_CTRL_ST_A, \
- _HSW_AUD_DIP_ELD_CTRL_ST_B)
+#define HSW_AUD_DIP_ELD_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_DIP_ELD_CTRL_ST_A, _HSW_AUD_DIP_ELD_CTRL_ST_B)
/* Audio Digital Converter */
#define _HSW_AUD_DIG_CNVT_1 0x65080
#define _HSW_AUD_DIG_CNVT_2 0x65180
-#define AUD_DIG_CNVT(pipe) _PIPE(pipe, \
- _HSW_AUD_DIG_CNVT_1, \
- _HSW_AUD_DIG_CNVT_2)
+#define AUD_DIG_CNVT(pipe) _MMIO_PIPE(pipe, _HSW_AUD_DIG_CNVT_1, _HSW_AUD_DIG_CNVT_2)
#define DIP_PORT_SEL_MASK 0x3
#define _HSW_AUD_EDID_DATA_A 0x65050
#define _HSW_AUD_EDID_DATA_B 0x65150
-#define HSW_AUD_EDID_DATA(pipe) _PIPE(pipe, \
- _HSW_AUD_EDID_DATA_A, \
- _HSW_AUD_EDID_DATA_B)
+#define HSW_AUD_EDID_DATA(pipe) _MMIO_PIPE(pipe, _HSW_AUD_EDID_DATA_A, _HSW_AUD_EDID_DATA_B)
-#define HSW_AUD_PIPE_CONV_CFG 0x6507c
-#define HSW_AUD_PIN_ELD_CP_VLD 0x650c0
+#define HSW_AUD_PIPE_CONV_CFG _MMIO(0x6507c)
+#define HSW_AUD_PIN_ELD_CP_VLD _MMIO(0x650c0)
#define AUDIO_INACTIVE(trans) ((1 << 3) << ((trans) * 4))
#define AUDIO_OUTPUT_ENABLE(trans) ((1 << 2) << ((trans) * 4))
#define AUDIO_CP_READY(trans) ((1 << 1) << ((trans) * 4))
#define AUDIO_ELD_VALID(trans) ((1 << 0) << ((trans) * 4))
-#define HSW_AUD_CHICKENBIT 0x65f10
+#define HSW_AUD_CHICKENBIT _MMIO(0x65f10)
#define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15)
/* HSW Power Wells */
-#define HSW_PWR_WELL_BIOS 0x45400 /* CTL1 */
-#define HSW_PWR_WELL_DRIVER 0x45404 /* CTL2 */
-#define HSW_PWR_WELL_KVMR 0x45408 /* CTL3 */
-#define HSW_PWR_WELL_DEBUG 0x4540C /* CTL4 */
+#define HSW_PWR_WELL_BIOS _MMIO(0x45400) /* CTL1 */
+#define HSW_PWR_WELL_DRIVER _MMIO(0x45404) /* CTL2 */
+#define HSW_PWR_WELL_KVMR _MMIO(0x45408) /* CTL3 */
+#define HSW_PWR_WELL_DEBUG _MMIO(0x4540C) /* CTL4 */
#define HSW_PWR_WELL_ENABLE_REQUEST (1<<31)
#define HSW_PWR_WELL_STATE_ENABLED (1<<30)
-#define HSW_PWR_WELL_CTL5 0x45410
+#define HSW_PWR_WELL_CTL5 _MMIO(0x45410)
#define HSW_PWR_WELL_ENABLE_SINGLE_STEP (1<<31)
#define HSW_PWR_WELL_PWR_GATE_OVERRIDE (1<<20)
#define HSW_PWR_WELL_FORCE_ON (1<<19)
-#define HSW_PWR_WELL_CTL6 0x45414
+#define HSW_PWR_WELL_CTL6 _MMIO(0x45414)
/* SKL Fuse Status */
-#define SKL_FUSE_STATUS 0x42000
+#define SKL_FUSE_STATUS _MMIO(0x42000)
#define SKL_FUSE_DOWNLOAD_STATUS (1<<31)
#define SKL_FUSE_PG0_DIST_STATUS (1<<27)
#define SKL_FUSE_PG1_DIST_STATUS (1<<26)
#define SKL_FUSE_PG2_DIST_STATUS (1<<25)
/* Per-pipe DDI Function Control */
-#define TRANS_DDI_FUNC_CTL_A 0x60400
-#define TRANS_DDI_FUNC_CTL_B 0x61400
-#define TRANS_DDI_FUNC_CTL_C 0x62400
-#define TRANS_DDI_FUNC_CTL_EDP 0x6F400
-#define TRANS_DDI_FUNC_CTL(tran) _TRANSCODER2(tran, TRANS_DDI_FUNC_CTL_A)
+#define _TRANS_DDI_FUNC_CTL_A 0x60400
+#define _TRANS_DDI_FUNC_CTL_B 0x61400
+#define _TRANS_DDI_FUNC_CTL_C 0x62400
+#define _TRANS_DDI_FUNC_CTL_EDP 0x6F400
+#define TRANS_DDI_FUNC_CTL(tran) _MMIO_TRANS2(tran, _TRANS_DDI_FUNC_CTL_A)
#define TRANS_DDI_FUNC_ENABLE (1<<31)
/* Those bits are ignored by pipe EDP since it can only connect to DDI A */
@@ -7207,9 +7252,9 @@ enum skl_disp_power_wells {
#define TRANS_DDI_BFI_ENABLE (1<<4)
/* DisplayPort Transport Control */
-#define DP_TP_CTL_A 0x64040
-#define DP_TP_CTL_B 0x64140
-#define DP_TP_CTL(port) _PORT(port, DP_TP_CTL_A, DP_TP_CTL_B)
+#define _DP_TP_CTL_A 0x64040
+#define _DP_TP_CTL_B 0x64140
+#define DP_TP_CTL(port) _MMIO_PORT(port, _DP_TP_CTL_A, _DP_TP_CTL_B)
#define DP_TP_CTL_ENABLE (1<<31)
#define DP_TP_CTL_MODE_SST (0<<27)
#define DP_TP_CTL_MODE_MST (1<<27)
@@ -7225,9 +7270,9 @@ enum skl_disp_power_wells {
#define DP_TP_CTL_SCRAMBLE_DISABLE (1<<7)
/* DisplayPort Transport Status */
-#define DP_TP_STATUS_A 0x64044
-#define DP_TP_STATUS_B 0x64144
-#define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B)
+#define _DP_TP_STATUS_A 0x64044
+#define _DP_TP_STATUS_B 0x64144
+#define DP_TP_STATUS(port) _MMIO_PORT(port, _DP_TP_STATUS_A, _DP_TP_STATUS_B)
#define DP_TP_STATUS_IDLE_DONE (1<<25)
#define DP_TP_STATUS_ACT_SENT (1<<24)
#define DP_TP_STATUS_MODE_STATUS_MST (1<<23)
@@ -7237,9 +7282,9 @@ enum skl_disp_power_wells {
#define DP_TP_STATUS_PAYLOAD_MAPPING_VC0 (3 << 0)
/* DDI Buffer Control */
-#define DDI_BUF_CTL_A 0x64000
-#define DDI_BUF_CTL_B 0x64100
-#define DDI_BUF_CTL(port) _PORT(port, DDI_BUF_CTL_A, DDI_BUF_CTL_B)
+#define _DDI_BUF_CTL_A 0x64000
+#define _DDI_BUF_CTL_B 0x64100
+#define DDI_BUF_CTL(port) _MMIO_PORT(port, _DDI_BUF_CTL_A, _DDI_BUF_CTL_B)
#define DDI_BUF_CTL_ENABLE (1<<31)
#define DDI_BUF_TRANS_SELECT(n) ((n) << 24)
#define DDI_BUF_EMP_MASK (0xf<<24)
@@ -7252,17 +7297,17 @@ enum skl_disp_power_wells {
#define DDI_INIT_DISPLAY_DETECTED (1<<0)
/* DDI Buffer Translations */
-#define DDI_BUF_TRANS_A 0x64E00
-#define DDI_BUF_TRANS_B 0x64E60
-#define DDI_BUF_TRANS_LO(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8)
-#define DDI_BUF_TRANS_HI(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8 + 4)
+#define _DDI_BUF_TRANS_A 0x64E00
+#define _DDI_BUF_TRANS_B 0x64E60
+#define DDI_BUF_TRANS_LO(port, i) _MMIO(_PORT(port, _DDI_BUF_TRANS_A, _DDI_BUF_TRANS_B) + (i) * 8)
+#define DDI_BUF_TRANS_HI(port, i) _MMIO(_PORT(port, _DDI_BUF_TRANS_A, _DDI_BUF_TRANS_B) + (i) * 8 + 4)
/* Sideband Interface (SBI) is programmed indirectly, via
* SBI_ADDR, which contains the register offset; and SBI_DATA,
* which contains the payload */
-#define SBI_ADDR 0xC6000
-#define SBI_DATA 0xC6004
-#define SBI_CTL_STAT 0xC6008
+#define SBI_ADDR _MMIO(0xC6000)
+#define SBI_DATA _MMIO(0xC6004)
+#define SBI_CTL_STAT _MMIO(0xC6008)
#define SBI_CTL_DEST_ICLK (0x0<<16)
#define SBI_CTL_DEST_MPHY (0x1<<16)
#define SBI_CTL_OP_IORD (0x2<<8)
@@ -7293,12 +7338,12 @@ enum skl_disp_power_wells {
#define SBI_GEN0_CFG_BUFFENABLE_DISABLE (1<<0)
/* LPT PIXCLK_GATE */
-#define PIXCLK_GATE 0xC6020
+#define PIXCLK_GATE _MMIO(0xC6020)
#define PIXCLK_GATE_UNGATE (1<<0)
#define PIXCLK_GATE_GATE (0<<0)
/* SPLL */
-#define SPLL_CTL 0x46020
+#define SPLL_CTL _MMIO(0x46020)
#define SPLL_PLL_ENABLE (1<<31)
#define SPLL_PLL_SSC (1<<28)
#define SPLL_PLL_NON_SSC (2<<28)
@@ -7310,9 +7355,9 @@ enum skl_disp_power_wells {
#define SPLL_PLL_FREQ_MASK (3<<26)
/* WRPLL */
-#define WRPLL_CTL1 0x46040
-#define WRPLL_CTL2 0x46060
-#define WRPLL_CTL(pll) (pll == 0 ? WRPLL_CTL1 : WRPLL_CTL2)
+#define _WRPLL_CTL1 0x46040
+#define _WRPLL_CTL2 0x46060
+#define WRPLL_CTL(pll) _MMIO_PIPE(pll, _WRPLL_CTL1, _WRPLL_CTL2)
#define WRPLL_PLL_ENABLE (1<<31)
#define WRPLL_PLL_SSC (1<<28)
#define WRPLL_PLL_NON_SSC (2<<28)
@@ -7329,9 +7374,9 @@ enum skl_disp_power_wells {
#define WRPLL_DIVIDER_FB_MASK (0xff<<16)
/* Port clock selection */
-#define PORT_CLK_SEL_A 0x46100
-#define PORT_CLK_SEL_B 0x46104
-#define PORT_CLK_SEL(port) _PORT(port, PORT_CLK_SEL_A, PORT_CLK_SEL_B)
+#define _PORT_CLK_SEL_A 0x46100
+#define _PORT_CLK_SEL_B 0x46104
+#define PORT_CLK_SEL(port) _MMIO_PORT(port, _PORT_CLK_SEL_A, _PORT_CLK_SEL_B)
#define PORT_CLK_SEL_LCPLL_2700 (0<<29)
#define PORT_CLK_SEL_LCPLL_1350 (1<<29)
#define PORT_CLK_SEL_LCPLL_810 (2<<29)
@@ -7343,18 +7388,18 @@ enum skl_disp_power_wells {
#define PORT_CLK_SEL_MASK (7<<29)
/* Transcoder clock selection */
-#define TRANS_CLK_SEL_A 0x46140
-#define TRANS_CLK_SEL_B 0x46144
-#define TRANS_CLK_SEL(tran) _TRANSCODER(tran, TRANS_CLK_SEL_A, TRANS_CLK_SEL_B)
+#define _TRANS_CLK_SEL_A 0x46140
+#define _TRANS_CLK_SEL_B 0x46144
+#define TRANS_CLK_SEL(tran) _MMIO_TRANS(tran, _TRANS_CLK_SEL_A, _TRANS_CLK_SEL_B)
/* For each transcoder, we need to select the corresponding port clock */
#define TRANS_CLK_SEL_DISABLED (0x0<<29)
#define TRANS_CLK_SEL_PORT(x) (((x)+1)<<29)
-#define TRANSA_MSA_MISC 0x60410
-#define TRANSB_MSA_MISC 0x61410
-#define TRANSC_MSA_MISC 0x62410
-#define TRANS_EDP_MSA_MISC 0x6f410
-#define TRANS_MSA_MISC(tran) _TRANSCODER2(tran, TRANSA_MSA_MISC)
+#define _TRANSA_MSA_MISC 0x60410
+#define _TRANSB_MSA_MISC 0x61410
+#define _TRANSC_MSA_MISC 0x62410
+#define _TRANS_EDP_MSA_MISC 0x6f410
+#define TRANS_MSA_MISC(tran) _MMIO_TRANS2(tran, _TRANSA_MSA_MISC)
#define TRANS_MSA_SYNC_CLK (1<<0)
#define TRANS_MSA_6_BPC (0<<5)
@@ -7364,7 +7409,7 @@ enum skl_disp_power_wells {
#define TRANS_MSA_16_BPC (4<<5)
/* LCPLL Control */
-#define LCPLL_CTL 0x130040
+#define LCPLL_CTL _MMIO(0x130040)
#define LCPLL_PLL_DISABLE (1<<31)
#define LCPLL_PLL_LOCK (1<<30)
#define LCPLL_CLK_FREQ_MASK (3<<26)
@@ -7384,7 +7429,7 @@ enum skl_disp_power_wells {
*/
/* CDCLK_CTL */
-#define CDCLK_CTL 0x46000
+#define CDCLK_CTL _MMIO(0x46000)
#define CDCLK_FREQ_SEL_MASK (3<<26)
#define CDCLK_FREQ_450_432 (0<<26)
#define CDCLK_FREQ_540 (1<<26)
@@ -7400,12 +7445,12 @@ enum skl_disp_power_wells {
#define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1<<16)
/* LCPLL_CTL */
-#define LCPLL1_CTL 0x46010
-#define LCPLL2_CTL 0x46014
+#define LCPLL1_CTL _MMIO(0x46010)
+#define LCPLL2_CTL _MMIO(0x46014)
#define LCPLL_PLL_ENABLE (1<<31)
/* DPLL control1 */
-#define DPLL_CTRL1 0x6C058
+#define DPLL_CTRL1 _MMIO(0x6C058)
#define DPLL_CTRL1_HDMI_MODE(id) (1<<((id)*6+5))
#define DPLL_CTRL1_SSC(id) (1<<((id)*6+4))
#define DPLL_CTRL1_LINK_RATE_MASK(id) (7<<((id)*6+1))
@@ -7420,7 +7465,7 @@ enum skl_disp_power_wells {
#define DPLL_CTRL1_LINK_RATE_2160 5
/* DPLL control2 */
-#define DPLL_CTRL2 0x6C05C
+#define DPLL_CTRL2 _MMIO(0x6C05C)
#define DPLL_CTRL2_DDI_CLK_OFF(port) (1<<((port)+15))
#define DPLL_CTRL2_DDI_CLK_SEL_MASK(port) (3<<((port)*3+1))
#define DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port) ((port)*3+1)
@@ -7428,21 +7473,21 @@ enum skl_disp_power_wells {
#define DPLL_CTRL2_DDI_SEL_OVERRIDE(port) (1<<((port)*3))
/* DPLL Status */
-#define DPLL_STATUS 0x6C060
+#define DPLL_STATUS _MMIO(0x6C060)
#define DPLL_LOCK(id) (1<<((id)*8))
/* DPLL cfg */
-#define DPLL1_CFGCR1 0x6C040
-#define DPLL2_CFGCR1 0x6C048
-#define DPLL3_CFGCR1 0x6C050
+#define _DPLL1_CFGCR1 0x6C040
+#define _DPLL2_CFGCR1 0x6C048
+#define _DPLL3_CFGCR1 0x6C050
#define DPLL_CFGCR1_FREQ_ENABLE (1<<31)
#define DPLL_CFGCR1_DCO_FRACTION_MASK (0x7fff<<9)
#define DPLL_CFGCR1_DCO_FRACTION(x) ((x)<<9)
#define DPLL_CFGCR1_DCO_INTEGER_MASK (0x1ff)
-#define DPLL1_CFGCR2 0x6C044
-#define DPLL2_CFGCR2 0x6C04C
-#define DPLL3_CFGCR2 0x6C054
+#define _DPLL1_CFGCR2 0x6C044
+#define _DPLL2_CFGCR2 0x6C04C
+#define _DPLL3_CFGCR2 0x6C054
#define DPLL_CFGCR2_QDIV_RATIO_MASK (0xff<<8)
#define DPLL_CFGCR2_QDIV_RATIO(x) ((x)<<8)
#define DPLL_CFGCR2_QDIV_MODE(x) ((x)<<7)
@@ -7460,58 +7505,58 @@ enum skl_disp_power_wells {
#define DPLL_CFGCR2_PDIV_7 (4<<2)
#define DPLL_CFGCR2_CENTRAL_FREQ_MASK (3)
-#define DPLL_CFGCR1(id) (DPLL1_CFGCR1 + ((id) - SKL_DPLL1) * 8)
-#define DPLL_CFGCR2(id) (DPLL1_CFGCR2 + ((id) - SKL_DPLL1) * 8)
+#define DPLL_CFGCR1(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR1, _DPLL2_CFGCR2)
+#define DPLL_CFGCR2(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR2, _DPLL2_CFGCR2)
/* BXT display engine PLL */
-#define BXT_DE_PLL_CTL 0x6d000
+#define BXT_DE_PLL_CTL _MMIO(0x6d000)
#define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */
#define BXT_DE_PLL_RATIO_MASK 0xff
-#define BXT_DE_PLL_ENABLE 0x46070
+#define BXT_DE_PLL_ENABLE _MMIO(0x46070)
#define BXT_DE_PLL_PLL_ENABLE (1 << 31)
#define BXT_DE_PLL_LOCK (1 << 30)
/* GEN9 DC */
-#define DC_STATE_EN 0x45504
+#define DC_STATE_EN _MMIO(0x45504)
+#define DC_STATE_DISABLE 0
#define DC_STATE_EN_UPTO_DC5 (1<<0)
#define DC_STATE_EN_DC9 (1<<3)
#define DC_STATE_EN_UPTO_DC6 (2<<0)
#define DC_STATE_EN_UPTO_DC5_DC6_MASK 0x3
-#define DC_STATE_DEBUG 0x45520
+#define DC_STATE_DEBUG _MMIO(0x45520)
#define DC_STATE_DEBUG_MASK_MEMORY_UP (1<<1)
/* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register,
* since on HSW we can't write to it using I915_WRITE. */
-#define D_COMP_HSW (MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
-#define D_COMP_BDW 0x138144
+#define D_COMP_HSW _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
+#define D_COMP_BDW _MMIO(0x138144)
#define D_COMP_RCOMP_IN_PROGRESS (1<<9)
#define D_COMP_COMP_FORCE (1<<8)
#define D_COMP_COMP_DISABLE (1<<0)
/* Pipe WM_LINETIME - watermark line time */
-#define PIPE_WM_LINETIME_A 0x45270
-#define PIPE_WM_LINETIME_B 0x45274
-#define PIPE_WM_LINETIME(pipe) _PIPE(pipe, PIPE_WM_LINETIME_A, \
- PIPE_WM_LINETIME_B)
+#define _PIPE_WM_LINETIME_A 0x45270
+#define _PIPE_WM_LINETIME_B 0x45274
+#define PIPE_WM_LINETIME(pipe) _MMIO_PIPE(pipe, _PIPE_WM_LINETIME_A, _PIPE_WM_LINETIME_B)
#define PIPE_WM_LINETIME_MASK (0x1ff)
#define PIPE_WM_LINETIME_TIME(x) ((x))
#define PIPE_WM_LINETIME_IPS_LINETIME_MASK (0x1ff<<16)
#define PIPE_WM_LINETIME_IPS_LINETIME(x) ((x)<<16)
/* SFUSE_STRAP */
-#define SFUSE_STRAP 0xc2014
+#define SFUSE_STRAP _MMIO(0xc2014)
#define SFUSE_STRAP_FUSE_LOCK (1<<13)
#define SFUSE_STRAP_DISPLAY_DISABLED (1<<7)
#define SFUSE_STRAP_DDIB_DETECTED (1<<2)
#define SFUSE_STRAP_DDIC_DETECTED (1<<1)
#define SFUSE_STRAP_DDID_DETECTED (1<<0)
-#define WM_MISC 0x45260
+#define WM_MISC _MMIO(0x45260)
#define WM_MISC_DATA_PARTITION_5_6 (1 << 0)
-#define WM_DBG 0x45280
+#define WM_DBG _MMIO(0x45280)
#define WM_DBG_DISALLOW_MULTIPLE_LP (1<<0)
#define WM_DBG_DISALLOW_MAXFIFO (1<<1)
#define WM_DBG_DISALLOW_SPRITE (1<<2)
@@ -7548,28 +7593,29 @@ enum skl_disp_power_wells {
#define _PIPE_B_CSC_POSTOFF_ME 0x49144
#define _PIPE_B_CSC_POSTOFF_LO 0x49148
-#define PIPE_CSC_COEFF_RY_GY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY)
-#define PIPE_CSC_COEFF_BY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY)
-#define PIPE_CSC_COEFF_RU_GU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU)
-#define PIPE_CSC_COEFF_BU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BU, _PIPE_B_CSC_COEFF_BU)
-#define PIPE_CSC_COEFF_RV_GV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, _PIPE_B_CSC_COEFF_RV_GV)
-#define PIPE_CSC_COEFF_BV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BV, _PIPE_B_CSC_COEFF_BV)
-#define PIPE_CSC_MODE(pipe) _PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE)
-#define PIPE_CSC_PREOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, _PIPE_B_CSC_PREOFF_HI)
-#define PIPE_CSC_PREOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, _PIPE_B_CSC_PREOFF_ME)
-#define PIPE_CSC_PREOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, _PIPE_B_CSC_PREOFF_LO)
-#define PIPE_CSC_POSTOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, _PIPE_B_CSC_POSTOFF_HI)
-#define PIPE_CSC_POSTOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
-#define PIPE_CSC_POSTOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
+#define PIPE_CSC_COEFF_RY_GY(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY)
+#define PIPE_CSC_COEFF_BY(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY)
+#define PIPE_CSC_COEFF_RU_GU(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU)
+#define PIPE_CSC_COEFF_BU(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BU, _PIPE_B_CSC_COEFF_BU)
+#define PIPE_CSC_COEFF_RV_GV(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, _PIPE_B_CSC_COEFF_RV_GV)
+#define PIPE_CSC_COEFF_BV(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BV, _PIPE_B_CSC_COEFF_BV)
+#define PIPE_CSC_MODE(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE)
+#define PIPE_CSC_PREOFF_HI(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, _PIPE_B_CSC_PREOFF_HI)
+#define PIPE_CSC_PREOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, _PIPE_B_CSC_PREOFF_ME)
+#define PIPE_CSC_PREOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, _PIPE_B_CSC_PREOFF_LO)
+#define PIPE_CSC_POSTOFF_HI(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, _PIPE_B_CSC_POSTOFF_HI)
+#define PIPE_CSC_POSTOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
+#define PIPE_CSC_POSTOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
/* MIPI DSI registers */
#define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */
+#define _MMIO_MIPI(port, a, c) _MMIO(_MIPI_PORT(port, a, c))
/* BXT MIPI clock controls */
#define BXT_MAX_VAR_OUTPUT_KHZ 39500
-#define BXT_MIPI_CLOCK_CTL 0x46090
+#define BXT_MIPI_CLOCK_CTL _MMIO(0x46090)
#define BXT_MIPI1_DIV_SHIFT 26
#define BXT_MIPI2_DIV_SHIFT 10
#define BXT_MIPI_DIV_SHIFT(port) \
@@ -7631,20 +7677,20 @@ enum skl_disp_power_wells {
/* BXT MIPI mode configure */
#define _BXT_MIPIA_TRANS_HACTIVE 0x6B0F8
#define _BXT_MIPIC_TRANS_HACTIVE 0x6B8F8
-#define BXT_MIPI_TRANS_HACTIVE(tc) _MIPI_PORT(tc, \
+#define BXT_MIPI_TRANS_HACTIVE(tc) _MMIO_MIPI(tc, \
_BXT_MIPIA_TRANS_HACTIVE, _BXT_MIPIC_TRANS_HACTIVE)
#define _BXT_MIPIA_TRANS_VACTIVE 0x6B0FC
#define _BXT_MIPIC_TRANS_VACTIVE 0x6B8FC
-#define BXT_MIPI_TRANS_VACTIVE(tc) _MIPI_PORT(tc, \
+#define BXT_MIPI_TRANS_VACTIVE(tc) _MMIO_MIPI(tc, \
_BXT_MIPIA_TRANS_VACTIVE, _BXT_MIPIC_TRANS_VACTIVE)
#define _BXT_MIPIA_TRANS_VTOTAL 0x6B100
#define _BXT_MIPIC_TRANS_VTOTAL 0x6B900
-#define BXT_MIPI_TRANS_VTOTAL(tc) _MIPI_PORT(tc, \
+#define BXT_MIPI_TRANS_VTOTAL(tc) _MMIO_MIPI(tc, \
_BXT_MIPIA_TRANS_VTOTAL, _BXT_MIPIC_TRANS_VTOTAL)
-#define BXT_DSI_PLL_CTL 0x161000
+#define BXT_DSI_PLL_CTL _MMIO(0x161000)
#define BXT_DSI_PLL_PVD_RATIO_SHIFT 16
#define BXT_DSI_PLL_PVD_RATIO_MASK (3 << BXT_DSI_PLL_PVD_RATIO_SHIFT)
#define BXT_DSI_PLL_PVD_RATIO_1 (1 << BXT_DSI_PLL_PVD_RATIO_SHIFT)
@@ -7662,19 +7708,18 @@ enum skl_disp_power_wells {
#define BXT_DSI_PLL_RATIO_MASK 0xFF
#define BXT_REF_CLOCK_KHZ 19500
-#define BXT_DSI_PLL_ENABLE 0x46080
+#define BXT_DSI_PLL_ENABLE _MMIO(0x46080)
#define BXT_DSI_PLL_DO_ENABLE (1 << 31)
#define BXT_DSI_PLL_LOCKED (1 << 30)
#define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190)
#define _MIPIC_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700)
-#define MIPI_PORT_CTRL(port) _MIPI_PORT(port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL)
+#define MIPI_PORT_CTRL(port) _MMIO_MIPI(port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL)
/* BXT port control */
#define _BXT_MIPIA_PORT_CTRL 0x6B0C0
#define _BXT_MIPIC_PORT_CTRL 0x6B8C0
-#define BXT_MIPI_PORT_CTRL(tc) _MIPI_PORT(tc, _BXT_MIPIA_PORT_CTRL, \
- _BXT_MIPIC_PORT_CTRL)
+#define BXT_MIPI_PORT_CTRL(tc) _MMIO_MIPI(tc, _BXT_MIPIA_PORT_CTRL, _BXT_MIPIC_PORT_CTRL)
#define DPI_ENABLE (1 << 31) /* A + C */
#define MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT 27
@@ -7718,8 +7763,7 @@ enum skl_disp_power_wells {
#define _MIPIA_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61194)
#define _MIPIC_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61704)
-#define MIPI_TEARING_CTRL(port) _MIPI_PORT(port, \
- _MIPIA_TEARING_CTRL, _MIPIC_TEARING_CTRL)
+#define MIPI_TEARING_CTRL(port) _MMIO_MIPI(port, _MIPIA_TEARING_CTRL, _MIPIC_TEARING_CTRL)
#define TEARING_EFFECT_DELAY_SHIFT 0
#define TEARING_EFFECT_DELAY_MASK (0xffff << 0)
@@ -7730,8 +7774,7 @@ enum skl_disp_power_wells {
#define _MIPIA_DEVICE_READY (dev_priv->mipi_mmio_base + 0xb000)
#define _MIPIC_DEVICE_READY (dev_priv->mipi_mmio_base + 0xb800)
-#define MIPI_DEVICE_READY(port) _MIPI_PORT(port, _MIPIA_DEVICE_READY, \
- _MIPIC_DEVICE_READY)
+#define MIPI_DEVICE_READY(port) _MMIO_MIPI(port, _MIPIA_DEVICE_READY, _MIPIC_DEVICE_READY)
#define BUS_POSSESSION (1 << 3) /* set to give bus to receiver */
#define ULPS_STATE_MASK (3 << 1)
#define ULPS_STATE_ENTER (2 << 1)
@@ -7741,12 +7784,10 @@ enum skl_disp_power_wells {
#define _MIPIA_INTR_STAT (dev_priv->mipi_mmio_base + 0xb004)
#define _MIPIC_INTR_STAT (dev_priv->mipi_mmio_base + 0xb804)
-#define MIPI_INTR_STAT(port) _MIPI_PORT(port, _MIPIA_INTR_STAT, \
- _MIPIC_INTR_STAT)
+#define MIPI_INTR_STAT(port) _MMIO_MIPI(port, _MIPIA_INTR_STAT, _MIPIC_INTR_STAT)
#define _MIPIA_INTR_EN (dev_priv->mipi_mmio_base + 0xb008)
#define _MIPIC_INTR_EN (dev_priv->mipi_mmio_base + 0xb808)
-#define MIPI_INTR_EN(port) _MIPI_PORT(port, _MIPIA_INTR_EN, \
- _MIPIC_INTR_EN)
+#define MIPI_INTR_EN(port) _MMIO_MIPI(port, _MIPIA_INTR_EN, _MIPIC_INTR_EN)
#define TEARING_EFFECT (1 << 31)
#define SPL_PKT_SENT_INTERRUPT (1 << 30)
#define GEN_READ_DATA_AVAIL (1 << 29)
@@ -7782,8 +7823,7 @@ enum skl_disp_power_wells {
#define _MIPIA_DSI_FUNC_PRG (dev_priv->mipi_mmio_base + 0xb00c)
#define _MIPIC_DSI_FUNC_PRG (dev_priv->mipi_mmio_base + 0xb80c)
-#define MIPI_DSI_FUNC_PRG(port) _MIPI_PORT(port, _MIPIA_DSI_FUNC_PRG, \
- _MIPIC_DSI_FUNC_PRG)
+#define MIPI_DSI_FUNC_PRG(port) _MMIO_MIPI(port, _MIPIA_DSI_FUNC_PRG, _MIPIC_DSI_FUNC_PRG)
#define CMD_MODE_DATA_WIDTH_MASK (7 << 13)
#define CMD_MODE_NOT_SUPPORTED (0 << 13)
#define CMD_MODE_DATA_WIDTH_16_BIT (1 << 13)
@@ -7806,32 +7846,27 @@ enum skl_disp_power_wells {
#define _MIPIA_HS_TX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb010)
#define _MIPIC_HS_TX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb810)
-#define MIPI_HS_TX_TIMEOUT(port) _MIPI_PORT(port, _MIPIA_HS_TX_TIMEOUT, \
- _MIPIC_HS_TX_TIMEOUT)
+#define MIPI_HS_TX_TIMEOUT(port) _MMIO_MIPI(port, _MIPIA_HS_TX_TIMEOUT, _MIPIC_HS_TX_TIMEOUT)
#define HIGH_SPEED_TX_TIMEOUT_COUNTER_MASK 0xffffff
#define _MIPIA_LP_RX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb014)
#define _MIPIC_LP_RX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb814)
-#define MIPI_LP_RX_TIMEOUT(port) _MIPI_PORT(port, _MIPIA_LP_RX_TIMEOUT, \
- _MIPIC_LP_RX_TIMEOUT)
+#define MIPI_LP_RX_TIMEOUT(port) _MMIO_MIPI(port, _MIPIA_LP_RX_TIMEOUT, _MIPIC_LP_RX_TIMEOUT)
#define LOW_POWER_RX_TIMEOUT_COUNTER_MASK 0xffffff
#define _MIPIA_TURN_AROUND_TIMEOUT (dev_priv->mipi_mmio_base + 0xb018)
#define _MIPIC_TURN_AROUND_TIMEOUT (dev_priv->mipi_mmio_base + 0xb818)
-#define MIPI_TURN_AROUND_TIMEOUT(port) _MIPI_PORT(port, \
- _MIPIA_TURN_AROUND_TIMEOUT, _MIPIC_TURN_AROUND_TIMEOUT)
+#define MIPI_TURN_AROUND_TIMEOUT(port) _MMIO_MIPI(port, _MIPIA_TURN_AROUND_TIMEOUT, _MIPIC_TURN_AROUND_TIMEOUT)
#define TURN_AROUND_TIMEOUT_MASK 0x3f
#define _MIPIA_DEVICE_RESET_TIMER (dev_priv->mipi_mmio_base + 0xb01c)
#define _MIPIC_DEVICE_RESET_TIMER (dev_priv->mipi_mmio_base + 0xb81c)
-#define MIPI_DEVICE_RESET_TIMER(port) _MIPI_PORT(port, \
- _MIPIA_DEVICE_RESET_TIMER, _MIPIC_DEVICE_RESET_TIMER)
+#define MIPI_DEVICE_RESET_TIMER(port) _MMIO_MIPI(port, _MIPIA_DEVICE_RESET_TIMER, _MIPIC_DEVICE_RESET_TIMER)
#define DEVICE_RESET_TIMER_MASK 0xffff
#define _MIPIA_DPI_RESOLUTION (dev_priv->mipi_mmio_base + 0xb020)
#define _MIPIC_DPI_RESOLUTION (dev_priv->mipi_mmio_base + 0xb820)
-#define MIPI_DPI_RESOLUTION(port) _MIPI_PORT(port, _MIPIA_DPI_RESOLUTION, \
- _MIPIC_DPI_RESOLUTION)
+#define MIPI_DPI_RESOLUTION(port) _MMIO_MIPI(port, _MIPIA_DPI_RESOLUTION, _MIPIC_DPI_RESOLUTION)
#define VERTICAL_ADDRESS_SHIFT 16
#define VERTICAL_ADDRESS_MASK (0xffff << 16)
#define HORIZONTAL_ADDRESS_SHIFT 0
@@ -7839,8 +7874,7 @@ enum skl_disp_power_wells {
#define _MIPIA_DBI_FIFO_THROTTLE (dev_priv->mipi_mmio_base + 0xb024)
#define _MIPIC_DBI_FIFO_THROTTLE (dev_priv->mipi_mmio_base + 0xb824)
-#define MIPI_DBI_FIFO_THROTTLE(port) _MIPI_PORT(port, \
- _MIPIA_DBI_FIFO_THROTTLE, _MIPIC_DBI_FIFO_THROTTLE)
+#define MIPI_DBI_FIFO_THROTTLE(port) _MMIO_MIPI(port, _MIPIA_DBI_FIFO_THROTTLE, _MIPIC_DBI_FIFO_THROTTLE)
#define DBI_FIFO_EMPTY_HALF (0 << 0)
#define DBI_FIFO_EMPTY_QUARTER (1 << 0)
#define DBI_FIFO_EMPTY_7_LOCATIONS (2 << 0)
@@ -7848,50 +7882,41 @@ enum skl_disp_power_wells {
/* regs below are bits 15:0 */
#define _MIPIA_HSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb028)
#define _MIPIC_HSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb828)
-#define MIPI_HSYNC_PADDING_COUNT(port) _MIPI_PORT(port, \
- _MIPIA_HSYNC_PADDING_COUNT, _MIPIC_HSYNC_PADDING_COUNT)
+#define MIPI_HSYNC_PADDING_COUNT(port) _MMIO_MIPI(port, _MIPIA_HSYNC_PADDING_COUNT, _MIPIC_HSYNC_PADDING_COUNT)
#define _MIPIA_HBP_COUNT (dev_priv->mipi_mmio_base + 0xb02c)
#define _MIPIC_HBP_COUNT (dev_priv->mipi_mmio_base + 0xb82c)
-#define MIPI_HBP_COUNT(port) _MIPI_PORT(port, _MIPIA_HBP_COUNT, \
- _MIPIC_HBP_COUNT)
+#define MIPI_HBP_COUNT(port) _MMIO_MIPI(port, _MIPIA_HBP_COUNT, _MIPIC_HBP_COUNT)
#define _MIPIA_HFP_COUNT (dev_priv->mipi_mmio_base + 0xb030)
#define _MIPIC_HFP_COUNT (dev_priv->mipi_mmio_base + 0xb830)
-#define MIPI_HFP_COUNT(port) _MIPI_PORT(port, _MIPIA_HFP_COUNT, \
- _MIPIC_HFP_COUNT)
+#define MIPI_HFP_COUNT(port) _MMIO_MIPI(port, _MIPIA_HFP_COUNT, _MIPIC_HFP_COUNT)
#define _MIPIA_HACTIVE_AREA_COUNT (dev_priv->mipi_mmio_base + 0xb034)
#define _MIPIC_HACTIVE_AREA_COUNT (dev_priv->mipi_mmio_base + 0xb834)
-#define MIPI_HACTIVE_AREA_COUNT(port) _MIPI_PORT(port, \
- _MIPIA_HACTIVE_AREA_COUNT, _MIPIC_HACTIVE_AREA_COUNT)
+#define MIPI_HACTIVE_AREA_COUNT(port) _MMIO_MIPI(port, _MIPIA_HACTIVE_AREA_COUNT, _MIPIC_HACTIVE_AREA_COUNT)
#define _MIPIA_VSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb038)
#define _MIPIC_VSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb838)
-#define MIPI_VSYNC_PADDING_COUNT(port) _MIPI_PORT(port, \
- _MIPIA_VSYNC_PADDING_COUNT, _MIPIC_VSYNC_PADDING_COUNT)
+#define MIPI_VSYNC_PADDING_COUNT(port) _MMIO_MIPI(port, _MIPIA_VSYNC_PADDING_COUNT, _MIPIC_VSYNC_PADDING_COUNT)
#define _MIPIA_VBP_COUNT (dev_priv->mipi_mmio_base + 0xb03c)
#define _MIPIC_VBP_COUNT (dev_priv->mipi_mmio_base + 0xb83c)
-#define MIPI_VBP_COUNT(port) _MIPI_PORT(port, _MIPIA_VBP_COUNT, \
- _MIPIC_VBP_COUNT)
+#define MIPI_VBP_COUNT(port) _MMIO_MIPI(port, _MIPIA_VBP_COUNT, _MIPIC_VBP_COUNT)
#define _MIPIA_VFP_COUNT (dev_priv->mipi_mmio_base + 0xb040)
#define _MIPIC_VFP_COUNT (dev_priv->mipi_mmio_base + 0xb840)
-#define MIPI_VFP_COUNT(port) _MIPI_PORT(port, _MIPIA_VFP_COUNT, \
- _MIPIC_VFP_COUNT)
+#define MIPI_VFP_COUNT(port) _MMIO_MIPI(port, _MIPIA_VFP_COUNT, _MIPIC_VFP_COUNT)
#define _MIPIA_HIGH_LOW_SWITCH_COUNT (dev_priv->mipi_mmio_base + 0xb044)
#define _MIPIC_HIGH_LOW_SWITCH_COUNT (dev_priv->mipi_mmio_base + 0xb844)
-#define MIPI_HIGH_LOW_SWITCH_COUNT(port) _MIPI_PORT(port, \
- _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIC_HIGH_LOW_SWITCH_COUNT)
+#define MIPI_HIGH_LOW_SWITCH_COUNT(port) _MMIO_MIPI(port, _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIC_HIGH_LOW_SWITCH_COUNT)
/* regs above are bits 15:0 */
#define _MIPIA_DPI_CONTROL (dev_priv->mipi_mmio_base + 0xb048)
#define _MIPIC_DPI_CONTROL (dev_priv->mipi_mmio_base + 0xb848)
-#define MIPI_DPI_CONTROL(port) _MIPI_PORT(port, _MIPIA_DPI_CONTROL, \
- _MIPIC_DPI_CONTROL)
+#define MIPI_DPI_CONTROL(port) _MMIO_MIPI(port, _MIPIA_DPI_CONTROL, _MIPIC_DPI_CONTROL)
#define DPI_LP_MODE (1 << 6)
#define BACKLIGHT_OFF (1 << 5)
#define BACKLIGHT_ON (1 << 4)
@@ -7902,29 +7927,26 @@ enum skl_disp_power_wells {
#define _MIPIA_DPI_DATA (dev_priv->mipi_mmio_base + 0xb04c)
#define _MIPIC_DPI_DATA (dev_priv->mipi_mmio_base + 0xb84c)
-#define MIPI_DPI_DATA(port) _MIPI_PORT(port, _MIPIA_DPI_DATA, \
- _MIPIC_DPI_DATA)
+#define MIPI_DPI_DATA(port) _MMIO_MIPI(port, _MIPIA_DPI_DATA, _MIPIC_DPI_DATA)
#define COMMAND_BYTE_SHIFT 0
#define COMMAND_BYTE_MASK (0x3f << 0)
#define _MIPIA_INIT_COUNT (dev_priv->mipi_mmio_base + 0xb050)
#define _MIPIC_INIT_COUNT (dev_priv->mipi_mmio_base + 0xb850)
-#define MIPI_INIT_COUNT(port) _MIPI_PORT(port, _MIPIA_INIT_COUNT, \
- _MIPIC_INIT_COUNT)
+#define MIPI_INIT_COUNT(port) _MMIO_MIPI(port, _MIPIA_INIT_COUNT, _MIPIC_INIT_COUNT)
#define MASTER_INIT_TIMER_SHIFT 0
#define MASTER_INIT_TIMER_MASK (0xffff << 0)
#define _MIPIA_MAX_RETURN_PKT_SIZE (dev_priv->mipi_mmio_base + 0xb054)
#define _MIPIC_MAX_RETURN_PKT_SIZE (dev_priv->mipi_mmio_base + 0xb854)
-#define MIPI_MAX_RETURN_PKT_SIZE(port) _MIPI_PORT(port, \
+#define MIPI_MAX_RETURN_PKT_SIZE(port) _MMIO_MIPI(port, \
_MIPIA_MAX_RETURN_PKT_SIZE, _MIPIC_MAX_RETURN_PKT_SIZE)
#define MAX_RETURN_PKT_SIZE_SHIFT 0
#define MAX_RETURN_PKT_SIZE_MASK (0x3ff << 0)
#define _MIPIA_VIDEO_MODE_FORMAT (dev_priv->mipi_mmio_base + 0xb058)
#define _MIPIC_VIDEO_MODE_FORMAT (dev_priv->mipi_mmio_base + 0xb858)
-#define MIPI_VIDEO_MODE_FORMAT(port) _MIPI_PORT(port, \
- _MIPIA_VIDEO_MODE_FORMAT, _MIPIC_VIDEO_MODE_FORMAT)
+#define MIPI_VIDEO_MODE_FORMAT(port) _MMIO_MIPI(port, _MIPIA_VIDEO_MODE_FORMAT, _MIPIC_VIDEO_MODE_FORMAT)
#define RANDOM_DPI_DISPLAY_RESOLUTION (1 << 4)
#define DISABLE_VIDEO_BTA (1 << 3)
#define IP_TG_CONFIG (1 << 2)
@@ -7934,8 +7956,7 @@ enum skl_disp_power_wells {
#define _MIPIA_EOT_DISABLE (dev_priv->mipi_mmio_base + 0xb05c)
#define _MIPIC_EOT_DISABLE (dev_priv->mipi_mmio_base + 0xb85c)
-#define MIPI_EOT_DISABLE(port) _MIPI_PORT(port, _MIPIA_EOT_DISABLE, \
- _MIPIC_EOT_DISABLE)
+#define MIPI_EOT_DISABLE(port) _MMIO_MIPI(port, _MIPIA_EOT_DISABLE, _MIPIC_EOT_DISABLE)
#define LP_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 7)
#define HS_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 6)
#define LOW_CONTENTION_RECOVERY_DISABLE (1 << 5)
@@ -7947,31 +7968,26 @@ enum skl_disp_power_wells {
#define _MIPIA_LP_BYTECLK (dev_priv->mipi_mmio_base + 0xb060)
#define _MIPIC_LP_BYTECLK (dev_priv->mipi_mmio_base + 0xb860)
-#define MIPI_LP_BYTECLK(port) _MIPI_PORT(port, _MIPIA_LP_BYTECLK, \
- _MIPIC_LP_BYTECLK)
+#define MIPI_LP_BYTECLK(port) _MMIO_MIPI(port, _MIPIA_LP_BYTECLK, _MIPIC_LP_BYTECLK)
#define LP_BYTECLK_SHIFT 0
#define LP_BYTECLK_MASK (0xffff << 0)
/* bits 31:0 */
#define _MIPIA_LP_GEN_DATA (dev_priv->mipi_mmio_base + 0xb064)
#define _MIPIC_LP_GEN_DATA (dev_priv->mipi_mmio_base + 0xb864)
-#define MIPI_LP_GEN_DATA(port) _MIPI_PORT(port, _MIPIA_LP_GEN_DATA, \
- _MIPIC_LP_GEN_DATA)
+#define MIPI_LP_GEN_DATA(port) _MMIO_MIPI(port, _MIPIA_LP_GEN_DATA, _MIPIC_LP_GEN_DATA)
/* bits 31:0 */
#define _MIPIA_HS_GEN_DATA (dev_priv->mipi_mmio_base + 0xb068)
#define _MIPIC_HS_GEN_DATA (dev_priv->mipi_mmio_base + 0xb868)
-#define MIPI_HS_GEN_DATA(port) _MIPI_PORT(port, _MIPIA_HS_GEN_DATA, \
- _MIPIC_HS_GEN_DATA)
+#define MIPI_HS_GEN_DATA(port) _MMIO_MIPI(port, _MIPIA_HS_GEN_DATA, _MIPIC_HS_GEN_DATA)
#define _MIPIA_LP_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb06c)
#define _MIPIC_LP_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb86c)
-#define MIPI_LP_GEN_CTRL(port) _MIPI_PORT(port, _MIPIA_LP_GEN_CTRL, \
- _MIPIC_LP_GEN_CTRL)
+#define MIPI_LP_GEN_CTRL(port) _MMIO_MIPI(port, _MIPIA_LP_GEN_CTRL, _MIPIC_LP_GEN_CTRL)
#define _MIPIA_HS_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb070)
#define _MIPIC_HS_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb870)
-#define MIPI_HS_GEN_CTRL(port) _MIPI_PORT(port, _MIPIA_HS_GEN_CTRL, \
- _MIPIC_HS_GEN_CTRL)
+#define MIPI_HS_GEN_CTRL(port) _MMIO_MIPI(port, _MIPIA_HS_GEN_CTRL, _MIPIC_HS_GEN_CTRL)
#define LONG_PACKET_WORD_COUNT_SHIFT 8
#define LONG_PACKET_WORD_COUNT_MASK (0xffff << 8)
#define SHORT_PACKET_PARAM_SHIFT 8
@@ -7984,8 +8000,7 @@ enum skl_disp_power_wells {
#define _MIPIA_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb074)
#define _MIPIC_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb874)
-#define MIPI_GEN_FIFO_STAT(port) _MIPI_PORT(port, _MIPIA_GEN_FIFO_STAT, \
- _MIPIC_GEN_FIFO_STAT)
+#define MIPI_GEN_FIFO_STAT(port) _MMIO_MIPI(port, _MIPIA_GEN_FIFO_STAT, _MIPIC_GEN_FIFO_STAT)
#define DPI_FIFO_EMPTY (1 << 28)
#define DBI_FIFO_EMPTY (1 << 27)
#define LP_CTRL_FIFO_EMPTY (1 << 26)
@@ -8003,16 +8018,14 @@ enum skl_disp_power_wells {
#define _MIPIA_HS_LS_DBI_ENABLE (dev_priv->mipi_mmio_base + 0xb078)
#define _MIPIC_HS_LS_DBI_ENABLE (dev_priv->mipi_mmio_base + 0xb878)
-#define MIPI_HS_LP_DBI_ENABLE(port) _MIPI_PORT(port, \
- _MIPIA_HS_LS_DBI_ENABLE, _MIPIC_HS_LS_DBI_ENABLE)
+#define MIPI_HS_LP_DBI_ENABLE(port) _MMIO_MIPI(port, _MIPIA_HS_LS_DBI_ENABLE, _MIPIC_HS_LS_DBI_ENABLE)
#define DBI_HS_LP_MODE_MASK (1 << 0)
#define DBI_LP_MODE (1 << 0)
#define DBI_HS_MODE (0 << 0)
#define _MIPIA_DPHY_PARAM (dev_priv->mipi_mmio_base + 0xb080)
#define _MIPIC_DPHY_PARAM (dev_priv->mipi_mmio_base + 0xb880)
-#define MIPI_DPHY_PARAM(port) _MIPI_PORT(port, _MIPIA_DPHY_PARAM, \
- _MIPIC_DPHY_PARAM)
+#define MIPI_DPHY_PARAM(port) _MMIO_MIPI(port, _MIPIA_DPHY_PARAM, _MIPIC_DPHY_PARAM)
#define EXIT_ZERO_COUNT_SHIFT 24
#define EXIT_ZERO_COUNT_MASK (0x3f << 24)
#define TRAIL_COUNT_SHIFT 16
@@ -8025,15 +8038,11 @@ enum skl_disp_power_wells {
/* bits 31:0 */
#define _MIPIA_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb084)
#define _MIPIC_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb884)
-#define MIPI_DBI_BW_CTRL(port) _MIPI_PORT(port, _MIPIA_DBI_BW_CTRL, \
- _MIPIC_DBI_BW_CTRL)
-
-#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base \
- + 0xb088)
-#define _MIPIC_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base \
- + 0xb888)
-#define MIPI_CLK_LANE_SWITCH_TIME_CNT(port) _MIPI_PORT(port, \
- _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIC_CLK_LANE_SWITCH_TIME_CNT)
+#define MIPI_DBI_BW_CTRL(port) _MMIO_MIPI(port, _MIPIA_DBI_BW_CTRL, _MIPIC_DBI_BW_CTRL)
+
+#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base + 0xb088)
+#define _MIPIC_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base + 0xb888)
+#define MIPI_CLK_LANE_SWITCH_TIME_CNT(port) _MMIO_MIPI(port, _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIC_CLK_LANE_SWITCH_TIME_CNT)
#define LP_HS_SSW_CNT_SHIFT 16
#define LP_HS_SSW_CNT_MASK (0xffff << 16)
#define HS_LP_PWR_SW_CNT_SHIFT 0
@@ -8041,19 +8050,16 @@ enum skl_disp_power_wells {
#define _MIPIA_STOP_STATE_STALL (dev_priv->mipi_mmio_base + 0xb08c)
#define _MIPIC_STOP_STATE_STALL (dev_priv->mipi_mmio_base + 0xb88c)
-#define MIPI_STOP_STATE_STALL(port) _MIPI_PORT(port, \
- _MIPIA_STOP_STATE_STALL, _MIPIC_STOP_STATE_STALL)
+#define MIPI_STOP_STATE_STALL(port) _MMIO_MIPI(port, _MIPIA_STOP_STATE_STALL, _MIPIC_STOP_STATE_STALL)
#define STOP_STATE_STALL_COUNTER_SHIFT 0
#define STOP_STATE_STALL_COUNTER_MASK (0xff << 0)
#define _MIPIA_INTR_STAT_REG_1 (dev_priv->mipi_mmio_base + 0xb090)
#define _MIPIC_INTR_STAT_REG_1 (dev_priv->mipi_mmio_base + 0xb890)
-#define MIPI_INTR_STAT_REG_1(port) _MIPI_PORT(port, \
- _MIPIA_INTR_STAT_REG_1, _MIPIC_INTR_STAT_REG_1)
+#define MIPI_INTR_STAT_REG_1(port) _MMIO_MIPI(port, _MIPIA_INTR_STAT_REG_1, _MIPIC_INTR_STAT_REG_1)
#define _MIPIA_INTR_EN_REG_1 (dev_priv->mipi_mmio_base + 0xb094)
#define _MIPIC_INTR_EN_REG_1 (dev_priv->mipi_mmio_base + 0xb894)
-#define MIPI_INTR_EN_REG_1(port) _MIPI_PORT(port, _MIPIA_INTR_EN_REG_1, \
- _MIPIC_INTR_EN_REG_1)
+#define MIPI_INTR_EN_REG_1(port) _MMIO_MIPI(port, _MIPIA_INTR_EN_REG_1, _MIPIC_INTR_EN_REG_1)
#define RX_CONTENTION_DETECTED (1 << 0)
/* XXX: only pipe A ?!? */
@@ -8073,8 +8079,7 @@ enum skl_disp_power_wells {
#define _MIPIA_CTRL (dev_priv->mipi_mmio_base + 0xb104)
#define _MIPIC_CTRL (dev_priv->mipi_mmio_base + 0xb904)
-#define MIPI_CTRL(port) _MIPI_PORT(port, _MIPIA_CTRL, \
- _MIPIC_CTRL)
+#define MIPI_CTRL(port) _MMIO_MIPI(port, _MIPIA_CTRL, _MIPIC_CTRL)
#define ESCAPE_CLOCK_DIVIDER_SHIFT 5 /* A only */
#define ESCAPE_CLOCK_DIVIDER_MASK (3 << 5)
#define ESCAPE_CLOCK_DIVIDER_1 (0 << 5)
@@ -8093,23 +8098,20 @@ enum skl_disp_power_wells {
#define _MIPIA_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb108)
#define _MIPIC_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb908)
-#define MIPI_DATA_ADDRESS(port) _MIPI_PORT(port, _MIPIA_DATA_ADDRESS, \
- _MIPIC_DATA_ADDRESS)
+#define MIPI_DATA_ADDRESS(port) _MMIO_MIPI(port, _MIPIA_DATA_ADDRESS, _MIPIC_DATA_ADDRESS)
#define DATA_MEM_ADDRESS_SHIFT 5
#define DATA_MEM_ADDRESS_MASK (0x7ffffff << 5)
#define DATA_VALID (1 << 0)
#define _MIPIA_DATA_LENGTH (dev_priv->mipi_mmio_base + 0xb10c)
#define _MIPIC_DATA_LENGTH (dev_priv->mipi_mmio_base + 0xb90c)
-#define MIPI_DATA_LENGTH(port) _MIPI_PORT(port, _MIPIA_DATA_LENGTH, \
- _MIPIC_DATA_LENGTH)
+#define MIPI_DATA_LENGTH(port) _MMIO_MIPI(port, _MIPIA_DATA_LENGTH, _MIPIC_DATA_LENGTH)
#define DATA_LENGTH_SHIFT 0
#define DATA_LENGTH_MASK (0xfffff << 0)
#define _MIPIA_COMMAND_ADDRESS (dev_priv->mipi_mmio_base + 0xb110)
#define _MIPIC_COMMAND_ADDRESS (dev_priv->mipi_mmio_base + 0xb910)
-#define MIPI_COMMAND_ADDRESS(port) _MIPI_PORT(port, \
- _MIPIA_COMMAND_ADDRESS, _MIPIC_COMMAND_ADDRESS)
+#define MIPI_COMMAND_ADDRESS(port) _MMIO_MIPI(port, _MIPIA_COMMAND_ADDRESS, _MIPIC_COMMAND_ADDRESS)
#define COMMAND_MEM_ADDRESS_SHIFT 5
#define COMMAND_MEM_ADDRESS_MASK (0x7ffffff << 5)
#define AUTO_PWG_ENABLE (1 << 2)
@@ -8118,21 +8120,17 @@ enum skl_disp_power_wells {
#define _MIPIA_COMMAND_LENGTH (dev_priv->mipi_mmio_base + 0xb114)
#define _MIPIC_COMMAND_LENGTH (dev_priv->mipi_mmio_base + 0xb914)
-#define MIPI_COMMAND_LENGTH(port) _MIPI_PORT(port, _MIPIA_COMMAND_LENGTH, \
- _MIPIC_COMMAND_LENGTH)
+#define MIPI_COMMAND_LENGTH(port) _MMIO_MIPI(port, _MIPIA_COMMAND_LENGTH, _MIPIC_COMMAND_LENGTH)
#define COMMAND_LENGTH_SHIFT(n) (8 * (n)) /* n: 0...3 */
#define COMMAND_LENGTH_MASK(n) (0xff << (8 * (n)))
#define _MIPIA_READ_DATA_RETURN0 (dev_priv->mipi_mmio_base + 0xb118)
#define _MIPIC_READ_DATA_RETURN0 (dev_priv->mipi_mmio_base + 0xb918)
-#define MIPI_READ_DATA_RETURN(port, n) \
- (_MIPI_PORT(port, _MIPIA_READ_DATA_RETURN0, _MIPIC_READ_DATA_RETURN0) \
- + 4 * (n)) /* n: 0...7 */
+#define MIPI_READ_DATA_RETURN(port, n) _MMIO(_MIPI(port, _MIPIA_READ_DATA_RETURN0, _MIPIC_READ_DATA_RETURN0) + 4 * (n)) /* n: 0...7 */
#define _MIPIA_READ_DATA_VALID (dev_priv->mipi_mmio_base + 0xb138)
#define _MIPIC_READ_DATA_VALID (dev_priv->mipi_mmio_base + 0xb938)
-#define MIPI_READ_DATA_VALID(port) _MIPI_PORT(port, \
- _MIPIA_READ_DATA_VALID, _MIPIC_READ_DATA_VALID)
+#define MIPI_READ_DATA_VALID(port) _MMIO_MIPI(port, _MIPIA_READ_DATA_VALID, _MIPIC_READ_DATA_VALID)
#define READ_DATA_VALID(n) (1 << (n))
/* For UMS only (deprecated): */
@@ -8140,12 +8138,12 @@ enum skl_disp_power_wells {
#define _PALETTE_B (dev_priv->info.display_mmio_offset + 0xa800)
/* MOCS (Memory Object Control State) registers */
-#define GEN9_LNCFCMOCS0 0xb020 /* L3 Cache Control base */
+#define GEN9_LNCFCMOCS(i) _MMIO(0xb020 + (i) * 4) /* L3 Cache Control */
-#define GEN9_GFX_MOCS_0 0xc800 /* Graphics MOCS base register*/
-#define GEN9_MFX0_MOCS_0 0xc900 /* Media 0 MOCS base register*/
-#define GEN9_MFX1_MOCS_0 0xca00 /* Media 1 MOCS base register*/
-#define GEN9_VEBOX_MOCS_0 0xcb00 /* Video MOCS base register*/
-#define GEN9_BLT_MOCS_0 0xcc00 /* Blitter MOCS base register*/
+#define GEN9_GFX_MOCS(i) _MMIO(0xc800 + (i) * 4) /* Graphics MOCS registers */
+#define GEN9_MFX0_MOCS(i) _MMIO(0xc900 + (i) * 4) /* Media 0 MOCS registers */
+#define GEN9_MFX1_MOCS(i) _MMIO(0xca00 + (i) * 4) /* Media 1 MOCS registers */
+#define GEN9_VEBOX_MOCS(i) _MMIO(0xcb00 + (i) * 4) /* Video MOCS registers */
+#define GEN9_BLT_MOCS(i) _MMIO(0xcc00 + (i) * 4) /* Blitter MOCS registers */
#endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 50ce9ce2b269..f929c61f0fa2 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -35,7 +35,8 @@
#define dev_to_drm_minor(d) dev_get_drvdata((d))
#ifdef CONFIG_PM
-static u32 calc_residency(struct drm_device *dev, const u32 reg)
+static u32 calc_residency(struct drm_device *dev,
+ i915_reg_t reg)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u64 raw_time; /* 32b value may overflow during fixed point math */
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 04fe8491c8b6..52b2d409945d 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -664,7 +664,7 @@ TRACE_EVENT(i915_flip_complete,
);
TRACE_EVENT_CONDITION(i915_reg_rw,
- TP_PROTO(bool write, u32 reg, u64 val, int len, bool trace),
+ TP_PROTO(bool write, i915_reg_t reg, u64 val, int len, bool trace),
TP_ARGS(write, reg, val, len, trace),
@@ -679,7 +679,7 @@ TRACE_EVENT_CONDITION(i915_reg_rw,
TP_fast_assign(
__entry->val = (u64)val;
- __entry->reg = reg;
+ __entry->reg = i915_mmio_reg_offset(reg);
__entry->write = write;
__entry->len = len;
),
diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c
index 5eee75bff170..dea7429be4d0 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.c
+++ b/drivers/gpu/drm/i915/i915_vgpu.c
@@ -69,13 +69,13 @@ void i915_check_vgpu(struct drm_device *dev)
if (!IS_HASWELL(dev))
return;
- magic = readq(dev_priv->regs + vgtif_reg(magic));
+ magic = __raw_i915_read64(dev_priv, vgtif_reg(magic));
if (magic != VGT_MAGIC)
return;
version = INTEL_VGT_IF_VERSION_ENCODE(
- readw(dev_priv->regs + vgtif_reg(version_major)),
- readw(dev_priv->regs + vgtif_reg(version_minor)));
+ __raw_i915_read16(dev_priv, vgtif_reg(version_major)),
+ __raw_i915_read16(dev_priv, vgtif_reg(version_minor)));
if (version != INTEL_VGT_IF_VERSION) {
DRM_INFO("VGT interface version mismatch!\n");
return;
diff --git a/drivers/gpu/drm/i915/i915_vgpu.h b/drivers/gpu/drm/i915/i915_vgpu.h
index 21c97f44d637..3c83b47b5f69 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.h
+++ b/drivers/gpu/drm/i915/i915_vgpu.h
@@ -92,14 +92,10 @@ struct vgt_if {
uint32_t g2v_notify;
uint32_t rsv6[7];
- uint32_t pdp0_lo;
- uint32_t pdp0_hi;
- uint32_t pdp1_lo;
- uint32_t pdp1_hi;
- uint32_t pdp2_lo;
- uint32_t pdp2_hi;
- uint32_t pdp3_lo;
- uint32_t pdp3_hi;
+ struct {
+ uint32_t lo;
+ uint32_t hi;
+ } pdp[4];
uint32_t execlist_context_descriptor_lo;
uint32_t execlist_context_descriptor_hi;
@@ -108,7 +104,7 @@ struct vgt_if {
} __packed;
#define vgtif_reg(x) \
- (VGT_PVINFO_PAGE + (long)&((struct vgt_if *)NULL)->x)
+ _MMIO((VGT_PVINFO_PAGE + (long)&((struct vgt_if *)NULL)->x))
/* vGPU display status to be used by the host side */
#define VGT_DRV_DISPLAY_NOT_READY 0
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index f1975f267710..643f342de33b 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -94,6 +94,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
__drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base);
crtc_state->update_pipe = false;
+ crtc_state->disable_lp_wm = false;
return &crtc_state->base;
}
@@ -205,8 +206,6 @@ int intel_atomic_setup_scalers(struct drm_device *dev,
* but since this plane is unchanged just do the
* minimum required validation.
*/
- if (plane->type == DRM_PLANE_TYPE_PRIMARY)
- intel_crtc->atomic.wait_for_flips = true;
crtc_state->base.planes_changed = true;
}
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index a11980696595..c6bb0fc1edfb 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -84,6 +84,7 @@ intel_plane_duplicate_state(struct drm_plane *plane)
state = &intel_state->base;
__drm_atomic_helper_plane_duplicate_state(plane, state);
+ intel_state->wait_req = NULL;
return state;
}
@@ -100,6 +101,7 @@ void
intel_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
{
+ WARN_ON(state && to_intel_plane_state(state)->wait_req);
drm_atomic_helper_plane_destroy_state(plane, state);
}
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 4dccd9b003a1..de465f2876d1 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -161,9 +161,9 @@ static bool audio_rate_need_prog(struct intel_crtc *crtc,
}
static bool intel_eld_uptodate(struct drm_connector *connector,
- int reg_eldv, uint32_t bits_eldv,
- int reg_elda, uint32_t bits_elda,
- int reg_edid)
+ i915_reg_t reg_eldv, uint32_t bits_eldv,
+ i915_reg_t reg_elda, uint32_t bits_elda,
+ i915_reg_t reg_edid)
{
struct drm_i915_private *dev_priv = connector->dev->dev_private;
uint8_t *eld = connector->eld;
@@ -364,8 +364,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder)
enum port port = intel_dig_port->port;
enum pipe pipe = intel_crtc->pipe;
uint32_t tmp, eldv;
- int aud_config;
- int aud_cntrl_st2;
+ i915_reg_t aud_config, aud_cntrl_st2;
DRM_DEBUG_KMS("Disable audio codec on port %c, pipe %c\n",
port_name(port), pipe_name(pipe));
@@ -416,10 +415,7 @@ static void ilk_audio_codec_enable(struct drm_connector *connector,
uint32_t eldv;
uint32_t tmp;
int len, i;
- int hdmiw_hdmiedid;
- int aud_config;
- int aud_cntl_st;
- int aud_cntrl_st2;
+ i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2;
DRM_DEBUG_KMS("Enable audio codec on port %c, pipe %c, %u bytes ELD\n",
port_name(port), pipe_name(pipe), drm_eld_size(eld));
@@ -525,6 +521,10 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
dev_priv->display.audio_codec_enable(connector, intel_encoder,
adjusted_mode);
+ mutex_lock(&dev_priv->av_mutex);
+ intel_dig_port->audio_connector = connector;
+ mutex_unlock(&dev_priv->av_mutex);
+
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
}
@@ -548,6 +548,10 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
if (dev_priv->display.audio_codec_disable)
dev_priv->display.audio_codec_disable(intel_encoder);
+ mutex_lock(&dev_priv->av_mutex);
+ intel_dig_port->audio_connector = NULL;
+ mutex_unlock(&dev_priv->av_mutex);
+
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
}
@@ -591,7 +595,7 @@ static void i915_audio_component_codec_wake_override(struct device *dev,
struct drm_i915_private *dev_priv = dev_to_i915(dev);
u32 tmp;
- if (!IS_SKYLAKE(dev_priv))
+ if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv))
return;
/*
@@ -632,44 +636,40 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
int port, int rate)
{
struct drm_i915_private *dev_priv = dev_to_i915(dev);
- struct drm_device *drm_dev = dev_priv->dev;
struct intel_encoder *intel_encoder;
- struct intel_digital_port *intel_dig_port;
struct intel_crtc *crtc;
struct drm_display_mode *mode;
struct i915_audio_component *acomp = dev_priv->audio_component;
- enum pipe pipe = -1;
+ enum pipe pipe = INVALID_PIPE;
u32 tmp;
int n;
+ int err = 0;
- /* HSW, BDW SKL need this fix */
+ /* HSW, BDW, SKL, KBL need this fix */
if (!IS_SKYLAKE(dev_priv) &&
- !IS_BROADWELL(dev_priv) &&
- !IS_HASWELL(dev_priv))
+ !IS_KABYLAKE(dev_priv) &&
+ !IS_BROADWELL(dev_priv) &&
+ !IS_HASWELL(dev_priv))
return 0;
mutex_lock(&dev_priv->av_mutex);
/* 1. get the pipe */
- for_each_intel_encoder(drm_dev, intel_encoder) {
- if (intel_encoder->type != INTEL_OUTPUT_HDMI)
- continue;
- intel_dig_port = enc_to_dig_port(&intel_encoder->base);
- if (port == intel_dig_port->port) {
- crtc = to_intel_crtc(intel_encoder->base.crtc);
- if (!crtc) {
- DRM_DEBUG_KMS("%s: crtc is NULL\n", __func__);
- continue;
- }
- pipe = crtc->pipe;
- break;
- }
+ intel_encoder = dev_priv->dig_port_map[port];
+ /* intel_encoder might be NULL for DP MST */
+ if (!intel_encoder || !intel_encoder->base.crtc ||
+ intel_encoder->type != INTEL_OUTPUT_HDMI) {
+ DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
+ err = -ENODEV;
+ goto unlock;
}
-
+ crtc = to_intel_crtc(intel_encoder->base.crtc);
+ pipe = crtc->pipe;
if (pipe == INVALID_PIPE) {
DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port));
- mutex_unlock(&dev_priv->av_mutex);
- return -ENODEV;
+ err = -ENODEV;
+ goto unlock;
}
+
DRM_DEBUG_KMS("pipe %c connects port %c\n",
pipe_name(pipe), port_name(port));
mode = &crtc->config->base.adjusted_mode;
@@ -682,8 +682,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
tmp = I915_READ(HSW_AUD_CFG(pipe));
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
- mutex_unlock(&dev_priv->av_mutex);
- return 0;
+ goto unlock;
}
n = audio_config_get_n(mode, rate);
@@ -693,8 +692,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
tmp = I915_READ(HSW_AUD_CFG(pipe));
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
- mutex_unlock(&dev_priv->av_mutex);
- return 0;
+ goto unlock;
}
/* 3. set the N/CTS/M */
@@ -702,8 +700,37 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
tmp = audio_config_setup_n_reg(n, tmp);
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+ unlock:
mutex_unlock(&dev_priv->av_mutex);
- return 0;
+ return err;
+}
+
+static int i915_audio_component_get_eld(struct device *dev, int port,
+ bool *enabled,
+ unsigned char *buf, int max_bytes)
+{
+ struct drm_i915_private *dev_priv = dev_to_i915(dev);
+ struct intel_encoder *intel_encoder;
+ struct intel_digital_port *intel_dig_port;
+ const u8 *eld;
+ int ret = -EINVAL;
+
+ mutex_lock(&dev_priv->av_mutex);
+ intel_encoder = dev_priv->dig_port_map[port];
+ /* intel_encoder might be NULL for DP MST */
+ if (intel_encoder) {
+ ret = 0;
+ intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+ *enabled = intel_dig_port->audio_connector != NULL;
+ if (*enabled) {
+ eld = intel_dig_port->audio_connector->eld;
+ ret = drm_eld_size(eld);
+ memcpy(buf, eld, min(max_bytes, ret));
+ }
+ }
+
+ mutex_unlock(&dev_priv->av_mutex);
+ return ret;
}
static const struct i915_audio_component_ops i915_audio_component_ops = {
@@ -713,6 +740,7 @@ static const struct i915_audio_component_ops i915_audio_component_ops = {
.codec_wake_override = i915_audio_component_codec_wake_override,
.get_cdclk_freq = i915_audio_component_get_cdclk_freq,
.sync_audio_rate = i915_audio_component_sync_audio_rate,
+ .get_eld = i915_audio_component_get_eld,
};
static int i915_audio_component_bind(struct device *i915_dev,
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 6a2c76e367a5..27b3e610e8f0 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -50,7 +50,7 @@ struct intel_crt {
* encoder's enable/disable callbacks */
struct intel_connector *connector;
bool force_hotplug_required;
- u32 adpa_reg;
+ i915_reg_t adpa_reg;
};
static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
@@ -480,12 +480,8 @@ intel_crt_load_detect(struct intel_crt *crt)
uint32_t vsample;
uint32_t vblank, vblank_start, vblank_end;
uint32_t dsl;
- uint32_t bclrpat_reg;
- uint32_t vtotal_reg;
- uint32_t vblank_reg;
- uint32_t vsync_reg;
- uint32_t pipeconf_reg;
- uint32_t pipe_dsl_reg;
+ i915_reg_t bclrpat_reg, vtotal_reg,
+ vblank_reg, vsync_reg, pipeconf_reg, pipe_dsl_reg;
uint8_t st00;
enum drm_connector_status status;
@@ -518,7 +514,7 @@ intel_crt_load_detect(struct intel_crt *crt)
/* Wait for next Vblank to substitue
* border color for Color info */
intel_wait_for_vblank(dev, pipe);
- st00 = I915_READ8(VGA_MSR_WRITE);
+ st00 = I915_READ8(_VGA_MSR_WRITE);
status = ((st00 & (1 << 4)) != 0) ?
connector_status_connected :
connector_status_disconnected;
@@ -563,7 +559,7 @@ intel_crt_load_detect(struct intel_crt *crt)
do {
count++;
/* Read the ST00 VGA status register */
- st00 = I915_READ8(VGA_MSR_WRITE);
+ st00 = I915_READ8(_VGA_MSR_WRITE);
if (st00 & (1 << 4))
detect++;
} while ((I915_READ(pipe_dsl_reg) == dsl));
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index 9e530a739354..6c6a6695e99c 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -47,21 +47,10 @@
MODULE_FIRMWARE(I915_CSR_SKL);
MODULE_FIRMWARE(I915_CSR_BXT);
-/*
-* SKL CSR registers for DC5 and DC6
-*/
-#define CSR_PROGRAM(i) (0x80000 + (i) * 4)
-#define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0
-#define CSR_HTP_ADDR_SKL 0x00500034
-#define CSR_SSP_BASE 0x8F074
-#define CSR_HTP_SKL 0x8F004
-#define CSR_LAST_WRITE 0x8F034
-#define CSR_LAST_WRITE_VALUE 0xc003b400
-/* MMIO address range for CSR program (0x80000 - 0x82FFF) */
+#define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 23)
+
#define CSR_MAX_FW_SIZE 0x2FFF
#define CSR_DEFAULT_FW_OFFSET 0xFFFFFFFF
-#define CSR_MMIO_START_RANGE 0x80000
-#define CSR_MMIO_END_RANGE 0x8FFFF
struct intel_css_header {
/* 0x09 for DMC */
@@ -178,166 +167,134 @@ struct stepping_info {
};
static const struct stepping_info skl_stepping_info[] = {
- {'A', '0'}, {'B', '0'}, {'C', '0'},
- {'D', '0'}, {'E', '0'}, {'F', '0'},
- {'G', '0'}, {'H', '0'}, {'I', '0'}
+ {'A', '0'}, {'B', '0'}, {'C', '0'},
+ {'D', '0'}, {'E', '0'}, {'F', '0'},
+ {'G', '0'}, {'H', '0'}, {'I', '0'}
};
-static struct stepping_info bxt_stepping_info[] = {
+static const struct stepping_info bxt_stepping_info[] = {
{'A', '0'}, {'A', '1'}, {'A', '2'},
{'B', '0'}, {'B', '1'}, {'B', '2'}
};
-static char intel_get_stepping(struct drm_device *dev)
-{
- if (IS_SKYLAKE(dev) && (dev->pdev->revision <
- ARRAY_SIZE(skl_stepping_info)))
- return skl_stepping_info[dev->pdev->revision].stepping;
- else if (IS_BROXTON(dev) && (dev->pdev->revision <
- ARRAY_SIZE(bxt_stepping_info)))
- return bxt_stepping_info[dev->pdev->revision].stepping;
- else
- return -ENODATA;
-}
-
-static char intel_get_substepping(struct drm_device *dev)
+static const struct stepping_info *intel_get_stepping_info(struct drm_device *dev)
{
- if (IS_SKYLAKE(dev) && (dev->pdev->revision <
- ARRAY_SIZE(skl_stepping_info)))
- return skl_stepping_info[dev->pdev->revision].substepping;
- else if (IS_BROXTON(dev) && (dev->pdev->revision <
- ARRAY_SIZE(bxt_stepping_info)))
- return bxt_stepping_info[dev->pdev->revision].substepping;
- else
- return -ENODATA;
-}
-
-/**
- * intel_csr_load_status_get() - to get firmware loading status.
- * @dev_priv: i915 device.
- *
- * This function helps to get the firmware loading status.
- *
- * Return: Firmware loading status.
- */
-enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv)
-{
- enum csr_state state;
+ const struct stepping_info *si;
+ unsigned int size;
+
+ if (IS_SKYLAKE(dev)) {
+ size = ARRAY_SIZE(skl_stepping_info);
+ si = skl_stepping_info;
+ } else if (IS_BROXTON(dev)) {
+ size = ARRAY_SIZE(bxt_stepping_info);
+ si = bxt_stepping_info;
+ } else {
+ return NULL;
+ }
- mutex_lock(&dev_priv->csr_lock);
- state = dev_priv->csr.state;
- mutex_unlock(&dev_priv->csr_lock);
+ if (INTEL_REVID(dev) < size)
+ return si + INTEL_REVID(dev);
- return state;
-}
-
-/**
- * intel_csr_load_status_set() - help to set firmware loading status.
- * @dev_priv: i915 device.
- * @state: enumeration of firmware loading status.
- *
- * Set the firmware loading status.
- */
-void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
- enum csr_state state)
-{
- mutex_lock(&dev_priv->csr_lock);
- dev_priv->csr.state = state;
- mutex_unlock(&dev_priv->csr_lock);
+ return NULL;
}
/**
* intel_csr_load_program() - write the firmware from memory to register.
- * @dev: drm device.
+ * @dev_priv: i915 drm device.
*
* CSR firmware is read from a .bin file and kept in internal memory one time.
* Everytime display comes back from low power state this function is called to
* copy the firmware from internal memory to registers.
*/
-void intel_csr_load_program(struct drm_device *dev)
+void intel_csr_load_program(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
u32 *payload = dev_priv->csr.dmc_payload;
uint32_t i, fw_size;
- if (!IS_GEN9(dev)) {
+ if (!IS_GEN9(dev_priv)) {
DRM_ERROR("No CSR support available for this platform\n");
return;
}
- /*
- * FIXME: Firmware gets lost on S3/S4, but not when entering system
- * standby or suspend-to-idle (which is just like forced runtime pm).
- * Unfortunately the ACPI subsystem doesn't yet give us a way to
- * differentiate this, hence figure it out with this hack.
- */
- if (I915_READ(CSR_PROGRAM(0)))
+ if (!dev_priv->csr.dmc_payload) {
+ DRM_ERROR("Tried to program CSR with empty payload\n");
return;
+ }
- mutex_lock(&dev_priv->csr_lock);
fw_size = dev_priv->csr.dmc_fw_size;
for (i = 0; i < fw_size; i++)
I915_WRITE(CSR_PROGRAM(i), payload[i]);
for (i = 0; i < dev_priv->csr.mmio_count; i++) {
I915_WRITE(dev_priv->csr.mmioaddr[i],
- dev_priv->csr.mmiodata[i]);
+ dev_priv->csr.mmiodata[i]);
}
-
- dev_priv->csr.state = FW_LOADED;
- mutex_unlock(&dev_priv->csr_lock);
}
-static void finish_csr_load(const struct firmware *fw, void *context)
+static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
+ const struct firmware *fw)
{
- struct drm_i915_private *dev_priv = context;
struct drm_device *dev = dev_priv->dev;
struct intel_css_header *css_header;
struct intel_package_header *package_header;
struct intel_dmc_header *dmc_header;
struct intel_csr *csr = &dev_priv->csr;
- char stepping = intel_get_stepping(dev);
- char substepping = intel_get_substepping(dev);
+ const struct stepping_info *stepping_info = intel_get_stepping_info(dev);
+ char stepping, substepping;
uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
uint32_t i;
uint32_t *dmc_payload;
- bool fw_loaded = false;
- if (!fw) {
- i915_firmware_load_error_print(csr->fw_path, 0);
- goto out;
- }
+ if (!fw)
+ return NULL;
- if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
+ if (!stepping_info) {
DRM_ERROR("Unknown stepping info, firmware loading failed\n");
- goto out;
+ return NULL;
}
+ stepping = stepping_info->stepping;
+ substepping = stepping_info->substepping;
+
/* Extract CSS Header information*/
css_header = (struct intel_css_header *)fw->data;
if (sizeof(struct intel_css_header) !=
- (css_header->header_len * 4)) {
+ (css_header->header_len * 4)) {
DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
- (css_header->header_len * 4));
- goto out;
+ (css_header->header_len * 4));
+ return NULL;
}
+
+ csr->version = css_header->version;
+
+ if (IS_SKYLAKE(dev) && csr->version < SKL_CSR_VERSION_REQUIRED) {
+ DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u,"
+ " please upgrade to v%u.%u or later"
+ " [https://01.org/linuxgraphics/intel-linux-graphics-firmwares].\n",
+ CSR_VERSION_MAJOR(csr->version),
+ CSR_VERSION_MINOR(csr->version),
+ CSR_VERSION_MAJOR(SKL_CSR_VERSION_REQUIRED),
+ CSR_VERSION_MINOR(SKL_CSR_VERSION_REQUIRED));
+ return NULL;
+ }
+
readcount += sizeof(struct intel_css_header);
/* Extract Package Header information*/
package_header = (struct intel_package_header *)
- &fw->data[readcount];
+ &fw->data[readcount];
if (sizeof(struct intel_package_header) !=
- (package_header->header_len * 4)) {
+ (package_header->header_len * 4)) {
DRM_ERROR("Firmware has wrong package header length %u bytes\n",
- (package_header->header_len * 4));
- goto out;
+ (package_header->header_len * 4));
+ return NULL;
}
readcount += sizeof(struct intel_package_header);
/* Search for dmc_offset to find firware binary. */
for (i = 0; i < package_header->num_entries; i++) {
if (package_header->fw_info[i].substepping == '*' &&
- stepping == package_header->fw_info[i].stepping) {
+ stepping == package_header->fw_info[i].stepping) {
dmc_offset = package_header->fw_info[i].offset;
break;
} else if (stepping == package_header->fw_info[i].stepping &&
@@ -345,12 +302,12 @@ static void finish_csr_load(const struct firmware *fw, void *context)
dmc_offset = package_header->fw_info[i].offset;
break;
} else if (package_header->fw_info[i].stepping == '*' &&
- package_header->fw_info[i].substepping == '*')
+ package_header->fw_info[i].substepping == '*')
dmc_offset = package_header->fw_info[i].offset;
}
if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
- goto out;
+ return NULL;
}
readcount += dmc_offset;
@@ -358,26 +315,26 @@ static void finish_csr_load(const struct firmware *fw, void *context)
dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
- (dmc_header->header_len));
- goto out;
+ (dmc_header->header_len));
+ return NULL;
}
readcount += sizeof(struct intel_dmc_header);
/* Cache the dmc header info. */
if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
DRM_ERROR("Firmware has wrong mmio count %u\n",
- dmc_header->mmio_count);
- goto out;
+ dmc_header->mmio_count);
+ return NULL;
}
csr->mmio_count = dmc_header->mmio_count;
for (i = 0; i < dmc_header->mmio_count; i++) {
if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE ||
- dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
+ dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
- dmc_header->mmioaddr[i]);
- goto out;
+ dmc_header->mmioaddr[i]);
+ return NULL;
}
- csr->mmioaddr[i] = dmc_header->mmioaddr[i];
+ csr->mmioaddr[i] = _MMIO(dmc_header->mmioaddr[i]);
csr->mmiodata[i] = dmc_header->mmiodata[i];
}
@@ -385,56 +342,80 @@ static void finish_csr_load(const struct firmware *fw, void *context)
nbytes = dmc_header->fw_size * 4;
if (nbytes > CSR_MAX_FW_SIZE) {
DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
- goto out;
+ return NULL;
}
csr->dmc_fw_size = dmc_header->fw_size;
- csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
- if (!csr->dmc_payload) {
+ dmc_payload = kmalloc(nbytes, GFP_KERNEL);
+ if (!dmc_payload) {
DRM_ERROR("Memory allocation failed for dmc payload\n");
- goto out;
+ return NULL;
}
- dmc_payload = csr->dmc_payload;
memcpy(dmc_payload, &fw->data[readcount], nbytes);
+ return dmc_payload;
+}
+
+static void csr_load_work_fn(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv;
+ struct intel_csr *csr;
+ const struct firmware *fw;
+ int ret;
+
+ dev_priv = container_of(work, typeof(*dev_priv), csr.work);
+ csr = &dev_priv->csr;
+
+ ret = request_firmware(&fw, dev_priv->csr.fw_path,
+ &dev_priv->dev->pdev->dev);
+ if (!fw)
+ goto out;
+
+ dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw);
+ if (!dev_priv->csr.dmc_payload)
+ goto out;
+
/* load csr program during system boot, as needed for DC states */
- intel_csr_load_program(dev);
- fw_loaded = true;
+ intel_csr_load_program(dev_priv);
- DRM_DEBUG_KMS("Finished loading %s\n", dev_priv->csr.fw_path);
out:
- if (fw_loaded)
- intel_runtime_pm_put(dev_priv);
- else
- intel_csr_load_status_set(dev_priv, FW_FAILED);
+ if (dev_priv->csr.dmc_payload) {
+ intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+
+ DRM_INFO("Finished loading %s (v%u.%u)\n",
+ dev_priv->csr.fw_path,
+ CSR_VERSION_MAJOR(csr->version),
+ CSR_VERSION_MINOR(csr->version));
+ } else {
+ DRM_ERROR("Failed to load DMC firmware, disabling rpm\n");
+ }
release_firmware(fw);
}
/**
* intel_csr_ucode_init() - initialize the firmware loading.
- * @dev: drm device.
+ * @dev_priv: i915 drm device.
*
* This function is called at the time of loading the display driver to read
* firmware from a .bin file and copied into a internal memory.
*/
-void intel_csr_ucode_init(struct drm_device *dev)
+void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_csr *csr = &dev_priv->csr;
- int ret;
- if (!HAS_CSR(dev))
+ INIT_WORK(&dev_priv->csr.work, csr_load_work_fn);
+
+ if (!HAS_CSR(dev_priv))
return;
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev_priv))
csr->fw_path = I915_CSR_SKL;
else if (IS_BROXTON(dev_priv))
csr->fw_path = I915_CSR_BXT;
else {
DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
- intel_csr_load_status_set(dev_priv, FW_FAILED);
return;
}
@@ -444,43 +425,24 @@ void intel_csr_ucode_init(struct drm_device *dev)
* Obtain a runtime pm reference, until CSR is loaded,
* to avoid entering runtime-suspend.
*/
- intel_runtime_pm_get(dev_priv);
-
- /* CSR supported for platform, load firmware */
- ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
- &dev_priv->dev->pdev->dev,
- GFP_KERNEL, dev_priv,
- finish_csr_load);
- if (ret) {
- i915_firmware_load_error_print(csr->fw_path, ret);
- intel_csr_load_status_set(dev_priv, FW_FAILED);
- }
+ intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+
+ schedule_work(&dev_priv->csr.work);
}
/**
* intel_csr_ucode_fini() - unload the CSR firmware.
- * @dev: drm device.
+ * @dev_priv: i915 drm device.
*
* Firmmware unloading includes freeing the internal momory and reset the
* firmware loading status.
*/
-void intel_csr_ucode_fini(struct drm_device *dev)
+void intel_csr_ucode_fini(struct drm_i915_private *dev_priv)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- if (!HAS_CSR(dev))
+ if (!HAS_CSR(dev_priv))
return;
- intel_csr_load_status_set(dev_priv, FW_FAILED);
- kfree(dev_priv->csr.dmc_payload);
-}
+ flush_work(&dev_priv->csr.work);
-void assert_csr_loaded(struct drm_i915_private *dev_priv)
-{
- WARN_ONCE(intel_csr_load_status_get(dev_priv) != FW_LOADED,
- "CSR is not loaded.\n");
- WARN_ONCE(!I915_READ(CSR_PROGRAM(0)),
- "CSR program storage start is NULL\n");
- WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n");
- WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
+ kfree(dev_priv->csr.dmc_payload);
}
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index a6752a61d99f..59deb0d85533 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -133,12 +133,12 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = {
{ 0x00002016, 0x000000A0, 0x0 },
{ 0x00005012, 0x0000009B, 0x0 },
{ 0x00007011, 0x00000088, 0x0 },
- { 0x00009010, 0x000000C7, 0x0 },
+ { 0x80009010, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */
{ 0x00002016, 0x0000009B, 0x0 },
{ 0x00005012, 0x00000088, 0x0 },
- { 0x00007011, 0x000000C7, 0x0 },
+ { 0x80007011, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */
{ 0x00002016, 0x000000DF, 0x0 },
- { 0x00005012, 0x000000C7, 0x0 },
+ { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */
};
/* Skylake U */
@@ -146,12 +146,12 @@ static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = {
{ 0x0000201B, 0x000000A2, 0x0 },
{ 0x00005012, 0x00000088, 0x0 },
{ 0x00007011, 0x00000087, 0x0 },
- { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost level 0x1 */
+ { 0x80009010, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */
{ 0x0000201B, 0x0000009D, 0x0 },
- { 0x00005012, 0x000000C7, 0x0 },
- { 0x00007011, 0x000000C7, 0x0 },
+ { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */
+ { 0x80007011, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */
{ 0x00002016, 0x00000088, 0x0 },
- { 0x00005012, 0x000000C7, 0x0 },
+ { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */
};
/* Skylake Y */
@@ -159,12 +159,12 @@ static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = {
{ 0x00000018, 0x000000A2, 0x0 },
{ 0x00005012, 0x00000088, 0x0 },
{ 0x00007011, 0x00000087, 0x0 },
- { 0x80009010, 0x000000C7, 0x3 }, /* Uses I_boost level 0x3 */
+ { 0x80009010, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */
{ 0x00000018, 0x0000009D, 0x0 },
- { 0x00005012, 0x000000C7, 0x0 },
- { 0x00007011, 0x000000C7, 0x0 },
+ { 0x80005012, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */
+ { 0x80007011, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */
{ 0x00000018, 0x00000088, 0x0 },
- { 0x00005012, 0x000000C7, 0x0 },
+ { 0x80005012, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */
};
/*
@@ -345,7 +345,7 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
static bool
intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port)
{
- return intel_dig_port->hdmi.hdmi_reg;
+ return i915_mmio_reg_valid(intel_dig_port->hdmi.hdmi_reg);
}
static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev,
@@ -448,7 +448,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
bxt_ddi_vswing_sequence(dev, hdmi_level, port,
INTEL_OUTPUT_HDMI);
return;
- } else if (IS_SKYLAKE(dev)) {
+ } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
ddi_translations_fdi = NULL;
ddi_translations_dp =
skl_get_buf_trans_dp(dev, &n_dp_entries);
@@ -576,7 +576,7 @@ void intel_prepare_ddi(struct drm_device *dev)
static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
enum port port)
{
- uint32_t reg = DDI_BUF_CTL(port);
+ i915_reg_t reg = DDI_BUF_CTL(port);
int i;
for (i = 0; i < 16; i++) {
@@ -931,7 +931,8 @@ static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
/* Otherwise a < c && b >= d, do nothing */
}
-static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, int reg)
+static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
+ i915_reg_t reg)
{
int refclk = LC_FREQ;
int n, p, r;
@@ -967,7 +968,7 @@ static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, int reg)
static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,
uint32_t dpll)
{
- uint32_t cfgcr1_reg, cfgcr2_reg;
+ i915_reg_t cfgcr1_reg, cfgcr2_reg;
uint32_t cfgcr1_val, cfgcr2_val;
uint32_t p0, p1, p2, dco_freq;
@@ -1112,10 +1113,10 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder,
link_clock = 270000;
break;
case PORT_CLK_SEL_WRPLL1:
- link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL1);
+ link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(0));
break;
case PORT_CLK_SEL_WRPLL2:
- link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL2);
+ link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(1));
break;
case PORT_CLK_SEL_SPLL:
pll = I915_READ(SPLL_CTL) & SPLL_PLL_FREQ_MASK;
@@ -1184,7 +1185,7 @@ void intel_ddi_clock_get(struct intel_encoder *encoder,
if (INTEL_INFO(dev)->gen <= 8)
hsw_ddi_clock_get(encoder, pipe_config);
- else if (IS_SKYLAKE(dev))
+ else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
skl_ddi_clock_get(encoder, pipe_config);
else if (IS_BROXTON(dev))
bxt_ddi_clock_get(encoder, pipe_config);
@@ -1780,7 +1781,7 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc,
struct intel_encoder *intel_encoder =
intel_ddi_get_crtc_new_encoder(crtc_state);
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
return skl_ddi_pll_select(intel_crtc, crtc_state,
intel_encoder);
else if (IS_BROXTON(dev))
@@ -1942,7 +1943,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
enum transcoder cpu_transcoder)
{
- uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
+ i915_reg_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
uint32_t val = I915_READ(reg);
val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK | TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
@@ -2097,21 +2098,21 @@ static void skl_ddi_set_iboost(struct drm_device *dev, u32 level,
iboost = dp_iboost;
} else {
ddi_translations = skl_get_buf_trans_dp(dev, &n_entries);
- iboost = ddi_translations[port].i_boost;
+ iboost = ddi_translations[level].i_boost;
}
} else if (type == INTEL_OUTPUT_EDP) {
if (dp_iboost) {
iboost = dp_iboost;
} else {
ddi_translations = skl_get_buf_trans_edp(dev, &n_entries);
- iboost = ddi_translations[port].i_boost;
+ iboost = ddi_translations[level].i_boost;
}
} else if (type == INTEL_OUTPUT_HDMI) {
if (hdmi_iboost) {
iboost = hdmi_iboost;
} else {
ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries);
- iboost = ddi_translations[port].i_boost;
+ iboost = ddi_translations[level].i_boost;
}
} else {
return;
@@ -2263,7 +2264,7 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
level = translate_signal_level(signal_levels);
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
skl_ddi_set_iboost(dev, level, port, encoder->type);
else if (IS_BROXTON(dev))
bxt_ddi_vswing_sequence(dev, level, port, encoder->type);
@@ -2271,30 +2272,21 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
return DDI_BUF_TRANS_SELECT(level);
}
-static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
+void intel_ddi_clk_select(struct intel_encoder *encoder,
+ const struct intel_crtc_state *pipe_config)
{
- struct drm_encoder *encoder = &intel_encoder->base;
- struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
- enum port port = intel_ddi_get_encoder_port(intel_encoder);
- int type = intel_encoder->type;
- int hdmi_level;
-
- if (type == INTEL_OUTPUT_EDP) {
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- intel_edp_panel_on(intel_dp);
- }
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum port port = intel_ddi_get_encoder_port(encoder);
- if (IS_SKYLAKE(dev)) {
- uint32_t dpll = crtc->config->ddi_pll_sel;
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+ uint32_t dpll = pipe_config->ddi_pll_sel;
uint32_t val;
/*
* DPLL0 is used for eDP and is the only "private" DPLL (as
* opposed to shared) on SKL
*/
- if (type == INTEL_OUTPUT_EDP) {
+ if (encoder->type == INTEL_OUTPUT_EDP) {
WARN_ON(dpll != SKL_DPLL0);
val = I915_READ(DPLL_CTRL1);
@@ -2302,7 +2294,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) |
DPLL_CTRL1_SSC(dpll) |
DPLL_CTRL1_LINK_RATE_MASK(dpll));
- val |= crtc->config->dpll_hw_state.ctrl1 << (dpll * 6);
+ val |= pipe_config->dpll_hw_state.ctrl1 << (dpll * 6);
I915_WRITE(DPLL_CTRL1, val);
POSTING_READ(DPLL_CTRL1);
@@ -2318,10 +2310,28 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
I915_WRITE(DPLL_CTRL2, val);
- } else if (INTEL_INFO(dev)->gen < 9) {
- WARN_ON(crtc->config->ddi_pll_sel == PORT_CLK_SEL_NONE);
- I915_WRITE(PORT_CLK_SEL(port), crtc->config->ddi_pll_sel);
+ } else if (INTEL_INFO(dev_priv)->gen < 9) {
+ WARN_ON(pipe_config->ddi_pll_sel == PORT_CLK_SEL_NONE);
+ I915_WRITE(PORT_CLK_SEL(port), pipe_config->ddi_pll_sel);
}
+}
+
+static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
+{
+ struct drm_encoder *encoder = &intel_encoder->base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
+ enum port port = intel_ddi_get_encoder_port(intel_encoder);
+ int type = intel_encoder->type;
+ int hdmi_level;
+
+ if (type == INTEL_OUTPUT_EDP) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ intel_edp_panel_on(intel_dp);
+ }
+
+ intel_ddi_clk_select(intel_encoder, crtc->config);
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@ -2381,7 +2391,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
intel_edp_panel_off(intel_dp);
}
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) |
DPLL_CTRL2_DDI_CLK_OFF(port)));
else if (INTEL_INFO(dev)->gen < 9)
@@ -2553,7 +2563,7 @@ static const char * const skl_ddi_pll_names[] = {
};
struct skl_dpll_regs {
- u32 ctl, cfgcr1, cfgcr2;
+ i915_reg_t ctl, cfgcr1, cfgcr2;
};
/* this array is indexed by the *shared* pll id */
@@ -2566,13 +2576,13 @@ static const struct skl_dpll_regs skl_dpll_regs[3] = {
},
{
/* DPLL 2 */
- .ctl = WRPLL_CTL1,
+ .ctl = WRPLL_CTL(0),
.cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
.cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
},
{
/* DPLL 3 */
- .ctl = WRPLL_CTL2,
+ .ctl = WRPLL_CTL(1),
.cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
.cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
},
@@ -2992,22 +3002,22 @@ void intel_ddi_pll_init(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t val = I915_READ(LCPLL_CTL);
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
skl_shared_dplls_init(dev_priv);
else if (IS_BROXTON(dev))
bxt_shared_dplls_init(dev_priv);
else
hsw_shared_dplls_init(dev_priv);
- if (IS_SKYLAKE(dev)) {
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
int cdclk_freq;
cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
dev_priv->skl_boot_cdclk = cdclk_freq;
+ if (skl_sanitize_cdclk(dev_priv))
+ DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
DRM_ERROR("LCPLL1 is disabled\n");
- else
- intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
} else if (IS_BROXTON(dev)) {
broxton_init_cdclk(dev);
broxton_ddi_phy_init(dev);
@@ -3026,11 +3036,11 @@ void intel_ddi_pll_init(struct drm_device *dev)
}
}
-void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
+void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
{
- struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
- struct intel_dp *intel_dp = &intel_dig_port->dp;
- struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *dev_priv =
+ to_i915(intel_dig_port->base.base.dev);
enum port port = intel_dig_port->port;
uint32_t val;
bool wait = false;
@@ -3285,10 +3295,25 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
intel_encoder->get_config = intel_ddi_get_config;
intel_dig_port->port = port;
+ dev_priv->dig_port_map[port] = intel_encoder;
intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
(DDI_BUF_PORT_REVERSAL |
DDI_A_4_LANES);
+ /*
+ * Bspec says that DDI_A_4_LANES is the only supported configuration
+ * for Broxton. Yet some BIOS fail to set this bit on port A if eDP
+ * wasn't lit up at boot. Force this bit on in our internal
+ * configuration so that we use the proper lane count for our
+ * calculations.
+ */
+ if (IS_BROXTON(dev) && port == PORT_A) {
+ if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) {
+ DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n");
+ intel_dig_port->saved_port_bits |= DDI_A_4_LANES;
+ }
+ }
+
intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
intel_encoder->cloneable = 0;
@@ -3302,8 +3327,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
* On BXT A0/A1, sw needs to activate DDIA HPD logic and
* interrupts to check the external panel connection.
*/
- if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0)
- && port == PORT_B)
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) && port == PORT_B)
dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port;
else
dev_priv->hotplug.irq_port[port] = intel_dig_port;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 32cf97346978..622d30c6c37f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1096,7 +1096,7 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 reg = PIPEDSL(pipe);
+ i915_reg_t reg = PIPEDSL(pipe);
u32 line1, line2;
u32 line_mask;
@@ -1136,7 +1136,7 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
enum pipe pipe = crtc->pipe;
if (INTEL_INFO(dev)->gen >= 4) {
- int reg = PIPECONF(cpu_transcoder);
+ i915_reg_t reg = PIPECONF(cpu_transcoder);
/* Wait for the Pipe State to go off */
if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
@@ -1286,7 +1286,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct drm_device *dev = dev_priv->dev;
- int pp_reg;
+ i915_reg_t pp_reg;
u32 val;
enum pipe panel_pipe = PIPE_A;
bool locked = true;
@@ -1481,8 +1481,7 @@ static bool dp_pipe_enabled(struct drm_i915_private *dev_priv,
return false;
if (HAS_PCH_CPT(dev_priv->dev)) {
- u32 trans_dp_ctl_reg = TRANS_DP_CTL(pipe);
- u32 trans_dp_ctl = I915_READ(trans_dp_ctl_reg);
+ u32 trans_dp_ctl = I915_READ(TRANS_DP_CTL(pipe));
if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel)
return false;
} else if (IS_CHERRYVIEW(dev_priv->dev)) {
@@ -1546,12 +1545,13 @@ static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv,
}
static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
- enum pipe pipe, int reg, u32 port_sel)
+ enum pipe pipe, i915_reg_t reg,
+ u32 port_sel)
{
u32 val = I915_READ(reg);
I915_STATE_WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val),
"PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
- reg, pipe_name(pipe));
+ i915_mmio_reg_offset(reg), pipe_name(pipe));
I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0
&& (val & DP_PIPEB_SELECT),
@@ -1559,12 +1559,12 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
}
static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
- enum pipe pipe, int reg)
+ enum pipe pipe, i915_reg_t reg)
{
u32 val = I915_READ(reg);
I915_STATE_WARN(hdmi_pipe_enabled(dev_priv, pipe, val),
"PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
- reg, pipe_name(pipe));
+ i915_mmio_reg_offset(reg), pipe_name(pipe));
I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0
&& (val & SDVO_PIPE_B_SELECT),
@@ -1600,7 +1600,7 @@ static void vlv_enable_pll(struct intel_crtc *crtc,
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- int reg = DPLL(crtc->pipe);
+ i915_reg_t reg = DPLL(crtc->pipe);
u32 dpll = pipe_config->dpll_hw_state.dpll;
assert_pipe_disabled(dev_priv, crtc->pipe);
@@ -1689,7 +1689,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- int reg = DPLL(crtc->pipe);
+ i915_reg_t reg = DPLL(crtc->pipe);
u32 dpll = crtc->config->dpll_hw_state.dpll;
assert_pipe_disabled(dev_priv, crtc->pipe);
@@ -1838,7 +1838,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
unsigned int expected_mask)
{
u32 port_mask;
- int dpll_reg;
+ i915_reg_t dpll_reg;
switch (dport->port) {
case PORT_B:
@@ -1963,7 +1963,8 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
struct drm_device *dev = dev_priv->dev;
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- uint32_t reg, val, pipeconf_val;
+ i915_reg_t reg;
+ uint32_t val, pipeconf_val;
/* PCH only available on ILK+ */
BUG_ON(!HAS_PCH_SPLIT(dev));
@@ -2052,7 +2053,8 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct drm_device *dev = dev_priv->dev;
- uint32_t reg, val;
+ i915_reg_t reg;
+ uint32_t val;
/* FDI relies on the transcoder */
assert_fdi_tx_disabled(dev_priv, pipe);
@@ -2069,7 +2071,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe));
- if (!HAS_PCH_IBX(dev)) {
+ if (HAS_PCH_CPT(dev)) {
/* Workaround: Clear the timing override chicken bit again. */
reg = TRANS_CHICKEN2(pipe);
val = I915_READ(reg);
@@ -2107,10 +2109,9 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe = crtc->pipe;
- enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
- pipe);
+ enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
enum pipe pch_transcoder;
- int reg;
+ i915_reg_t reg;
u32 val;
DRM_DEBUG_KMS("enabling pipe %c\n", pipe_name(pipe));
@@ -2171,7 +2172,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc)
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
enum pipe pipe = crtc->pipe;
- int reg;
+ i915_reg_t reg;
u32 val;
DRM_DEBUG_KMS("disabling pipe %c\n", pipe_name(pipe));
@@ -2270,20 +2271,20 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
fb_format_modifier, 0));
}
-static int
+static void
intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
const struct drm_plane_state *plane_state)
{
- struct intel_rotation_info *info = &view->rotation_info;
+ struct intel_rotation_info *info = &view->params.rotation_info;
unsigned int tile_height, tile_pitch;
*view = i915_ggtt_view_normal;
if (!plane_state)
- return 0;
+ return;
if (!intel_rotation_90_or_270(plane_state->rotation))
- return 0;
+ return;
*view = i915_ggtt_view_rotated;
@@ -2310,8 +2311,6 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
info->size_uv = info->width_pages_uv * info->height_pages_uv *
PAGE_SIZE;
}
-
- return 0;
}
static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
@@ -2330,9 +2329,7 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
int
intel_pin_and_fence_fb_obj(struct drm_plane *plane,
struct drm_framebuffer *fb,
- const struct drm_plane_state *plane_state,
- struct intel_engine_cs *pipelined,
- struct drm_i915_gem_request **pipelined_request)
+ const struct drm_plane_state *plane_state)
{
struct drm_device *dev = fb->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2367,9 +2364,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
return -EINVAL;
}
- ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
- if (ret)
- return ret;
+ intel_fill_fb_ggtt_view(&view, fb, plane_state);
/* Note that the w/a also requires 64 PTE of padding following the
* bo. We currently fill all unused PTE with the shadow page and so
@@ -2388,11 +2383,10 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
*/
intel_runtime_pm_get(dev_priv);
- dev_priv->mm.interruptible = false;
- ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined,
- pipelined_request, &view);
+ ret = i915_gem_object_pin_to_display_plane(obj, alignment,
+ &view);
if (ret)
- goto err_interruptible;
+ goto err_pm;
/* Install a fence for tiled scan-out. Pre-i965 always needs a
* fence, whereas 965+ only requires a fence if using
@@ -2418,14 +2412,12 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
i915_gem_object_pin_fence(obj);
}
- dev_priv->mm.interruptible = true;
intel_runtime_pm_put(dev_priv);
return 0;
err_unpin:
i915_gem_object_unpin_from_display_plane(obj, &view);
-err_interruptible:
- dev_priv->mm.interruptible = true;
+err_pm:
intel_runtime_pm_put(dev_priv);
return ret;
}
@@ -2435,12 +2427,10 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
{
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct i915_ggtt_view view;
- int ret;
WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
- ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
- WARN_ONCE(ret, "Couldn't get view from plane state!");
+ intel_fill_fb_ggtt_view(&view, fb, plane_state);
if (view.type == I915_GGTT_VIEW_NORMAL)
i915_gem_object_unpin_fence(obj);
@@ -2695,7 +2685,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
int plane = intel_crtc->plane;
unsigned long linear_offset;
u32 dspcntr;
- u32 reg = DSPCNTR(plane);
+ i915_reg_t reg = DSPCNTR(plane);
int pixel_size;
if (!visible || !fb) {
@@ -2825,7 +2815,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
int plane = intel_crtc->plane;
unsigned long linear_offset;
u32 dspcntr;
- u32 reg = DSPCNTR(plane);
+ i915_reg_t reg = DSPCNTR(plane);
int pixel_size;
if (!visible || !fb) {
@@ -2950,30 +2940,32 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
}
}
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
- struct drm_i915_gem_object *obj,
- unsigned int plane)
+u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
+ struct drm_i915_gem_object *obj,
+ unsigned int plane)
{
- const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
+ struct i915_ggtt_view view;
struct i915_vma *vma;
- unsigned char *offset;
+ u64 offset;
- if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
- view = &i915_ggtt_view_rotated;
+ intel_fill_fb_ggtt_view(&view, intel_plane->base.fb,
+ intel_plane->base.state);
- vma = i915_gem_obj_to_ggtt_view(obj, view);
+ vma = i915_gem_obj_to_ggtt_view(obj, &view);
if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
- view->type))
+ view.type))
return -1;
- offset = (unsigned char *)vma->node.start;
+ offset = vma->node.start;
if (plane == 1) {
- offset += vma->ggtt_view.rotation_info.uv_start_page *
+ offset += vma->ggtt_view.params.rotation_info.uv_start_page *
PAGE_SIZE;
}
- return (unsigned long)offset;
+ WARN_ON(upper_32_bits(offset));
+
+ return lower_32_bits(offset);
}
static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
@@ -3099,7 +3091,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
u32 tile_height, plane_offset, plane_size;
unsigned int rotation;
int x_offset, y_offset;
- unsigned long surf_addr;
+ u32 surf_addr;
struct intel_crtc_state *crtc_state = intel_crtc->config;
struct intel_plane_state *plane_state;
int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
@@ -3227,10 +3219,9 @@ static void intel_update_primary_planes(struct drm_device *dev)
struct intel_plane_state *plane_state;
drm_modeset_lock_crtc(crtc, &plane->base);
-
plane_state = to_intel_plane_state(plane->base.state);
- if (plane_state->base.fb)
+ if (crtc->state->active && plane_state->base.fb)
plane->commit_plane(&plane->base, plane_state);
drm_modeset_unlock_crtc(crtc);
@@ -3306,32 +3297,6 @@ void intel_finish_reset(struct drm_device *dev)
drm_modeset_unlock_all(dev);
}
-static void
-intel_finish_fb(struct drm_framebuffer *old_fb)
-{
- struct drm_i915_gem_object *obj = intel_fb_obj(old_fb);
- struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
- bool was_interruptible = dev_priv->mm.interruptible;
- int ret;
-
- /* Big Hammer, we also need to ensure that any pending
- * MI_WAIT_FOR_EVENT inside a user batch buffer on the
- * current scanout is retired before unpinning the old
- * framebuffer. Note that we rely on userspace rendering
- * into the buffer attached to the pipe they are waiting
- * on. If not, userspace generates a GPU hang with IPEHR
- * point to the MI_WAIT_FOR_EVENT.
- *
- * This should only fail upon a hung GPU, in which case we
- * can safely continue.
- */
- dev_priv->mm.interruptible = false;
- ret = i915_gem_object_wait_rendering(obj, true);
- dev_priv->mm.interruptible = was_interruptible;
-
- WARN_ON(ret);
-}
-
static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -3401,7 +3366,8 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+ i915_reg_t reg;
+ u32 temp;
/* enable normal train */
reg = FDI_TX_CTL(pipe);
@@ -3443,7 +3409,8 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp, tries;
+ i915_reg_t reg;
+ u32 temp, tries;
/* FDI needs bits from pipe first */
assert_pipe_enabled(dev_priv, pipe);
@@ -3543,7 +3510,8 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp, i, retry;
+ i915_reg_t reg;
+ u32 temp, i, retry;
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */
@@ -3675,7 +3643,8 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp, i, j;
+ i915_reg_t reg;
+ u32 temp, i, j;
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */
@@ -3792,8 +3761,8 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe = intel_crtc->pipe;
- u32 reg, temp;
-
+ i915_reg_t reg;
+ u32 temp;
/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
reg = FDI_RX_CTL(pipe);
@@ -3829,7 +3798,8 @@ static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc)
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+ i915_reg_t reg;
+ u32 temp;
/* Switch from PCDclk to Rawclk */
reg = FDI_RX_CTL(pipe);
@@ -3859,7 +3829,8 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+ i915_reg_t reg;
+ u32 temp;
/* disable CPU FDI tx and PCH FDI rx */
reg = FDI_TX_CTL(pipe);
@@ -3952,15 +3923,23 @@ static void page_flip_completed(struct intel_crtc *intel_crtc)
work->pending_flip_obj);
}
-void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
+static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ long ret;
WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
- if (WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
- !intel_crtc_has_pending_flip(crtc),
- 60*HZ) == 0)) {
+
+ ret = wait_event_interruptible_timeout(
+ dev_priv->pending_flip_queue,
+ !intel_crtc_has_pending_flip(crtc),
+ 60*HZ);
+
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0) {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
spin_lock_irq(&dev->event_lock);
@@ -3971,11 +3950,7 @@ void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
spin_unlock_irq(&dev->event_lock);
}
- if (crtc->primary->fb) {
- mutex_lock(&dev->struct_mutex);
- intel_finish_fb(crtc->primary->fb);
- mutex_unlock(&dev->struct_mutex);
- }
+ return 0;
}
/* Program iCLKIP clock to the desired frequency */
@@ -4135,6 +4110,22 @@ static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
}
}
+/* Return which DP Port should be selected for Transcoder DP control */
+static enum port
+intel_trans_dp_port_sel(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct intel_encoder *encoder;
+
+ for_each_encoder_on_crtc(dev, crtc, encoder) {
+ if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+ encoder->type == INTEL_OUTPUT_EDP)
+ return enc_to_dig_port(&encoder->base)->port;
+ }
+
+ return -1;
+}
+
/*
* Enable PCH resources required for PCH ports:
* - PCH PLLs
@@ -4149,7 +4140,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+ u32 temp;
assert_pch_transcoder_disabled(dev_priv, pipe);
@@ -4196,8 +4187,10 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
/* For PCH DP, enable TRANS_DP_CTL */
if (HAS_PCH_CPT(dev) && intel_crtc->config->has_dp_encoder) {
+ const struct drm_display_mode *adjusted_mode =
+ &intel_crtc->config->base.adjusted_mode;
u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
- reg = TRANS_DP_CTL(pipe);
+ i915_reg_t reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg);
temp &= ~(TRANS_DP_PORT_SEL_MASK |
TRANS_DP_SYNC_MASK |
@@ -4205,19 +4198,19 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
temp |= TRANS_DP_OUTPUT_ENABLE;
temp |= bpc << 9; /* same format but at 11:9 */
- if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
+ if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
- if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
+ if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
temp |= TRANS_DP_VSYNC_ACTIVE_HIGH;
switch (intel_trans_dp_port_sel(crtc)) {
- case PCH_DP_B:
+ case PORT_B:
temp |= TRANS_DP_PORT_SEL_B;
break;
- case PCH_DP_C:
+ case PORT_C:
temp |= TRANS_DP_PORT_SEL_C;
break;
- case PCH_DP_D:
+ case PORT_D:
temp |= TRANS_DP_PORT_SEL_D;
break;
default:
@@ -4357,7 +4350,7 @@ static void intel_shared_dpll_commit(struct drm_atomic_state *state)
static void cpt_verify_modeset(struct drm_device *dev, int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- int dslreg = PIPEDSL(pipe);
+ i915_reg_t dslreg = PIPEDSL(pipe);
u32 temp;
temp = I915_READ(dslreg);
@@ -4667,7 +4660,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
}
for (i = 0; i < 256; i++) {
- u32 palreg;
+ i915_reg_t palreg;
if (HAS_GMCH_DISPLAY(dev))
palreg = PALETTE(pipe, i);
@@ -4746,9 +4739,9 @@ intel_post_enable_primary(struct drm_crtc *crtc)
if (IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
- /* Underruns don't raise interrupts, so check manually. */
- if (HAS_GMCH_DISPLAY(dev))
- i9xx_check_fifo_underruns(dev_priv);
+ /* Underruns don't always raise interrupts, so check manually. */
+ intel_check_cpu_fifo_underruns(dev_priv);
+ intel_check_pch_fifo_underruns(dev_priv);
}
/**
@@ -4807,7 +4800,6 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_plane *plane;
if (atomic->wait_vblank)
intel_wait_for_vblank(dev, crtc->pipe);
@@ -4826,10 +4818,6 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
if (atomic->post_enable_primary)
intel_post_enable_primary(&crtc->base);
- drm_for_each_plane_mask(plane, dev, atomic->update_sprite_watermarks)
- intel_update_sprite_watermarks(plane, &crtc->base,
- 0, 0, 0, false, false);
-
memset(atomic, 0, sizeof(*atomic));
}
@@ -4838,20 +4826,6 @@ static void intel_pre_plane_update(struct intel_crtc *crtc)
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
- struct drm_plane *p;
-
- /* Track fb's for any planes being disabled */
- drm_for_each_plane_mask(p, dev, atomic->disabled_planes) {
- struct intel_plane *plane = to_intel_plane(p);
-
- mutex_lock(&dev->struct_mutex);
- i915_gem_track_fb(intel_fb_obj(plane->base.fb), NULL,
- plane->frontbuffer_bit);
- mutex_unlock(&dev->struct_mutex);
- }
-
- if (atomic->wait_for_flips)
- intel_crtc_wait_for_pending_flips(&crtc->base);
if (atomic->disable_fbc)
intel_fbc_disable_crtc(crtc);
@@ -4900,6 +4874,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
return;
if (intel_crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
+
+ if (intel_crtc->config->has_pch_encoder)
intel_prepare_shared_dpll(intel_crtc);
if (intel_crtc->config->has_dp_encoder)
@@ -4917,7 +4894,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true;
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
- intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable)
@@ -4955,6 +4931,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
if (HAS_PCH_CPT(dev))
cpt_verify_modeset(dev, intel_crtc->pipe);
+
+ /* Must wait for vblank to avoid spurious PCH FIFO underruns */
+ if (intel_crtc->config->has_pch_encoder)
+ intel_wait_for_vblank(dev, pipe);
+ intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
}
/* IPS only exists on ULT machines and is tied to pipe A. */
@@ -4977,6 +4958,10 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
if (WARN_ON(intel_crtc->active))
return;
+ if (intel_crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
+ false);
+
if (intel_crtc_to_shared_dpll(intel_crtc))
intel_enable_shared_dpll(intel_crtc);
@@ -5009,11 +4994,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
encoder->pre_enable(encoder);
}
- if (intel_crtc->config->has_pch_encoder) {
- intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
- true);
+ if (intel_crtc->config->has_pch_encoder)
dev_priv->display.fdi_link_train(crtc);
- }
if (!is_dsi)
intel_ddi_enable_pipe_clock(intel_crtc);
@@ -5050,6 +5032,10 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_opregion_notify_encoder(encoder, true);
}
+ if (intel_crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
+ true);
+
/* If we change the relative order between pipe/planes enabling, we need
* to change the workaround. */
hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
@@ -5081,7 +5067,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *encoder;
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+
+ if (intel_crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->disable(encoder);
@@ -5089,9 +5077,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
drm_crtc_vblank_off(crtc);
assert_vblank_disabled(crtc);
- if (intel_crtc->config->has_pch_encoder)
- intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
-
intel_disable_pipe(intel_crtc);
ironlake_pfit_disable(intel_crtc, false);
@@ -5107,6 +5092,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
ironlake_disable_pch_transcoder(dev_priv, pipe);
if (HAS_PCH_CPT(dev)) {
+ i915_reg_t reg;
+ u32 temp;
+
/* disable TRANS_DP_CTL */
reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg);
@@ -5123,6 +5111,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
ironlake_fdi_pll_disable(intel_crtc);
}
+
+ intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
}
static void haswell_crtc_disable(struct drm_crtc *crtc)
@@ -5134,6 +5124,10 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
bool is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
+ if (intel_crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
+ false);
+
for_each_encoder_on_crtc(dev, crtc, encoder) {
intel_opregion_notify_encoder(encoder, false);
encoder->disable(encoder);
@@ -5142,9 +5136,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
drm_crtc_vblank_off(crtc);
assert_vblank_disabled(crtc);
- if (intel_crtc->config->has_pch_encoder)
- intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
- false);
intel_disable_pipe(intel_crtc);
if (intel_crtc->config->dp_encoder_is_mst)
@@ -5169,6 +5160,10 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->post_disable)
encoder->post_disable(encoder);
+
+ if (intel_crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
+ true);
}
static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -5199,15 +5194,15 @@ static enum intel_display_power_domain port_to_power_domain(enum port port)
{
switch (port) {
case PORT_A:
- return POWER_DOMAIN_PORT_DDI_A_4_LANES;
+ return POWER_DOMAIN_PORT_DDI_A_LANES;
case PORT_B:
- return POWER_DOMAIN_PORT_DDI_B_4_LANES;
+ return POWER_DOMAIN_PORT_DDI_B_LANES;
case PORT_C:
- return POWER_DOMAIN_PORT_DDI_C_4_LANES;
+ return POWER_DOMAIN_PORT_DDI_C_LANES;
case PORT_D:
- return POWER_DOMAIN_PORT_DDI_D_4_LANES;
+ return POWER_DOMAIN_PORT_DDI_D_LANES;
case PORT_E:
- return POWER_DOMAIN_PORT_DDI_E_2_LANES;
+ return POWER_DOMAIN_PORT_DDI_E_LANES;
default:
MISSING_CASE(port);
return POWER_DOMAIN_PORT_OTHER;
@@ -5302,13 +5297,11 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
enum pipe pipe = intel_crtc->pipe;
unsigned long mask;
- enum transcoder transcoder;
+ enum transcoder transcoder = intel_crtc->config->cpu_transcoder;
if (!crtc->state->active)
return 0;
- transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
-
mask = BIT(POWER_DOMAIN_PIPE(pipe));
mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
if (intel_crtc->config->pch_pfit.enabled ||
@@ -5395,7 +5388,7 @@ static void intel_update_max_cdclk(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (IS_SKYLAKE(dev)) {
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
if (limit == SKL_DFSM_CDCLK_LIMIT_675)
@@ -5812,32 +5805,16 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
DRM_ERROR("DBuf power disable timeout\n");
- /*
- * DMC assumes ownership of LCPLL and will get confused if we touch it.
- */
- if (dev_priv->csr.dmc_payload) {
- /* disable DPLL0 */
- I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) &
- ~LCPLL_PLL_ENABLE);
- if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
- DRM_ERROR("Couldn't disable DPLL0\n");
- }
-
- intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+ /* disable DPLL0 */
+ I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
+ if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
+ DRM_ERROR("Couldn't disable DPLL0\n");
}
void skl_init_cdclk(struct drm_i915_private *dev_priv)
{
- u32 val;
unsigned int required_vco;
- /* enable PCH reset handshake */
- val = I915_READ(HSW_NDE_RSTWRN_OPT);
- I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE);
-
- /* enable PG1 and Misc I/O */
- intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
-
/* DPLL0 not enabled (happens on early BIOS versions) */
if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) {
/* enable DPLL0 */
@@ -5858,6 +5835,45 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
DRM_ERROR("DBuf power enable timeout\n");
}
+int skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
+{
+ uint32_t lcpll1 = I915_READ(LCPLL1_CTL);
+ uint32_t cdctl = I915_READ(CDCLK_CTL);
+ int freq = dev_priv->skl_boot_cdclk;
+
+ /*
+ * check if the pre-os intialized the display
+ * There is SWF18 scratchpad register defined which is set by the
+ * pre-os which can be used by the OS drivers to check the status
+ */
+ if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
+ goto sanitize;
+
+ /* Is PLL enabled and locked ? */
+ if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK)))
+ goto sanitize;
+
+ /* DPLL okay; verify the cdclock
+ *
+ * Noticed in some instances that the freq selection is correct but
+ * decimal part is programmed wrong from BIOS where pre-os does not
+ * enable display. Verify the same as well.
+ */
+ if (cdctl == ((cdctl & CDCLK_FREQ_SEL_MASK) | skl_cdclk_decimal(freq)))
+ /* All well; nothing to sanitize */
+ return false;
+sanitize:
+ /*
+ * As of now initialize with max cdclk till
+ * we get dynamic cdclk support
+ * */
+ dev_priv->skl_boot_cdclk = dev_priv->max_cdclk_freq;
+ skl_init_cdclk(dev_priv);
+
+ /* we did have to sanitize */
+ return true;
+}
+
/* Adjust CDclk dividers to allow high res or save power if possible */
static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
{
@@ -6322,7 +6338,8 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
return;
if (to_intel_plane_state(crtc->primary->state)->visible) {
- intel_crtc_wait_for_pending_flips(crtc);
+ WARN_ON(intel_crtc->unpin_work);
+
intel_pre_disable_primary(crtc);
intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
@@ -6642,6 +6659,15 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc,
pipe_config_supports_ips(dev_priv, pipe_config);
}
+static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
+{
+ const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+ /* GDG double wide on either pipe, otherwise pipe A only */
+ return INTEL_INFO(dev_priv)->gen < 4 &&
+ (crtc->pipe == PIPE_A || IS_I915G(dev_priv));
+}
+
static int intel_crtc_compute_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
@@ -6651,23 +6677,24 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
/* FIXME should check pixel clock limits on all platforms */
if (INTEL_INFO(dev)->gen < 4) {
- int clock_limit = dev_priv->max_cdclk_freq;
+ int clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
/*
- * Enable pixel doubling when the dot clock
+ * Enable double wide mode when the dot clock
* is > 90% of the (display) core speed.
- *
- * GDG double wide on either pipe,
- * otherwise pipe A only.
*/
- if ((crtc->pipe == PIPE_A || IS_I915G(dev)) &&
- adjusted_mode->crtc_clock > clock_limit * 9 / 10) {
+ if (intel_crtc_supports_double_wide(crtc) &&
+ adjusted_mode->crtc_clock > clock_limit) {
clock_limit *= 2;
pipe_config->double_wide = true;
}
- if (adjusted_mode->crtc_clock > clock_limit * 9 / 10)
+ if (adjusted_mode->crtc_clock > clock_limit) {
+ DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
+ adjusted_mode->crtc_clock, clock_limit,
+ yesno(pipe_config->double_wide));
return -EINVAL;
+ }
}
/*
@@ -7432,7 +7459,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe = crtc->pipe;
- int dpll_reg = DPLL(crtc->pipe);
+ i915_reg_t dpll_reg = DPLL(crtc->pipe);
enum dpio_channel port = vlv_pipe_to_channel(pipe);
u32 loopfilter, tribuf_calcntr;
u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
@@ -9350,8 +9377,8 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
I915_STATE_WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
- I915_STATE_WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
- I915_STATE_WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
+ I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
+ I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
"CPU PWM1 enabled\n");
@@ -9813,7 +9840,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
skylake_get_ddi_pll(dev_priv, port, pipe_config);
else if (IS_BROXTON(dev))
bxt_get_ddi_pll(dev_priv, port, pipe_config);
@@ -10154,20 +10181,17 @@ __intel_framebuffer_create(struct drm_device *dev,
int ret;
intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
- if (!intel_fb) {
- drm_gem_object_unreference(&obj->base);
+ if (!intel_fb)
return ERR_PTR(-ENOMEM);
- }
ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
if (ret)
goto err;
return &intel_fb->base;
+
err:
- drm_gem_object_unreference(&obj->base);
kfree(intel_fb);
-
return ERR_PTR(ret);
}
@@ -10207,6 +10231,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
struct drm_display_mode *mode,
int depth, int bpp)
{
+ struct drm_framebuffer *fb;
struct drm_i915_gem_object *obj;
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
@@ -10221,7 +10246,11 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
bpp);
mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
- return intel_framebuffer_create(dev, &mode_cmd, obj);
+ fb = intel_framebuffer_create(dev, &mode_cmd, obj);
+ if (IS_ERR(fb))
+ drm_gem_object_unreference_unlocked(&obj->base);
+
+ return fb;
}
static struct drm_framebuffer *
@@ -11124,7 +11153,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
*/
if (ring->id == RCS) {
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, DERRMR);
+ intel_ring_emit_reg(ring, DERRMR);
intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
DERRMR_PIPEB_PRI_FLIP_DONE |
DERRMR_PIPEC_PRI_FLIP_DONE));
@@ -11134,7 +11163,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
else
intel_ring_emit(ring, MI_STORE_REGISTER_MEM |
MI_SRM_LRM_GLOBAL_GTT);
- intel_ring_emit(ring, DERRMR);
+ intel_ring_emit_reg(ring, DERRMR);
intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
if (IS_GEN8(dev)) {
intel_ring_emit(ring, 0);
@@ -11179,13 +11208,14 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,
}
static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
+ unsigned int rotation,
struct intel_unpin_work *work)
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
const enum pipe pipe = intel_crtc->pipe;
- u32 ctl, stride;
+ u32 ctl, stride, tile_height;
ctl = I915_READ(PLANE_CTL(pipe, 0));
ctl &= ~PLANE_CTL_TILED_MASK;
@@ -11209,9 +11239,16 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
* The stride is either expressed as a multiple of 64 bytes chunks for
* linear buffers or in number of tiles for tiled buffers.
*/
- stride = fb->pitches[0] /
- intel_fb_stride_alignment(dev, fb->modifier[0],
- fb->pixel_format);
+ if (intel_rotation_90_or_270(rotation)) {
+ /* stride = Surface height in tiles */
+ tile_height = intel_tile_height(dev, fb->pixel_format,
+ fb->modifier[0], 0);
+ stride = DIV_ROUND_UP(fb->height, tile_height);
+ } else {
+ stride = fb->pitches[0] /
+ intel_fb_stride_alignment(dev, fb->modifier[0],
+ fb->pixel_format);
+ }
/*
* Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on
@@ -11232,10 +11269,9 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
struct intel_framebuffer *intel_fb =
to_intel_framebuffer(intel_crtc->base.primary->fb);
struct drm_i915_gem_object *obj = intel_fb->obj;
+ i915_reg_t reg = DSPCNTR(intel_crtc->plane);
u32 dspcntr;
- u32 reg;
- reg = DSPCNTR(intel_crtc->plane);
dspcntr = I915_READ(reg);
if (obj->tiling_mode != I915_TILING_NONE)
@@ -11269,7 +11305,7 @@ static void intel_do_mmio_flip(struct intel_mmio_flip *mmio_flip)
intel_pipe_update_start(crtc);
if (INTEL_INFO(mmio_flip->i915)->gen >= 9)
- skl_do_mmio_flip(crtc, work);
+ skl_do_mmio_flip(crtc, mmio_flip->rotation, work);
else
/* use_mmio_flip() retricts MMIO flips to ilk+ */
ilk_do_mmio_flip(crtc, work);
@@ -11296,10 +11332,7 @@ static void intel_mmio_flip_work_func(struct work_struct *work)
static int intel_queue_mmio_flip(struct drm_device *dev,
struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_i915_gem_object *obj,
- struct intel_engine_cs *ring,
- uint32_t flags)
+ struct drm_i915_gem_object *obj)
{
struct intel_mmio_flip *mmio_flip;
@@ -11310,6 +11343,7 @@ static int intel_queue_mmio_flip(struct drm_device *dev,
mmio_flip->i915 = to_i915(dev);
mmio_flip->req = i915_gem_request_reference(obj->last_write_req);
mmio_flip->crtc = to_intel_crtc(crtc);
+ mmio_flip->rotation = crtc->primary->state->rotation;
INIT_WORK(&mmio_flip->work, intel_mmio_flip_work_func);
schedule_work(&mmio_flip->work);
@@ -11515,9 +11549,14 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
* synchronisation, so all we want here is to pin the framebuffer
* into the display plane and skip any waits.
*/
+ if (!mmio_flip) {
+ ret = i915_gem_object_sync(obj, ring, &request);
+ if (ret)
+ goto cleanup_pending;
+ }
+
ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
- crtc->primary->state,
- mmio_flip ? i915_gem_request_get_ring(obj->last_write_req) : ring, &request);
+ crtc->primary->state);
if (ret)
goto cleanup_pending;
@@ -11526,8 +11565,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
work->gtt_offset += intel_crtc->dspaddr_offset;
if (mmio_flip) {
- ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
- page_flip_flags);
+ ret = intel_queue_mmio_flip(dev, crtc, obj);
if (ret)
goto cleanup_unpin;
@@ -11641,18 +11679,32 @@ retry:
static bool intel_wm_need_update(struct drm_plane *plane,
struct drm_plane_state *state)
{
- /* Update watermarks on tiling changes. */
+ struct intel_plane_state *new = to_intel_plane_state(state);
+ struct intel_plane_state *cur = to_intel_plane_state(plane->state);
+
+ /* Update watermarks on tiling or size changes. */
if (!plane->state->fb || !state->fb ||
plane->state->fb->modifier[0] != state->fb->modifier[0] ||
- plane->state->rotation != state->rotation)
- return true;
-
- if (plane->state->crtc_w != state->crtc_w)
+ plane->state->rotation != state->rotation ||
+ drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
+ drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
+ drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
+ drm_rect_height(&new->dst) != drm_rect_height(&cur->dst))
return true;
return false;
}
+static bool needs_scaling(struct intel_plane_state *state)
+{
+ int src_w = drm_rect_width(&state->src) >> 16;
+ int src_h = drm_rect_height(&state->src) >> 16;
+ int dst_w = drm_rect_width(&state->dst);
+ int dst_h = drm_rect_height(&state->dst);
+
+ return (src_w != dst_w || src_h != dst_h);
+}
+
int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
struct drm_plane_state *plane_state)
{
@@ -11668,7 +11720,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
bool mode_changed = needs_modeset(crtc_state);
bool was_crtc_enabled = crtc->state->active;
bool is_crtc_enabled = crtc_state->active;
-
bool turn_off, turn_on, visible, was_visible;
struct drm_framebuffer *fb = plane_state->fb;
@@ -11681,14 +11732,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
return ret;
}
- /*
- * Disabling a plane is always okay; we just need to update
- * fb tracking in a special way since cleanup_fb() won't
- * get called by the plane helpers.
- */
- if (old_plane_state->base.fb && !fb)
- intel_crtc->atomic.disabled_planes |= 1 << i;
-
was_visible = old_plane_state->visible;
visible = to_intel_plane_state(plane_state)->visible;
@@ -11738,7 +11781,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
switch (plane->type) {
case DRM_PLANE_TYPE_PRIMARY:
- intel_crtc->atomic.wait_for_flips = true;
intel_crtc->atomic.pre_disable_primary = turn_off;
intel_crtc->atomic.post_enable_primary = turn_on;
@@ -11786,11 +11828,23 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
case DRM_PLANE_TYPE_CURSOR:
break;
case DRM_PLANE_TYPE_OVERLAY:
- if (turn_off && !mode_changed) {
+ /*
+ * WaCxSRDisabledForSpriteScaling:ivb
+ *
+ * cstate->update_wm was already set above, so this flag will
+ * take effect when we commit and program watermarks.
+ */
+ if (IS_IVYBRIDGE(dev) &&
+ needs_scaling(to_intel_plane_state(plane_state)) &&
+ !needs_scaling(old_plane_state)) {
+ to_intel_crtc_state(crtc_state)->disable_lp_wm = true;
+ } else if (turn_off && !mode_changed) {
intel_crtc->atomic.wait_vblank = true;
intel_crtc->atomic.update_sprite_watermarks |=
1 << i;
}
+
+ break;
}
return 0;
}
@@ -11875,6 +11929,12 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
}
ret = 0;
+ if (dev_priv->display.compute_pipe_wm) {
+ ret = dev_priv->display.compute_pipe_wm(intel_crtc, state);
+ if (ret)
+ return ret;
+ }
+
if (INTEL_INFO(dev)->gen >= 9) {
if (mode_changed)
ret = skl_update_scaler_crtc(pipe_config);
@@ -12064,7 +12124,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
pipe_config->dpll_hw_state.pll9,
pipe_config->dpll_hw_state.pll10,
pipe_config->dpll_hw_state.pcsdw12);
- } else if (IS_SKYLAKE(dev)) {
+ } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: "
"ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
pipe_config->ddi_pll_sel,
@@ -12322,6 +12382,18 @@ intel_modeset_update_crtc_state(struct drm_atomic_state *state)
crtc->hwmode = crtc->state->adjusted_mode;
else
crtc->hwmode.crtc_clock = 0;
+
+ /*
+ * Update legacy state to satisfy fbc code. This can
+ * be removed when fbc uses the atomic state.
+ */
+ if (drm_atomic_get_existing_plane_state(state, crtc->primary)) {
+ struct drm_plane_state *plane_state = crtc->primary->state;
+
+ crtc->primary->fb = plane_state->fb;
+ crtc->x = plane_state->src_x >> 16;
+ crtc->y = plane_state->src_y >> 16;
+ }
}
}
@@ -12347,7 +12419,7 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2)
list_for_each_entry((intel_crtc), \
&(dev)->mode_config.crtc_list, \
base.head) \
- if (mask & (1 <<(intel_crtc)->pipe))
+ for_each_if (mask & (1 <<(intel_crtc)->pipe))
static bool
intel_compare_m_n(unsigned int m, unsigned int n,
@@ -13085,6 +13157,45 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
return 0;
}
+/*
+ * Handle calculation of various watermark data at the end of the atomic check
+ * phase. The code here should be run after the per-crtc and per-plane 'check'
+ * handlers to ensure that all derived state has been updated.
+ */
+static void calc_watermark_data(struct drm_atomic_state *state)
+{
+ struct drm_device *dev = state->dev;
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *cstate;
+ struct drm_plane *plane;
+ struct drm_plane_state *pstate;
+
+ /*
+ * Calculate watermark configuration details now that derived
+ * plane/crtc state is all properly updated.
+ */
+ drm_for_each_crtc(crtc, dev) {
+ cstate = drm_atomic_get_existing_crtc_state(state, crtc) ?:
+ crtc->state;
+
+ if (cstate->active)
+ intel_state->wm_config.num_pipes_active++;
+ }
+ drm_for_each_legacy_plane(plane, dev) {
+ pstate = drm_atomic_get_existing_plane_state(state, plane) ?:
+ plane->state;
+
+ if (!to_intel_plane_state(pstate)->visible)
+ continue;
+
+ intel_state->wm_config.sprites_enabled = true;
+ if (pstate->crtc_w != pstate->src_w >> 16 ||
+ pstate->crtc_h != pstate->src_h >> 16)
+ intel_state->wm_config.sprites_scaled = true;
+ }
+}
+
/**
* intel_atomic_check - validate state object
* @dev: drm device
@@ -13093,6 +13204,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
static int intel_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
int ret, i;
@@ -13160,10 +13272,81 @@ static int intel_atomic_check(struct drm_device *dev,
if (ret)
return ret;
} else
- to_intel_atomic_state(state)->cdclk =
- to_i915(state->dev)->cdclk_freq;
+ intel_state->cdclk = to_i915(state->dev)->cdclk_freq;
- return drm_atomic_helper_check_planes(state->dev, state);
+ ret = drm_atomic_helper_check_planes(state->dev, state);
+ if (ret)
+ return ret;
+
+ calc_watermark_data(state);
+
+ return 0;
+}
+
+static int intel_atomic_prepare_commit(struct drm_device *dev,
+ struct drm_atomic_state *state,
+ bool async)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_plane_state *plane_state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ int i, ret;
+
+ if (async) {
+ DRM_DEBUG_KMS("i915 does not yet support async commit\n");
+ return -EINVAL;
+ }
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ ret = intel_crtc_wait_for_pending_flips(crtc);
+ if (ret)
+ return ret;
+
+ if (atomic_read(&to_intel_crtc(crtc)->unpin_work_count) >= 2)
+ flush_workqueue(dev_priv->wq);
+ }
+
+ ret = mutex_lock_interruptible(&dev->struct_mutex);
+ if (ret)
+ return ret;
+
+ ret = drm_atomic_helper_prepare_planes(dev, state);
+ if (!ret && !async && !i915_reset_in_progress(&dev_priv->gpu_error)) {
+ u32 reset_counter;
+
+ reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
+ mutex_unlock(&dev->struct_mutex);
+
+ for_each_plane_in_state(state, plane, plane_state, i) {
+ struct intel_plane_state *intel_plane_state =
+ to_intel_plane_state(plane_state);
+
+ if (!intel_plane_state->wait_req)
+ continue;
+
+ ret = __i915_wait_request(intel_plane_state->wait_req,
+ reset_counter, true,
+ NULL, NULL);
+
+ /* Swallow -EIO errors to allow updates during hw lockup. */
+ if (ret == -EIO)
+ ret = 0;
+
+ if (ret)
+ break;
+ }
+
+ if (!ret)
+ return 0;
+
+ mutex_lock(&dev->struct_mutex);
+ drm_atomic_helper_cleanup_planes(dev, state);
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
}
/**
@@ -13187,22 +13370,20 @@ static int intel_atomic_commit(struct drm_device *dev,
bool async)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
int ret = 0;
int i;
bool any_ms = false;
- if (async) {
- DRM_DEBUG_KMS("i915 does not yet support async commit\n");
- return -EINVAL;
- }
-
- ret = drm_atomic_helper_prepare_planes(dev, state);
- if (ret)
+ ret = intel_atomic_prepare_commit(dev, state, async);
+ if (ret) {
+ DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
return ret;
+ }
drm_atomic_helper_swap_state(dev, state);
+ dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
for_each_crtc_in_state(state, crtc, crtc_state, i) {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -13240,6 +13421,9 @@ static int intel_atomic_commit(struct drm_device *dev,
to_intel_crtc_state(crtc->state)->update_pipe;
unsigned long put_domains = 0;
+ if (modeset)
+ intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
+
if (modeset && crtc->state->active) {
update_scanline_offset(to_intel_crtc(crtc));
dev_priv->display.crtc_enable(crtc);
@@ -13255,18 +13439,26 @@ static int intel_atomic_commit(struct drm_device *dev,
if (!modeset)
intel_pre_plane_update(intel_crtc);
- drm_atomic_helper_commit_planes_on_crtc(crtc_state);
+ if (crtc->state->active &&
+ (crtc->state->planes_changed || update_pipe))
+ drm_atomic_helper_commit_planes_on_crtc(crtc_state);
if (put_domains)
modeset_put_power_domains(dev_priv, put_domains);
intel_post_plane_update(intel_crtc);
+
+ if (modeset)
+ intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
}
/* FIXME: add subpixel order */
drm_atomic_helper_wait_for_vblanks(dev, state);
+
+ mutex_lock(&dev->struct_mutex);
drm_atomic_helper_cleanup_planes(dev, state);
+ mutex_unlock(&dev->struct_mutex);
if (any_ms)
intel_modeset_check_state(dev, state);
@@ -13435,6 +13627,8 @@ static void intel_shared_dpll_init(struct drm_device *dev)
* bits. Some older platforms need special physical address handling for
* cursor planes.
*
+ * Must be called with struct_mutex held.
+ *
* Returns 0 on success, negative error code on failure.
*/
int
@@ -13445,28 +13639,58 @@ intel_prepare_plane_fb(struct drm_plane *plane,
struct drm_framebuffer *fb = new_state->fb;
struct intel_plane *intel_plane = to_intel_plane(plane);
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
- struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
int ret = 0;
- if (!obj)
+ if (!obj && !old_obj)
return 0;
- mutex_lock(&dev->struct_mutex);
+ if (old_obj) {
+ struct drm_crtc_state *crtc_state =
+ drm_atomic_get_existing_crtc_state(new_state->state, plane->state->crtc);
+
+ /* Big Hammer, we also need to ensure that any pending
+ * MI_WAIT_FOR_EVENT inside a user batch buffer on the
+ * current scanout is retired before unpinning the old
+ * framebuffer. Note that we rely on userspace rendering
+ * into the buffer attached to the pipe they are waiting
+ * on. If not, userspace generates a GPU hang with IPEHR
+ * point to the MI_WAIT_FOR_EVENT.
+ *
+ * This should only fail upon a hung GPU, in which case we
+ * can safely continue.
+ */
+ if (needs_modeset(crtc_state))
+ ret = i915_gem_object_wait_rendering(old_obj, true);
+
+ /* Swallow -EIO errors to allow updates during hw lockup. */
+ if (ret && ret != -EIO)
+ return ret;
+ }
- if (plane->type == DRM_PLANE_TYPE_CURSOR &&
+ if (!obj) {
+ ret = 0;
+ } else if (plane->type == DRM_PLANE_TYPE_CURSOR &&
INTEL_INFO(dev)->cursor_needs_physical) {
int align = IS_I830(dev) ? 16 * 1024 : 256;
ret = i915_gem_object_attach_phys(obj, align);
if (ret)
DRM_DEBUG_KMS("failed to attach phys object\n");
} else {
- ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL, NULL);
+ ret = intel_pin_and_fence_fb_obj(plane, fb, new_state);
}
- if (ret == 0)
- i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
+ if (ret == 0) {
+ if (obj) {
+ struct intel_plane_state *plane_state =
+ to_intel_plane_state(new_state);
- mutex_unlock(&dev->struct_mutex);
+ i915_gem_request_assign(&plane_state->wait_req,
+ obj->last_write_req);
+ }
+
+ i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
+ }
return ret;
}
@@ -13477,23 +13701,35 @@ intel_prepare_plane_fb(struct drm_plane *plane,
* @fb: old framebuffer that was on plane
*
* Cleans up a framebuffer that has just been removed from a plane.
+ *
+ * Must be called with struct_mutex held.
*/
void
intel_cleanup_plane_fb(struct drm_plane *plane,
const struct drm_plane_state *old_state)
{
struct drm_device *dev = plane->dev;
- struct drm_i915_gem_object *obj = intel_fb_obj(old_state->fb);
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+ struct intel_plane_state *old_intel_state;
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
+ struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);
- if (!obj)
+ old_intel_state = to_intel_plane_state(old_state);
+
+ if (!obj && !old_obj)
return;
- if (plane->type != DRM_PLANE_TYPE_CURSOR ||
- !INTEL_INFO(dev)->cursor_needs_physical) {
- mutex_lock(&dev->struct_mutex);
+ if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
+ !INTEL_INFO(dev)->cursor_needs_physical))
intel_unpin_fb_obj(old_state->fb, old_state);
- mutex_unlock(&dev->struct_mutex);
- }
+
+ /* prepare_fb aborted? */
+ if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) ||
+ (obj && !(obj->frontbuffer_bits & intel_plane->frontbuffer_bit)))
+ i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
+
+ i915_gem_request_assign(&old_intel_state->wait_req, NULL);
+
}
int
@@ -13512,7 +13748,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk;
- if (!crtc_clock || !cdclk)
+ if (WARN_ON_ONCE(!crtc_clock || cdclk < crtc_clock))
return DRM_PLANE_HELPER_NO_SCALING;
/*
@@ -13560,18 +13796,8 @@ intel_commit_primary_plane(struct drm_plane *plane,
struct drm_framebuffer *fb = state->base.fb;
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc;
- struct drm_rect *src = &state->src;
crtc = crtc ? crtc : plane->crtc;
- intel_crtc = to_intel_crtc(crtc);
-
- plane->fb = fb;
- crtc->x = src->x1 >> 16;
- crtc->y = src->y1 >> 16;
-
- if (!crtc->state->active)
- return;
dev_priv->display.update_primary_plane(crtc, fb,
state->src.x1 >> 16,
@@ -13601,8 +13827,7 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
intel_update_watermarks(crtc);
/* Perform vblank evasion around commit operation */
- if (crtc->state->active)
- intel_pipe_update_start(intel_crtc);
+ intel_pipe_update_start(intel_crtc);
if (modeset)
return;
@@ -13618,8 +13843,7 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- if (crtc->state->active)
- intel_pipe_update_end(intel_crtc);
+ intel_pipe_update_end(intel_crtc);
}
/**
@@ -14087,7 +14311,7 @@ static void intel_setup_outputs(struct drm_device *dev)
*/
found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
/* WaIgnoreDDIAStrap: skl */
- if (found || IS_SKYLAKE(dev))
+ if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
intel_ddi_init(dev, PORT_A);
/* DDI B, C and D detection is indicated by the SFUSE_STRAP
@@ -14103,7 +14327,7 @@ static void intel_setup_outputs(struct drm_device *dev)
/*
* On SKL we don't have a way to detect DDI-E so we rely on VBT.
*/
- if (IS_SKYLAKE(dev) &&
+ if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
(dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
@@ -14118,7 +14342,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
/* PCH SDVOB multiplex with HDMIB */
- found = intel_sdvo_init(dev, PCH_SDVOB, true);
+ found = intel_sdvo_init(dev, PCH_SDVOB, PORT_B);
if (!found)
intel_hdmi_init(dev, PCH_HDMIB, PORT_B);
if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
@@ -14174,7 +14398,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
DRM_DEBUG_KMS("probing SDVOB\n");
- found = intel_sdvo_init(dev, GEN3_SDVOB, true);
+ found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B);
if (!found && IS_G4X(dev)) {
DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
@@ -14188,7 +14412,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
DRM_DEBUG_KMS("probing SDVOC\n");
- found = intel_sdvo_init(dev, GEN3_SDVOC, false);
+ found = intel_sdvo_init(dev, GEN3_SDVOC, PORT_C);
}
if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) {
@@ -14454,8 +14678,9 @@ static int intel_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
intel_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
- struct drm_mode_fb_cmd2 *user_mode_cmd)
+ const struct drm_mode_fb_cmd2 *user_mode_cmd)
{
+ struct drm_framebuffer *fb;
struct drm_i915_gem_object *obj;
struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
@@ -14464,7 +14689,11 @@ intel_user_framebuffer_create(struct drm_device *dev,
if (&obj->base == NULL)
return ERR_PTR(-ENOENT);
- return intel_framebuffer_create(dev, &mode_cmd, obj);
+ fb = intel_framebuffer_create(dev, &mode_cmd, obj);
+ if (IS_ERR(fb))
+ drm_gem_object_unreference_unlocked(&obj->base);
+
+ return fb;
}
#ifndef CONFIG_DRM_FBDEV_EMULATION
@@ -14549,7 +14778,7 @@ static void intel_init_display(struct drm_device *dev)
}
/* Returns the core display clock speed */
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
dev_priv->display.get_display_clock_speed =
skylake_get_display_clock_speed;
else if (IS_BROXTON(dev))
@@ -14838,7 +15067,7 @@ static void i915_disable_vga(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u8 sr1;
- u32 vga_reg = i915_vgacntrl_reg(dev);
+ i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
/* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
@@ -14954,9 +15183,6 @@ void intel_modeset_init(struct drm_device *dev)
i915_disable_vga(dev);
intel_setup_outputs(dev);
- /* Just in case the BIOS is doing something questionable. */
- intel_fbc_disable(dev_priv);
-
drm_modeset_lock_all(dev);
intel_modeset_setup_hw_state(dev);
drm_modeset_unlock_all(dev);
@@ -15043,10 +15269,9 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 reg;
+ i915_reg_t reg = PIPECONF(crtc->config->cpu_transcoder);
/* Clear any frame start delays used for debugging left by the BIOS */
- reg = PIPECONF(crtc->config->cpu_transcoder);
I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
/* restore vblank interrupts to correct state */
@@ -15200,7 +15425,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
void i915_redisable_vga_power_on(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 vga_reg = i915_vgacntrl_reg(dev);
+ i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
@@ -15239,7 +15464,7 @@ static void readout_plane_state(struct intel_crtc *crtc)
struct intel_plane_state *plane_state =
to_intel_plane_state(primary->state);
- plane_state->visible =
+ plane_state->visible = crtc->active &&
primary_get_hw_state(to_intel_plane(primary));
if (plane_state->visible)
@@ -15496,8 +15721,7 @@ void intel_modeset_gem_init(struct drm_device *dev)
mutex_lock(&dev->struct_mutex);
ret = intel_pin_and_fence_fb_obj(c->primary,
c->primary->fb,
- c->primary->state,
- NULL, NULL);
+ c->primary->state);
mutex_unlock(&dev->struct_mutex);
if (ret) {
DRM_ERROR("failed to pin boot fb on pipe %d\n",
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 78b8ec84d576..e1456ead5c53 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -541,7 +541,8 @@ void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
}
}
-static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
+static i915_reg_t
+_pp_ctrl_reg(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -553,7 +554,8 @@ static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
return VLV_PIPE_PP_CONTROL(vlv_power_sequencer_pipe(intel_dp));
}
-static u32 _pp_stat_reg(struct intel_dp *intel_dp)
+static i915_reg_t
+_pp_stat_reg(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -582,7 +584,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
if (IS_VALLEYVIEW(dev)) {
enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
- u32 pp_ctrl_reg, pp_div_reg;
+ i915_reg_t pp_ctrl_reg, pp_div_reg;
u32 pp_div;
pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
@@ -652,7 +654,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
+ i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg;
uint32_t status;
bool done;
@@ -750,7 +752,7 @@ static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp,
else
precharge = 5;
- if (IS_BROADWELL(dev) && intel_dp->aux_ch_ctl_reg == DPA_AUX_CH_CTL)
+ if (IS_BROADWELL(dev) && intel_dig_port->port == PORT_A)
timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
else
timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
@@ -789,8 +791,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
- uint32_t ch_data = ch_ctl + 4;
+ i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg;
uint32_t aux_clock_divider;
int i, ret, recv_bytes;
uint32_t status;
@@ -854,7 +855,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
for (try = 0; try < 5; try++) {
/* Load the send data into the aux channel data registers */
for (i = 0; i < send_bytes; i += 4)
- I915_WRITE(ch_data + i,
+ I915_WRITE(intel_dp->aux_ch_data_reg[i >> 2],
intel_dp_pack_aux(send + i,
send_bytes - i));
@@ -918,7 +919,7 @@ done:
recv_bytes = recv_size;
for (i = 0; i < recv_bytes; i += 4)
- intel_dp_unpack_aux(I915_READ(ch_data + i),
+ intel_dp_unpack_aux(I915_READ(intel_dp->aux_ch_data_reg[i >> 2]),
recv + i, recv_bytes - i);
ret = recv_bytes;
@@ -1005,96 +1006,206 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
return ret;
}
-static void
-intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
+static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv,
+ enum port port)
{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- enum port port = intel_dig_port->port;
- struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
- const char *name = NULL;
- uint32_t porte_aux_ctl_reg = DPA_AUX_CH_CTL;
- int ret;
+ switch (port) {
+ case PORT_B:
+ case PORT_C:
+ case PORT_D:
+ return DP_AUX_CH_CTL(port);
+ default:
+ MISSING_CASE(port);
+ return DP_AUX_CH_CTL(PORT_B);
+ }
+}
- /* On SKL we don't have Aux for port E so we rely on VBT to set
- * a proper alternate aux channel.
- */
- if (IS_SKYLAKE(dev) && port == PORT_E) {
- switch (info->alternate_aux_channel) {
- case DP_AUX_B:
- porte_aux_ctl_reg = DPB_AUX_CH_CTL;
- break;
- case DP_AUX_C:
- porte_aux_ctl_reg = DPC_AUX_CH_CTL;
- break;
- case DP_AUX_D:
- porte_aux_ctl_reg = DPD_AUX_CH_CTL;
- break;
- case DP_AUX_A:
- default:
- porte_aux_ctl_reg = DPA_AUX_CH_CTL;
- }
+static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv,
+ enum port port, int index)
+{
+ switch (port) {
+ case PORT_B:
+ case PORT_C:
+ case PORT_D:
+ return DP_AUX_CH_DATA(port, index);
+ default:
+ MISSING_CASE(port);
+ return DP_AUX_CH_DATA(PORT_B, index);
}
+}
+static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv,
+ enum port port)
+{
switch (port) {
case PORT_A:
- intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL;
- name = "DPDDC-A";
- break;
+ return DP_AUX_CH_CTL(port);
case PORT_B:
- intel_dp->aux_ch_ctl_reg = PCH_DPB_AUX_CH_CTL;
- name = "DPDDC-B";
- break;
case PORT_C:
- intel_dp->aux_ch_ctl_reg = PCH_DPC_AUX_CH_CTL;
- name = "DPDDC-C";
- break;
case PORT_D:
- intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL;
- name = "DPDDC-D";
- break;
- case PORT_E:
- intel_dp->aux_ch_ctl_reg = porte_aux_ctl_reg;
- name = "DPDDC-E";
- break;
+ return PCH_DP_AUX_CH_CTL(port);
default:
- BUG();
+ MISSING_CASE(port);
+ return DP_AUX_CH_CTL(PORT_A);
}
+}
- /*
- * The AUX_CTL register is usually DP_CTL + 0x10.
- *
- * On Haswell and Broadwell though:
- * - Both port A DDI_BUF_CTL and DDI_AUX_CTL are on the CPU
- * - Port B/C/D AUX channels are on the PCH, DDI_BUF_CTL on the CPU
- *
- * Skylake moves AUX_CTL back next to DDI_BUF_CTL, on the CPU.
- */
- if (!IS_HASWELL(dev) && !IS_BROADWELL(dev) && port != PORT_E)
- intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
+static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv,
+ enum port port, int index)
+{
+ switch (port) {
+ case PORT_A:
+ return DP_AUX_CH_DATA(port, index);
+ case PORT_B:
+ case PORT_C:
+ case PORT_D:
+ return PCH_DP_AUX_CH_DATA(port, index);
+ default:
+ MISSING_CASE(port);
+ return DP_AUX_CH_DATA(PORT_A, index);
+ }
+}
+
+/*
+ * On SKL we don't have Aux for port E so we rely
+ * on VBT to set a proper alternate aux channel.
+ */
+static enum port skl_porte_aux_port(struct drm_i915_private *dev_priv)
+{
+ const struct ddi_vbt_port_info *info =
+ &dev_priv->vbt.ddi_port_info[PORT_E];
+
+ switch (info->alternate_aux_channel) {
+ case DP_AUX_A:
+ return PORT_A;
+ case DP_AUX_B:
+ return PORT_B;
+ case DP_AUX_C:
+ return PORT_C;
+ case DP_AUX_D:
+ return PORT_D;
+ default:
+ MISSING_CASE(info->alternate_aux_channel);
+ return PORT_A;
+ }
+}
+
+static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv,
+ enum port port)
+{
+ if (port == PORT_E)
+ port = skl_porte_aux_port(dev_priv);
+
+ switch (port) {
+ case PORT_A:
+ case PORT_B:
+ case PORT_C:
+ case PORT_D:
+ return DP_AUX_CH_CTL(port);
+ default:
+ MISSING_CASE(port);
+ return DP_AUX_CH_CTL(PORT_A);
+ }
+}
+
+static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv,
+ enum port port, int index)
+{
+ if (port == PORT_E)
+ port = skl_porte_aux_port(dev_priv);
+
+ switch (port) {
+ case PORT_A:
+ case PORT_B:
+ case PORT_C:
+ case PORT_D:
+ return DP_AUX_CH_DATA(port, index);
+ default:
+ MISSING_CASE(port);
+ return DP_AUX_CH_DATA(PORT_A, index);
+ }
+}
+
+static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv,
+ enum port port)
+{
+ if (INTEL_INFO(dev_priv)->gen >= 9)
+ return skl_aux_ctl_reg(dev_priv, port);
+ else if (HAS_PCH_SPLIT(dev_priv))
+ return ilk_aux_ctl_reg(dev_priv, port);
+ else
+ return g4x_aux_ctl_reg(dev_priv, port);
+}
+
+static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv,
+ enum port port, int index)
+{
+ if (INTEL_INFO(dev_priv)->gen >= 9)
+ return skl_aux_data_reg(dev_priv, port, index);
+ else if (HAS_PCH_SPLIT(dev_priv))
+ return ilk_aux_data_reg(dev_priv, port, index);
+ else
+ return g4x_aux_data_reg(dev_priv, port, index);
+}
+
+static void intel_aux_reg_init(struct intel_dp *intel_dp)
+{
+ struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
+ enum port port = dp_to_dig_port(intel_dp)->port;
+ int i;
+
+ intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port);
+ for (i = 0; i < ARRAY_SIZE(intel_dp->aux_ch_data_reg); i++)
+ intel_dp->aux_ch_data_reg[i] = intel_aux_data_reg(dev_priv, port, i);
+}
+
+static void
+intel_dp_aux_fini(struct intel_dp *intel_dp)
+{
+ drm_dp_aux_unregister(&intel_dp->aux);
+ kfree(intel_dp->aux.name);
+}
+
+static int
+intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ enum port port = intel_dig_port->port;
+ int ret;
+
+ intel_aux_reg_init(intel_dp);
+
+ intel_dp->aux.name = kasprintf(GFP_KERNEL, "DPDDC-%c", port_name(port));
+ if (!intel_dp->aux.name)
+ return -ENOMEM;
- intel_dp->aux.name = name;
intel_dp->aux.dev = dev->dev;
intel_dp->aux.transfer = intel_dp_aux_transfer;
- DRM_DEBUG_KMS("registering %s bus for %s\n", name,
+ DRM_DEBUG_KMS("registering %s bus for %s\n",
+ intel_dp->aux.name,
connector->base.kdev->kobj.name);
ret = drm_dp_aux_register(&intel_dp->aux);
if (ret < 0) {
DRM_ERROR("drm_dp_aux_register() for %s failed (%d)\n",
- name, ret);
- return;
+ intel_dp->aux.name, ret);
+ kfree(intel_dp->aux.name);
+ return ret;
}
ret = sysfs_create_link(&connector->base.kdev->kobj,
&intel_dp->aux.ddc.dev.kobj,
intel_dp->aux.ddc.dev.kobj.name);
if (ret < 0) {
- DRM_ERROR("sysfs_create_link() for %s failed (%d)\n", name, ret);
- drm_dp_aux_unregister(&intel_dp->aux);
+ DRM_ERROR("sysfs_create_link() for %s failed (%d)\n",
+ intel_dp->aux.name, ret);
+ intel_dp_aux_fini(intel_dp);
+ return ret;
}
+
+ return 0;
}
static void
@@ -1186,10 +1297,13 @@ intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
return (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
}
-static bool intel_dp_source_supports_hbr2(struct drm_device *dev)
+bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp)
{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = dig_port->base.base.dev;
+
/* WaDisableHBR2:skl */
- if (IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0)
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_B0))
return false;
if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) ||
@@ -1200,14 +1314,16 @@ static bool intel_dp_source_supports_hbr2(struct drm_device *dev)
}
static int
-intel_dp_source_rates(struct drm_device *dev, const int **source_rates)
+intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates)
{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = dig_port->base.base.dev;
int size;
if (IS_BROXTON(dev)) {
*source_rates = bxt_rates;
size = ARRAY_SIZE(bxt_rates);
- } else if (IS_SKYLAKE(dev)) {
+ } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
*source_rates = skl_rates;
size = ARRAY_SIZE(skl_rates);
} else {
@@ -1216,7 +1332,7 @@ intel_dp_source_rates(struct drm_device *dev, const int **source_rates)
}
/* This depends on the fact that 5.4 is last value in the array */
- if (!intel_dp_source_supports_hbr2(dev))
+ if (!intel_dp_source_supports_hbr2(intel_dp))
size--;
return size;
@@ -1281,12 +1397,11 @@ static int intersect_rates(const int *source_rates, int source_len,
static int intel_dp_common_rates(struct intel_dp *intel_dp,
int *common_rates)
{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
const int *source_rates, *sink_rates;
int source_len, sink_len;
sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
- source_len = intel_dp_source_rates(dev, &source_rates);
+ source_len = intel_dp_source_rates(intel_dp, &source_rates);
return intersect_rates(source_rates, source_len,
sink_rates, sink_len,
@@ -1311,7 +1426,6 @@ static void snprintf_int_array(char *str, size_t len,
static void intel_dp_print_rates(struct intel_dp *intel_dp)
{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
const int *source_rates, *sink_rates;
int source_len, sink_len, common_len;
int common_rates[DP_MAX_SUPPORTED_RATES];
@@ -1320,7 +1434,7 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
if ((drm_debug & DRM_UT_KMS) == 0)
return;
- source_len = intel_dp_source_rates(dev, &source_rates);
+ source_len = intel_dp_source_rates(intel_dp, &source_rates);
snprintf_int_array(str, sizeof(str), source_rates, source_len);
DRM_DEBUG_KMS("source rates: %s\n", str);
@@ -1362,8 +1476,8 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
return rate_to_index(rate, intel_dp->sink_rates);
}
-static void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
- uint8_t *link_bw, uint8_t *rate_select)
+void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
+ uint8_t *link_bw, uint8_t *rate_select)
{
if (intel_dp->num_sink_rates) {
*link_bw = 0;
@@ -1423,7 +1537,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
return ret;
}
- if (!HAS_PCH_SPLIT(dev))
+ if (HAS_GMCH_DISPLAY(dev))
intel_gmch_panel_fitting(intel_crtc, pipe_config,
intel_connector->panel.fitting_mode);
else
@@ -1527,7 +1641,7 @@ found:
&pipe_config->dp_m2_n2);
}
- if (IS_SKYLAKE(dev) && is_edp(intel_dp))
+ if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && is_edp(intel_dp))
skl_edp_set_pll_config(pipe_config);
else if (IS_BROXTON(dev))
/* handled in ddi */;
@@ -1539,37 +1653,6 @@ found:
return true;
}
-static void ironlake_set_pll_cpu_edp(struct intel_dp *intel_dp)
-{
- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc);
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- u32 dpa_ctl;
-
- DRM_DEBUG_KMS("eDP PLL enable for clock %d\n",
- crtc->config->port_clock);
- dpa_ctl = I915_READ(DP_A);
- dpa_ctl &= ~DP_PLL_FREQ_MASK;
-
- if (crtc->config->port_clock == 162000) {
- /* For a long time we've carried around a ILK-DevA w/a for the
- * 160MHz clock. If we're really unlucky, it's still required.
- */
- DRM_DEBUG_KMS("160MHz cpu eDP clock, might need ilk devA w/a\n");
- dpa_ctl |= DP_PLL_FREQ_160MHZ;
- intel_dp->DP |= DP_PLL_FREQ_160MHZ;
- } else {
- dpa_ctl |= DP_PLL_FREQ_270MHZ;
- intel_dp->DP |= DP_PLL_FREQ_270MHZ;
- }
-
- I915_WRITE(DP_A, dpa_ctl);
-
- POSTING_READ(DP_A);
- udelay(500);
-}
-
void intel_dp_set_link_params(struct intel_dp *intel_dp,
const struct intel_crtc_state *pipe_config)
{
@@ -1614,9 +1697,6 @@ static void intel_dp_prepare(struct intel_encoder *encoder)
intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
intel_dp->DP |= DP_PORT_WIDTH(crtc->config->lane_count);
- if (crtc->config->has_audio)
- intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
-
/* Split out the IBX/CPU vs CPT settings */
if (IS_GEN7(dev) && port == PORT_A) {
@@ -1677,7 +1757,7 @@ static void wait_panel_status(struct intel_dp *intel_dp,
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 pp_stat_reg, pp_ctrl_reg;
+ i915_reg_t pp_stat_reg, pp_ctrl_reg;
lockdep_assert_held(&dev_priv->pps_mutex);
@@ -1767,7 +1847,7 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dev->dev_private;
enum intel_display_power_domain power_domain;
u32 pp;
- u32 pp_stat_reg, pp_ctrl_reg;
+ i915_reg_t pp_stat_reg, pp_ctrl_reg;
bool need_to_disable = !intel_dp->want_panel_vdd;
lockdep_assert_held(&dev_priv->pps_mutex);
@@ -1843,7 +1923,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
struct intel_encoder *intel_encoder = &intel_dig_port->base;
enum intel_display_power_domain power_domain;
u32 pp;
- u32 pp_stat_reg, pp_ctrl_reg;
+ i915_reg_t pp_stat_reg, pp_ctrl_reg;
lockdep_assert_held(&dev_priv->pps_mutex);
@@ -1930,7 +2010,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp;
- u32 pp_ctrl_reg;
+ i915_reg_t pp_ctrl_reg;
lockdep_assert_held(&dev_priv->pps_mutex);
@@ -1992,7 +2072,7 @@ static void edp_panel_off(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dev->dev_private;
enum intel_display_power_domain power_domain;
u32 pp;
- u32 pp_ctrl_reg;
+ i915_reg_t pp_ctrl_reg;
lockdep_assert_held(&dev_priv->pps_mutex);
@@ -2043,7 +2123,7 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp;
- u32 pp_ctrl_reg;
+ i915_reg_t pp_ctrl_reg;
/*
* If we enable the backlight right away following a panel power
@@ -2084,7 +2164,7 @@ static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp;
- u32 pp_ctrl_reg;
+ i915_reg_t pp_ctrl_reg;
if (!is_edp(intel_dp))
return;
@@ -2143,27 +2223,61 @@ static void intel_edp_backlight_power(struct intel_connector *connector,
_intel_edp_backlight_off(intel_dp);
}
+static const char *state_string(bool enabled)
+{
+ return enabled ? "on" : "off";
+}
+
+static void assert_dp_port(struct intel_dp *intel_dp, bool state)
+{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+ bool cur_state = I915_READ(intel_dp->output_reg) & DP_PORT_EN;
+
+ I915_STATE_WARN(cur_state != state,
+ "DP port %c state assertion failure (expected %s, current %s)\n",
+ port_name(dig_port->port),
+ state_string(state), state_string(cur_state));
+}
+#define assert_dp_port_disabled(d) assert_dp_port((d), false)
+
+static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state)
+{
+ bool cur_state = I915_READ(DP_A) & DP_PLL_ENABLE;
+
+ I915_STATE_WARN(cur_state != state,
+ "eDP PLL state assertion failure (expected %s, current %s)\n",
+ state_string(state), state_string(cur_state));
+}
+#define assert_edp_pll_enabled(d) assert_edp_pll((d), true)
+#define assert_edp_pll_disabled(d) assert_edp_pll((d), false)
+
static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- u32 dpa_ctl;
+ struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- assert_pipe_disabled(dev_priv,
- to_intel_crtc(crtc)->pipe);
+ assert_pipe_disabled(dev_priv, crtc->pipe);
+ assert_dp_port_disabled(intel_dp);
+ assert_edp_pll_disabled(dev_priv);
+
+ DRM_DEBUG_KMS("enabling eDP PLL for clock %d\n",
+ crtc->config->port_clock);
+
+ intel_dp->DP &= ~DP_PLL_FREQ_MASK;
+
+ if (crtc->config->port_clock == 162000)
+ intel_dp->DP |= DP_PLL_FREQ_162MHZ;
+ else
+ intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+
+ I915_WRITE(DP_A, intel_dp->DP);
+ POSTING_READ(DP_A);
+ udelay(500);
- DRM_DEBUG_KMS("\n");
- dpa_ctl = I915_READ(DP_A);
- WARN(dpa_ctl & DP_PLL_ENABLE, "dp pll on, should be off\n");
- WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n");
-
- /* We don't adjust intel_dp->DP while tearing down the link, to
- * facilitate link retraining (e.g. after hotplug). Hence clear all
- * enable bits here to ensure that we don't enable too much. */
- intel_dp->DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE);
intel_dp->DP |= DP_PLL_ENABLE;
+
I915_WRITE(DP_A, intel_dp->DP);
POSTING_READ(DP_A);
udelay(200);
@@ -2172,24 +2286,18 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- u32 dpa_ctl;
+ struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+ assert_pipe_disabled(dev_priv, crtc->pipe);
+ assert_dp_port_disabled(intel_dp);
+ assert_edp_pll_enabled(dev_priv);
- assert_pipe_disabled(dev_priv,
- to_intel_crtc(crtc)->pipe);
+ DRM_DEBUG_KMS("disabling eDP PLL\n");
- dpa_ctl = I915_READ(DP_A);
- WARN((dpa_ctl & DP_PLL_ENABLE) == 0,
- "dp pll off, should be on\n");
- WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n");
+ intel_dp->DP &= ~DP_PLL_ENABLE;
- /* We can't rely on the value tracked for the DP register in
- * intel_dp->DP because link_down must not change that (otherwise link
- * re-training will fail. */
- dpa_ctl &= ~DP_PLL_ENABLE;
- I915_WRITE(DP_A, dpa_ctl);
+ I915_WRITE(DP_A, intel_dp->DP);
POSTING_READ(DP_A);
udelay(200);
}
@@ -2258,7 +2366,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
}
DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n",
- intel_dp->output_reg);
+ i915_mmio_reg_offset(intel_dp->output_reg));
} else if (IS_CHERRYVIEW(dev)) {
*pipe = DP_PORT_TO_PIPE_CHV(tmp);
} else {
@@ -2321,7 +2429,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
intel_dp_get_m_n(crtc, pipe_config);
if (port == PORT_A) {
- if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_160MHZ)
+ if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_162MHZ)
pipe_config->port_clock = 162000;
else
pipe_config->port_clock = 270000;
@@ -2386,6 +2494,8 @@ static void ilk_post_disable_dp(struct intel_encoder *encoder)
enum port port = dp_to_dig_port(intel_dp)->port;
intel_dp_link_down(intel_dp);
+
+ /* Only ilk+ has port A */
if (port == PORT_A)
ironlake_edp_pll_off(intel_dp);
}
@@ -2545,6 +2655,8 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *crtc =
+ to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc);
/* enable with pattern 1 (as per spec) */
_intel_dp_set_link_train(intel_dp, &intel_dp->DP,
@@ -2560,6 +2672,8 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp)
* fail when the power sequencer is freshly used for this port.
*/
intel_dp->DP |= DP_PORT_EN;
+ if (crtc->config->has_audio)
+ intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
I915_WRITE(intel_dp->output_reg, intel_dp->DP);
POSTING_READ(intel_dp->output_reg);
@@ -2572,6 +2686,8 @@ static void intel_enable_dp(struct intel_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
uint32_t dp_reg = I915_READ(intel_dp->output_reg);
+ enum port port = dp_to_dig_port(intel_dp)->port;
+ enum pipe pipe = crtc->pipe;
if (WARN_ON(dp_reg & DP_PORT_EN))
return;
@@ -2583,6 +2699,17 @@ static void intel_enable_dp(struct intel_encoder *encoder)
intel_dp_enable_port(intel_dp);
+ if (port == PORT_A && IS_GEN5(dev_priv)) {
+ /*
+ * Underrun reporting for the other pipe was disabled in
+ * g4x_pre_enable_dp(). The eDP PLL and port have now been
+ * enabled, so it's now safe to re-enable underrun reporting.
+ */
+ intel_wait_for_vblank_if_active(dev_priv->dev, !pipe);
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, !pipe, true);
+ intel_set_pch_fifo_underrun_reporting(dev_priv, !pipe, true);
+ }
+
edp_panel_vdd_on(intel_dp);
edp_panel_on(intel_dp);
edp_panel_vdd_off(intel_dp, true);
@@ -2605,7 +2732,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
if (crtc->config->has_audio) {
DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
- pipe_name(crtc->pipe));
+ pipe_name(pipe));
intel_audio_codec_enable(encoder);
}
}
@@ -2628,16 +2755,29 @@ static void vlv_enable_dp(struct intel_encoder *encoder)
static void g4x_pre_enable_dp(struct intel_encoder *encoder)
{
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
- struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
+ enum port port = dp_to_dig_port(intel_dp)->port;
+ enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
intel_dp_prepare(encoder);
+ if (port == PORT_A && IS_GEN5(dev_priv)) {
+ /*
+ * We get FIFO underruns on the other pipe when
+ * enabling the CPU eDP PLL, and when enabling CPU
+ * eDP port. We could potentially avoid the PLL
+ * underrun with a vblank wait just prior to enabling
+ * the PLL, but that doesn't appear to help the port
+ * enable case. Just sweep it all under the rug.
+ */
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, !pipe, false);
+ intel_set_pch_fifo_underrun_reporting(dev_priv, !pipe, false);
+ }
+
/* Only ilk+ has port A */
- if (dport->port == PORT_A) {
- ironlake_set_pll_cpu_edp(intel_dp);
+ if (port == PORT_A)
ironlake_edp_pll_on(intel_dp);
- }
}
static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
@@ -2645,7 +2785,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = intel_dig_port->base.base.dev->dev_private;
enum pipe pipe = intel_dp->pps_pipe;
- int pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
+ i915_reg_t pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
edp_panel_vdd_off_sync(intel_dp);
@@ -3043,7 +3183,7 @@ intel_dp_dpcd_read_wake(struct drm_dp_aux *aux, unsigned int offset,
* Fetch AUX CH registers 0x202 - 0x207 which contain
* link status information
*/
-static bool
+bool
intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
{
return intel_dp_dpcd_read_wake(&intel_dp->aux,
@@ -3053,7 +3193,7 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_
}
/* These are source-specific values. */
-static uint8_t
+uint8_t
intel_dp_voltage_max(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -3076,7 +3216,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
}
-static uint8_t
+uint8_t
intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -3418,38 +3558,6 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
return 0;
}
-static void
-intel_get_adjust_train(struct intel_dp *intel_dp,
- const uint8_t link_status[DP_LINK_STATUS_SIZE])
-{
- uint8_t v = 0;
- uint8_t p = 0;
- int lane;
- uint8_t voltage_max;
- uint8_t preemph_max;
-
- for (lane = 0; lane < intel_dp->lane_count; lane++) {
- uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane);
- uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
-
- if (this_v > v)
- v = this_v;
- if (this_p > p)
- p = this_p;
- }
-
- voltage_max = intel_dp_voltage_max(intel_dp);
- if (v >= voltage_max)
- v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
-
- preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
- if (p >= preemph_max)
- p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
- for (lane = 0; lane < 4; lane++)
- intel_dp->train_set[lane] = v | p;
-}
-
static uint32_t
gen4_signal_levels(uint8_t train_set)
{
@@ -3547,13 +3655,13 @@ gen7_edp_signal_levels(uint8_t train_set)
}
}
-/* Properly updates "DP" with the correct signal levels. */
-static void
-intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
+void
+intel_dp_set_signal_levels(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
enum port port = intel_dig_port->port;
struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
uint32_t signal_levels, mask = 0;
uint8_t train_set = intel_dp->train_set[0];
@@ -3588,74 +3696,27 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
(train_set & DP_TRAIN_PRE_EMPHASIS_MASK) >>
DP_TRAIN_PRE_EMPHASIS_SHIFT);
- *DP = (*DP & ~mask) | signal_levels;
-}
+ intel_dp->DP = (intel_dp->DP & ~mask) | signal_levels;
-static bool
-intel_dp_set_link_train(struct intel_dp *intel_dp,
- uint32_t *DP,
- uint8_t dp_train_pat)
-{
- struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- struct drm_i915_private *dev_priv =
- to_i915(intel_dig_port->base.base.dev);
- uint8_t buf[sizeof(intel_dp->train_set) + 1];
- int ret, len;
-
- _intel_dp_set_link_train(intel_dp, DP, dp_train_pat);
-
- I915_WRITE(intel_dp->output_reg, *DP);
+ I915_WRITE(intel_dp->output_reg, intel_dp->DP);
POSTING_READ(intel_dp->output_reg);
-
- buf[0] = dp_train_pat;
- if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) ==
- DP_TRAINING_PATTERN_DISABLE) {
- /* don't write DP_TRAINING_LANEx_SET on disable */
- len = 1;
- } else {
- /* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */
- memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count);
- len = intel_dp->lane_count + 1;
- }
-
- ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
- buf, len);
-
- return ret == len;
-}
-
-static bool
-intel_dp_reset_link_train(struct intel_dp *intel_dp, uint32_t *DP,
- uint8_t dp_train_pat)
-{
- if (!intel_dp->train_set_valid)
- memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
- intel_dp_set_signal_levels(intel_dp, DP);
- return intel_dp_set_link_train(intel_dp, DP, dp_train_pat);
}
-static bool
-intel_dp_update_link_train(struct intel_dp *intel_dp, uint32_t *DP,
- const uint8_t link_status[DP_LINK_STATUS_SIZE])
+void
+intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
+ uint8_t dp_train_pat)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv =
to_i915(intel_dig_port->base.base.dev);
- int ret;
- intel_get_adjust_train(intel_dp, link_status);
- intel_dp_set_signal_levels(intel_dp, DP);
+ _intel_dp_set_link_train(intel_dp, &intel_dp->DP, dp_train_pat);
- I915_WRITE(intel_dp->output_reg, *DP);
+ I915_WRITE(intel_dp->output_reg, intel_dp->DP);
POSTING_READ(intel_dp->output_reg);
-
- ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
- intel_dp->train_set, intel_dp->lane_count);
-
- return ret == intel_dp->lane_count;
}
-static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
+void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev;
@@ -3686,232 +3747,6 @@ static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
DRM_ERROR("Timed out waiting for DP idle patterns\n");
}
-/* Enable corresponding port and start training pattern 1 */
-static void
-intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
-{
- struct drm_encoder *encoder = &dp_to_dig_port(intel_dp)->base.base;
- struct drm_device *dev = encoder->dev;
- int i;
- uint8_t voltage;
- int voltage_tries, loop_tries;
- uint32_t DP = intel_dp->DP;
- uint8_t link_config[2];
- uint8_t link_bw, rate_select;
-
- if (HAS_DDI(dev))
- intel_ddi_prepare_link_retrain(encoder);
-
- intel_dp_compute_rate(intel_dp, intel_dp->link_rate,
- &link_bw, &rate_select);
-
- /* Write the link configuration data */
- link_config[0] = link_bw;
- link_config[1] = intel_dp->lane_count;
- if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
- link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
- drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
- if (intel_dp->num_sink_rates)
- drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
- &rate_select, 1);
-
- link_config[0] = 0;
- link_config[1] = DP_SET_ANSI_8B10B;
- drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
-
- DP |= DP_PORT_EN;
-
- /* clock recovery */
- if (!intel_dp_reset_link_train(intel_dp, &DP,
- DP_TRAINING_PATTERN_1 |
- DP_LINK_SCRAMBLING_DISABLE)) {
- DRM_ERROR("failed to enable link training\n");
- return;
- }
-
- voltage = 0xff;
- voltage_tries = 0;
- loop_tries = 0;
- for (;;) {
- uint8_t link_status[DP_LINK_STATUS_SIZE];
-
- drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd);
- if (!intel_dp_get_link_status(intel_dp, link_status)) {
- DRM_ERROR("failed to get link status\n");
- break;
- }
-
- if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
- DRM_DEBUG_KMS("clock recovery OK\n");
- break;
- }
-
- /*
- * if we used previously trained voltage and pre-emphasis values
- * and we don't get clock recovery, reset link training values
- */
- if (intel_dp->train_set_valid) {
- DRM_DEBUG_KMS("clock recovery not ok, reset");
- /* clear the flag as we are not reusing train set */
- intel_dp->train_set_valid = false;
- if (!intel_dp_reset_link_train(intel_dp, &DP,
- DP_TRAINING_PATTERN_1 |
- DP_LINK_SCRAMBLING_DISABLE)) {
- DRM_ERROR("failed to enable link training\n");
- return;
- }
- continue;
- }
-
- /* Check to see if we've tried the max voltage */
- for (i = 0; i < intel_dp->lane_count; i++)
- if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
- break;
- if (i == intel_dp->lane_count) {
- ++loop_tries;
- if (loop_tries == 5) {
- DRM_ERROR("too many full retries, give up\n");
- break;
- }
- intel_dp_reset_link_train(intel_dp, &DP,
- DP_TRAINING_PATTERN_1 |
- DP_LINK_SCRAMBLING_DISABLE);
- voltage_tries = 0;
- continue;
- }
-
- /* Check to see if we've tried the same voltage 5 times */
- if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
- ++voltage_tries;
- if (voltage_tries == 5) {
- DRM_ERROR("too many voltage retries, give up\n");
- break;
- }
- } else
- voltage_tries = 0;
- voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
-
- /* Update training set as requested by target */
- if (!intel_dp_update_link_train(intel_dp, &DP, link_status)) {
- DRM_ERROR("failed to update link training\n");
- break;
- }
- }
-
- intel_dp->DP = DP;
-}
-
-static void
-intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
-{
- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- struct drm_device *dev = dig_port->base.base.dev;
- bool channel_eq = false;
- int tries, cr_tries;
- uint32_t DP = intel_dp->DP;
- uint32_t training_pattern = DP_TRAINING_PATTERN_2;
-
- /*
- * Training Pattern 3 for HBR2 or 1.2 devices that support it.
- *
- * Intel platforms that support HBR2 also support TPS3. TPS3 support is
- * also mandatory for downstream devices that support HBR2.
- *
- * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is
- * supported but still not enabled.
- */
- if (intel_dp_source_supports_hbr2(dev) &&
- drm_dp_tps3_supported(intel_dp->dpcd))
- training_pattern = DP_TRAINING_PATTERN_3;
- else if (intel_dp->link_rate == 540000)
- DRM_ERROR("5.4 Gbps link rate without HBR2/TPS3 support\n");
-
- /* channel equalization */
- if (!intel_dp_set_link_train(intel_dp, &DP,
- training_pattern |
- DP_LINK_SCRAMBLING_DISABLE)) {
- DRM_ERROR("failed to start channel equalization\n");
- return;
- }
-
- tries = 0;
- cr_tries = 0;
- channel_eq = false;
- for (;;) {
- uint8_t link_status[DP_LINK_STATUS_SIZE];
-
- if (cr_tries > 5) {
- DRM_ERROR("failed to train DP, aborting\n");
- break;
- }
-
- drm_dp_link_train_channel_eq_delay(intel_dp->dpcd);
- if (!intel_dp_get_link_status(intel_dp, link_status)) {
- DRM_ERROR("failed to get link status\n");
- break;
- }
-
- /* Make sure clock is still ok */
- if (!drm_dp_clock_recovery_ok(link_status,
- intel_dp->lane_count)) {
- intel_dp->train_set_valid = false;
- intel_dp_link_training_clock_recovery(intel_dp);
- intel_dp_set_link_train(intel_dp, &DP,
- training_pattern |
- DP_LINK_SCRAMBLING_DISABLE);
- cr_tries++;
- continue;
- }
-
- if (drm_dp_channel_eq_ok(link_status,
- intel_dp->lane_count)) {
- channel_eq = true;
- break;
- }
-
- /* Try 5 times, then try clock recovery if that fails */
- if (tries > 5) {
- intel_dp->train_set_valid = false;
- intel_dp_link_training_clock_recovery(intel_dp);
- intel_dp_set_link_train(intel_dp, &DP,
- training_pattern |
- DP_LINK_SCRAMBLING_DISABLE);
- tries = 0;
- cr_tries++;
- continue;
- }
-
- /* Update training set as requested by target */
- if (!intel_dp_update_link_train(intel_dp, &DP, link_status)) {
- DRM_ERROR("failed to update link training\n");
- break;
- }
- ++tries;
- }
-
- intel_dp_set_idle_link_train(intel_dp);
-
- intel_dp->DP = DP;
-
- if (channel_eq) {
- intel_dp->train_set_valid = true;
- DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
- }
-}
-
-void intel_dp_stop_link_train(struct intel_dp *intel_dp)
-{
- intel_dp_set_link_train(intel_dp, &intel_dp->DP,
- DP_TRAINING_PATTERN_DISABLE);
-}
-
-void
-intel_dp_start_link_train(struct intel_dp *intel_dp)
-{
- intel_dp_link_training_clock_recovery(intel_dp);
- intel_dp_link_training_channel_equalization(intel_dp);
-}
-
static void
intel_dp_link_down(struct intel_dp *intel_dp)
{
@@ -3954,6 +3789,13 @@ intel_dp_link_down(struct intel_dp *intel_dp)
* matching HDMI port to be enabled on transcoder A.
*/
if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) {
+ /*
+ * We get CPU/PCH FIFO underruns on the other pipe when
+ * doing the workaround. Sweep them under the rug.
+ */
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false);
+ intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
+
/* always enable with pattern 1 (as per spec) */
DP &= ~(DP_PIPEB_SELECT | DP_LINK_TRAIN_MASK);
DP |= DP_PORT_EN | DP_LINK_TRAIN_PAT_1;
@@ -3963,9 +3805,15 @@ intel_dp_link_down(struct intel_dp *intel_dp)
DP &= ~DP_PORT_EN;
I915_WRITE(intel_dp->output_reg, DP);
POSTING_READ(intel_dp->output_reg);
+
+ intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A);
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
+ intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
}
msleep(intel_dp->panel_power_down_delay);
+
+ intel_dp->DP = DP;
}
static bool
@@ -4013,7 +3861,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
}
DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n",
- yesno(intel_dp_source_supports_hbr2(dev)),
+ yesno(intel_dp_source_supports_hbr2(intel_dp)),
yesno(drm_dp_tps3_supported(intel_dp->dpcd)));
/* Intermediate frequency support */
@@ -4103,9 +3951,12 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = dig_port->base.base.dev;
struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
u8 buf;
int ret = 0;
+ int count = 0;
+ int attempts = 10;
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) {
DRM_DEBUG_KMS("Sink CRC couldn't be stopped properly\n");
@@ -4120,7 +3971,22 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
goto out;
}
- intel_dp->sink_crc.started = false;
+ do {
+ intel_wait_for_vblank(dev, intel_crtc->pipe);
+
+ if (drm_dp_dpcd_readb(&intel_dp->aux,
+ DP_TEST_SINK_MISC, &buf) < 0) {
+ ret = -EIO;
+ goto out;
+ }
+ count = buf & DP_TEST_COUNT_MASK;
+ } while (--attempts && count);
+
+ if (attempts == 0) {
+ DRM_ERROR("TIMEOUT: Sink CRC counter is not zeroed\n");
+ ret = -ETIMEDOUT;
+ }
+
out:
hsw_enable_ips(intel_crtc);
return ret;
@@ -4129,27 +3995,26 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = dig_port->base.base.dev;
struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
u8 buf;
int ret;
- if (intel_dp->sink_crc.started) {
- ret = intel_dp_sink_crc_stop(intel_dp);
- if (ret)
- return ret;
- }
-
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0)
return -EIO;
if (!(buf & DP_TEST_CRC_SUPPORTED))
return -ENOTTY;
- intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK;
-
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0)
return -EIO;
+ if (buf & DP_TEST_SINK_START) {
+ ret = intel_dp_sink_crc_stop(intel_dp);
+ if (ret)
+ return ret;
+ }
+
hsw_disable_ips(intel_crtc);
if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK,
@@ -4158,7 +4023,7 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
return -EIO;
}
- intel_dp->sink_crc.started = true;
+ intel_wait_for_vblank(dev, intel_crtc->pipe);
return 0;
}
@@ -4170,7 +4035,6 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
u8 buf;
int count, ret;
int attempts = 6;
- bool old_equal_new;
ret = intel_dp_sink_crc_start(intel_dp);
if (ret)
@@ -4186,35 +4050,17 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
}
count = buf & DP_TEST_COUNT_MASK;
- /*
- * Count might be reset during the loop. In this case
- * last known count needs to be reset as well.
- */
- if (count == 0)
- intel_dp->sink_crc.last_count = 0;
-
- if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
- ret = -EIO;
- goto stop;
- }
-
- old_equal_new = (count == intel_dp->sink_crc.last_count &&
- !memcmp(intel_dp->sink_crc.last_crc, crc,
- 6 * sizeof(u8)));
-
- } while (--attempts && (count == 0 || old_equal_new));
-
- intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK;
- memcpy(intel_dp->sink_crc.last_crc, crc, 6 * sizeof(u8));
+ } while (--attempts && count == 0);
if (attempts == 0) {
- if (old_equal_new) {
- DRM_DEBUG_KMS("Unreliable Sink CRC counter: Current returned CRC is identical to the previous one\n");
- } else {
- DRM_ERROR("Panel is unable to calculate any CRC after 6 vblanks\n");
- ret = -ETIMEDOUT;
- goto stop;
- }
+ DRM_ERROR("Panel is unable to calculate any CRC after 6 vblanks\n");
+ ret = -ETIMEDOUT;
+ goto stop;
+ }
+
+ if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) {
+ ret = -EIO;
+ goto stop;
}
stop:
@@ -4314,13 +4160,6 @@ static void intel_dp_handle_test_request(struct intel_dp *intel_dp)
uint8_t rxdata = 0;
int status = 0;
- intel_dp->compliance_test_active = 0;
- intel_dp->compliance_test_type = 0;
- intel_dp->compliance_test_data = 0;
-
- intel_dp->aux.i2c_nack_count = 0;
- intel_dp->aux.i2c_defer_count = 0;
-
status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_REQUEST, &rxdata, 1);
if (status <= 0) {
DRM_DEBUG_KMS("Could not read test request from sink\n");
@@ -4436,6 +4275,14 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+ /*
+ * Clearing compliance test variables to allow capturing
+ * of values for next automated test request.
+ */
+ intel_dp->compliance_test_active = 0;
+ intel_dp->compliance_test_type = 0;
+ intel_dp->compliance_test_data = 0;
+
if (!intel_encoder->base.crtc)
return;
@@ -4466,7 +4313,9 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
}
- if (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) {
+ /* if link training is requested we should perform it always */
+ if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
+ (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
intel_encoder->base.name);
intel_dp_start_link_train(intel_dp);
@@ -4684,41 +4533,6 @@ bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
return g4x_digital_port_connected(dev_priv, port);
}
-static enum drm_connector_status
-ironlake_dp_detect(struct intel_dp *intel_dp)
-{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-
- if (!intel_digital_port_connected(dev_priv, intel_dig_port))
- return connector_status_disconnected;
-
- return intel_dp_detect_dpcd(intel_dp);
-}
-
-static enum drm_connector_status
-g4x_dp_detect(struct intel_dp *intel_dp)
-{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
- struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-
- /* Can't disconnect eDP, but you can close the lid... */
- if (is_edp(intel_dp)) {
- enum drm_connector_status status;
-
- status = intel_panel_detect(dev);
- if (status == connector_status_unknown)
- status = connector_status_connected;
- return status;
- }
-
- if (!intel_digital_port_connected(dev->dev_private, intel_dig_port))
- return connector_status_disconnected;
-
- return intel_dp_detect_dpcd(intel_dp);
-}
-
static struct edid *
intel_dp_get_edid(struct intel_dp *intel_dp)
{
@@ -4791,12 +4605,19 @@ intel_dp_detect(struct drm_connector *connector, bool force)
/* Can't disconnect eDP, but you can close the lid... */
if (is_edp(intel_dp))
status = edp_detect(intel_dp);
- else if (HAS_PCH_SPLIT(dev))
- status = ironlake_dp_detect(intel_dp);
+ else if (intel_digital_port_connected(to_i915(dev),
+ dp_to_dig_port(intel_dp)))
+ status = intel_dp_detect_dpcd(intel_dp);
else
- status = g4x_dp_detect(intel_dp);
- if (status != connector_status_connected)
+ status = connector_status_disconnected;
+
+ if (status != connector_status_connected) {
+ intel_dp->compliance_test_active = 0;
+ intel_dp->compliance_test_type = 0;
+ intel_dp->compliance_test_data = 0;
+
goto out;
+ }
intel_dp_probe_oui(intel_dp);
@@ -4810,6 +4631,14 @@ intel_dp_detect(struct drm_connector *connector, bool force)
goto out;
}
+ /*
+ * Clearing NACK and defer counts to get their exact values
+ * while reading EDID which are required by Compliance tests
+ * 4.2.2.4 and 4.2.2.5
+ */
+ intel_dp->aux.i2c_nack_count = 0;
+ intel_dp->aux.i2c_defer_count = 0;
+
intel_dp_set_edid(intel_dp);
if (intel_encoder->type != INTEL_OUTPUT_EDP)
@@ -5014,7 +4843,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
struct intel_dp *intel_dp = &intel_dig_port->dp;
- drm_dp_aux_unregister(&intel_dp->aux);
+ intel_dp_aux_fini(intel_dp);
intel_dp_mst_encoder_cleanup(intel_dig_port);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
@@ -5204,25 +5033,6 @@ put_power:
return ret;
}
-/* Return which DP Port should be selected for Transcoder DP control */
-int
-intel_trans_dp_port_sel(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct intel_encoder *intel_encoder;
- struct intel_dp *intel_dp;
-
- for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
- intel_dp = enc_to_intel_dp(&intel_encoder->base);
-
- if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
- intel_encoder->type == INTEL_OUTPUT_EDP)
- return intel_dp->output_reg;
- }
-
- return -1;
-}
-
/* check the VBT to see whether the eDP is on another port */
bool intel_dp_is_edp(struct drm_device *dev, enum port port)
{
@@ -5294,7 +5104,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
struct edp_power_seq cur, vbt, spec,
*final = &intel_dp->pps_delays;
u32 pp_on, pp_off, pp_div = 0, pp_ctl = 0;
- int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg = 0;
+ i915_reg_t pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
lockdep_assert_held(&dev_priv->pps_mutex);
@@ -5416,7 +5226,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp_on, pp_off, pp_div, port_sel = 0;
int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
- int pp_on_reg, pp_off_reg, pp_div_reg = 0, pp_ctrl_reg;
+ i915_reg_t pp_on_reg, pp_off_reg, pp_div_reg, pp_ctrl_reg;
enum port port = dp_to_dig_port(intel_dp)->port;
const struct edp_power_seq *seq = &intel_dp->pps_delays;
@@ -5578,7 +5388,7 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
DRM_ERROR("Unsupported refreshrate type\n");
}
} else if (INTEL_INFO(dev)->gen > 6) {
- u32 reg = PIPECONF(intel_crtc->config->cpu_transcoder);
+ i915_reg_t reg = PIPECONF(intel_crtc->config->cpu_transcoder);
u32 val;
val = I915_READ(reg);
@@ -5996,7 +5806,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct drm_device *dev = intel_encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_dig_port->port;
- int type;
+ int type, ret;
intel_dp->pps_pipe = INVALID_PIPE;
@@ -6017,6 +5827,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
else
intel_dp->get_aux_send_ctl = i9xx_get_aux_send_ctl;
+ if (HAS_DDI(dev))
+ intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain;
+
/* Preserve the current hw state. */
intel_dp->DP = I915_READ(intel_dp->output_reg);
intel_dp->attached_connector = intel_connector;
@@ -6068,7 +5881,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
break;
case PORT_B:
intel_encoder->hpd_pin = HPD_PORT_B;
- if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0))
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
intel_encoder->hpd_pin = HPD_PORT_A;
break;
case PORT_C:
@@ -6094,7 +5907,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
pps_unlock(intel_dp);
}
- intel_dp_aux_init(intel_dp, intel_connector);
+ ret = intel_dp_aux_init(intel_dp, intel_connector);
+ if (ret)
+ goto fail;
/* init MST on ports that can support it */
if (HAS_DP_MST(dev) &&
@@ -6103,20 +5918,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
intel_connector->base.base.id);
if (!intel_edp_init_connector(intel_dp, intel_connector)) {
- drm_dp_aux_unregister(&intel_dp->aux);
- if (is_edp(intel_dp)) {
- cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
- /*
- * vdd might still be enabled do to the delayed vdd off.
- * Make sure vdd is actually turned off here.
- */
- pps_lock(intel_dp);
- edp_panel_vdd_off_sync(intel_dp);
- pps_unlock(intel_dp);
- }
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
- return false;
+ intel_dp_aux_fini(intel_dp);
+ intel_dp_mst_encoder_cleanup(intel_dig_port);
+ goto fail;
}
intel_dp_add_properties(intel_dp, connector);
@@ -6133,10 +5937,27 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
i915_debugfs_connector_add(connector);
return true;
+
+fail:
+ if (is_edp(intel_dp)) {
+ cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+ /*
+ * vdd might still be enabled do to the delayed vdd off.
+ * Make sure vdd is actually turned off here.
+ */
+ pps_lock(intel_dp);
+ edp_panel_vdd_off_sync(intel_dp);
+ pps_unlock(intel_dp);
+ }
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+
+ return false;
}
void
-intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+intel_dp_init(struct drm_device *dev,
+ i915_reg_t output_reg, enum port port)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_digital_port *intel_dig_port;
@@ -6182,6 +6003,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
}
intel_dig_port->port = port;
+ dev_priv->dig_port_map[port] = intel_encoder;
intel_dig_port->dp.output_reg = output_reg;
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c
new file mode 100644
index 000000000000..88887938e0bf
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dp_link_training.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright © 2008-2015 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.
+ */
+
+#include "intel_drv.h"
+
+static void
+intel_get_adjust_train(struct intel_dp *intel_dp,
+ const uint8_t link_status[DP_LINK_STATUS_SIZE])
+{
+ uint8_t v = 0;
+ uint8_t p = 0;
+ int lane;
+ uint8_t voltage_max;
+ uint8_t preemph_max;
+
+ for (lane = 0; lane < intel_dp->lane_count; lane++) {
+ uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane);
+ uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
+
+ if (this_v > v)
+ v = this_v;
+ if (this_p > p)
+ p = this_p;
+ }
+
+ voltage_max = intel_dp_voltage_max(intel_dp);
+ if (v >= voltage_max)
+ v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
+
+ preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
+ if (p >= preemph_max)
+ p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+ for (lane = 0; lane < 4; lane++)
+ intel_dp->train_set[lane] = v | p;
+}
+
+static bool
+intel_dp_set_link_train(struct intel_dp *intel_dp,
+ uint8_t dp_train_pat)
+{
+ uint8_t buf[sizeof(intel_dp->train_set) + 1];
+ int ret, len;
+
+ intel_dp_program_link_training_pattern(intel_dp, dp_train_pat);
+
+ buf[0] = dp_train_pat;
+ if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) ==
+ DP_TRAINING_PATTERN_DISABLE) {
+ /* don't write DP_TRAINING_LANEx_SET on disable */
+ len = 1;
+ } else {
+ /* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */
+ memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count);
+ len = intel_dp->lane_count + 1;
+ }
+
+ ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
+ buf, len);
+
+ return ret == len;
+}
+
+static bool
+intel_dp_reset_link_train(struct intel_dp *intel_dp,
+ uint8_t dp_train_pat)
+{
+ if (!intel_dp->train_set_valid)
+ memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
+ intel_dp_set_signal_levels(intel_dp);
+ return intel_dp_set_link_train(intel_dp, dp_train_pat);
+}
+
+static bool
+intel_dp_update_link_train(struct intel_dp *intel_dp)
+{
+ int ret;
+
+ intel_dp_set_signal_levels(intel_dp);
+
+ ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
+ intel_dp->train_set, intel_dp->lane_count);
+
+ return ret == intel_dp->lane_count;
+}
+
+/* Enable corresponding port and start training pattern 1 */
+static void
+intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
+{
+ int i;
+ uint8_t voltage;
+ int voltage_tries, loop_tries;
+ uint8_t link_config[2];
+ uint8_t link_bw, rate_select;
+
+ if (intel_dp->prepare_link_retrain)
+ intel_dp->prepare_link_retrain(intel_dp);
+
+ intel_dp_compute_rate(intel_dp, intel_dp->link_rate,
+ &link_bw, &rate_select);
+
+ /* Write the link configuration data */
+ link_config[0] = link_bw;
+ link_config[1] = intel_dp->lane_count;
+ if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+ link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+ drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
+ if (intel_dp->num_sink_rates)
+ drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
+ &rate_select, 1);
+
+ link_config[0] = 0;
+ link_config[1] = DP_SET_ANSI_8B10B;
+ drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
+
+ intel_dp->DP |= DP_PORT_EN;
+
+ /* clock recovery */
+ if (!intel_dp_reset_link_train(intel_dp,
+ DP_TRAINING_PATTERN_1 |
+ DP_LINK_SCRAMBLING_DISABLE)) {
+ DRM_ERROR("failed to enable link training\n");
+ return;
+ }
+
+ voltage = 0xff;
+ voltage_tries = 0;
+ loop_tries = 0;
+ for (;;) {
+ uint8_t link_status[DP_LINK_STATUS_SIZE];
+
+ drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd);
+ if (!intel_dp_get_link_status(intel_dp, link_status)) {
+ DRM_ERROR("failed to get link status\n");
+ break;
+ }
+
+ if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
+ DRM_DEBUG_KMS("clock recovery OK\n");
+ break;
+ }
+
+ /*
+ * if we used previously trained voltage and pre-emphasis values
+ * and we don't get clock recovery, reset link training values
+ */
+ if (intel_dp->train_set_valid) {
+ DRM_DEBUG_KMS("clock recovery not ok, reset");
+ /* clear the flag as we are not reusing train set */
+ intel_dp->train_set_valid = false;
+ if (!intel_dp_reset_link_train(intel_dp,
+ DP_TRAINING_PATTERN_1 |
+ DP_LINK_SCRAMBLING_DISABLE)) {
+ DRM_ERROR("failed to enable link training\n");
+ return;
+ }
+ continue;
+ }
+
+ /* Check to see if we've tried the max voltage */
+ for (i = 0; i < intel_dp->lane_count; i++)
+ if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+ break;
+ if (i == intel_dp->lane_count) {
+ ++loop_tries;
+ if (loop_tries == 5) {
+ DRM_ERROR("too many full retries, give up\n");
+ break;
+ }
+ intel_dp_reset_link_train(intel_dp,
+ DP_TRAINING_PATTERN_1 |
+ DP_LINK_SCRAMBLING_DISABLE);
+ voltage_tries = 0;
+ continue;
+ }
+
+ /* Check to see if we've tried the same voltage 5 times */
+ if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
+ ++voltage_tries;
+ if (voltage_tries == 5) {
+ DRM_ERROR("too many voltage retries, give up\n");
+ break;
+ }
+ } else
+ voltage_tries = 0;
+ voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+ /* Update training set as requested by target */
+ intel_get_adjust_train(intel_dp, link_status);
+ if (!intel_dp_update_link_train(intel_dp)) {
+ DRM_ERROR("failed to update link training\n");
+ break;
+ }
+ }
+}
+
+static void
+intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
+{
+ bool channel_eq = false;
+ int tries, cr_tries;
+ uint32_t training_pattern = DP_TRAINING_PATTERN_2;
+
+ /*
+ * Training Pattern 3 for HBR2 or 1.2 devices that support it.
+ *
+ * Intel platforms that support HBR2 also support TPS3. TPS3 support is
+ * also mandatory for downstream devices that support HBR2.
+ *
+ * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is
+ * supported but still not enabled.
+ */
+ if (intel_dp_source_supports_hbr2(intel_dp) &&
+ drm_dp_tps3_supported(intel_dp->dpcd))
+ training_pattern = DP_TRAINING_PATTERN_3;
+ else if (intel_dp->link_rate == 540000)
+ DRM_ERROR("5.4 Gbps link rate without HBR2/TPS3 support\n");
+
+ /* channel equalization */
+ if (!intel_dp_set_link_train(intel_dp,
+ training_pattern |
+ DP_LINK_SCRAMBLING_DISABLE)) {
+ DRM_ERROR("failed to start channel equalization\n");
+ return;
+ }
+
+ tries = 0;
+ cr_tries = 0;
+ channel_eq = false;
+ for (;;) {
+ uint8_t link_status[DP_LINK_STATUS_SIZE];
+
+ if (cr_tries > 5) {
+ DRM_ERROR("failed to train DP, aborting\n");
+ break;
+ }
+
+ drm_dp_link_train_channel_eq_delay(intel_dp->dpcd);
+ if (!intel_dp_get_link_status(intel_dp, link_status)) {
+ DRM_ERROR("failed to get link status\n");
+ break;
+ }
+
+ /* Make sure clock is still ok */
+ if (!drm_dp_clock_recovery_ok(link_status,
+ intel_dp->lane_count)) {
+ intel_dp->train_set_valid = false;
+ intel_dp_link_training_clock_recovery(intel_dp);
+ intel_dp_set_link_train(intel_dp,
+ training_pattern |
+ DP_LINK_SCRAMBLING_DISABLE);
+ cr_tries++;
+ continue;
+ }
+
+ if (drm_dp_channel_eq_ok(link_status,
+ intel_dp->lane_count)) {
+ channel_eq = true;
+ break;
+ }
+
+ /* Try 5 times, then try clock recovery if that fails */
+ if (tries > 5) {
+ intel_dp->train_set_valid = false;
+ intel_dp_link_training_clock_recovery(intel_dp);
+ intel_dp_set_link_train(intel_dp,
+ training_pattern |
+ DP_LINK_SCRAMBLING_DISABLE);
+ tries = 0;
+ cr_tries++;
+ continue;
+ }
+
+ /* Update training set as requested by target */
+ intel_get_adjust_train(intel_dp, link_status);
+ if (!intel_dp_update_link_train(intel_dp)) {
+ DRM_ERROR("failed to update link training\n");
+ break;
+ }
+ ++tries;
+ }
+
+ intel_dp_set_idle_link_train(intel_dp);
+
+ if (channel_eq) {
+ intel_dp->train_set_valid = true;
+ DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
+ }
+}
+
+void intel_dp_stop_link_train(struct intel_dp *intel_dp)
+{
+ intel_dp_set_link_train(intel_dp,
+ DP_TRAINING_PATTERN_DISABLE);
+}
+
+void
+intel_dp_start_link_train(struct intel_dp *intel_dp)
+{
+ intel_dp_link_training_clock_recovery(intel_dp);
+ intel_dp_link_training_channel_equalization(intel_dp);
+}
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 0639275fc471..8c4e7dfe304c 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -173,20 +173,14 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
intel_mst->port = found->port;
if (intel_dp->active_mst_links == 0) {
- enum port port = intel_ddi_get_encoder_port(encoder);
+ intel_ddi_clk_select(encoder, intel_crtc->config);
intel_dp_set_link_params(intel_dp, intel_crtc->config);
- /* FIXME: add support for SKL */
- if (INTEL_INFO(dev)->gen < 9)
- I915_WRITE(PORT_CLK_SEL(port),
- intel_crtc->config->ddi_pll_sel);
-
intel_ddi_init_dp_buf_reg(&intel_dig_port->base);
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-
intel_dp_start_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
}
@@ -414,7 +408,10 @@ static void intel_connector_add_to_fbdev(struct intel_connector *connector)
{
#ifdef CONFIG_DRM_FBDEV_EMULATION
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, &connector->base);
+
+ if (dev_priv->fbdev)
+ drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper,
+ &connector->base);
#endif
}
@@ -422,7 +419,10 @@ static void intel_connector_remove_from_fbdev(struct intel_connector *connector)
{
#ifdef CONFIG_DRM_FBDEV_EMULATION
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, &connector->base);
+
+ if (dev_priv->fbdev)
+ drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper,
+ &connector->base);
#endif
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0d00f07b7163..86ce3c2ed79a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -123,8 +123,6 @@ struct intel_framebuffer {
struct intel_fbdev {
struct drm_fb_helper helper;
struct intel_framebuffer *fb;
- struct list_head fbdev_list;
- struct drm_display_mode *our_mode;
int preferred_bpp;
};
@@ -250,6 +248,7 @@ struct intel_atomic_state {
unsigned int cdclk;
bool dpll_set;
struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
+ struct intel_wm_config wm_config;
};
struct intel_plane_state {
@@ -280,6 +279,9 @@ struct intel_plane_state {
int scaler_id;
struct drm_intel_sprite_colorkey ckey;
+
+ /* async flip related structures */
+ struct drm_i915_gem_request *wait_req;
};
struct intel_initial_plane_config {
@@ -334,6 +336,21 @@ struct intel_crtc_scaler_state {
/* drm_mode->private_flags */
#define I915_MODE_FLAG_INHERITED 1
+struct intel_pipe_wm {
+ struct intel_wm_level wm[5];
+ uint32_t linetime;
+ bool fbc_wm_enabled;
+ bool pipe_enabled;
+ bool sprites_enabled;
+ bool sprites_scaled;
+};
+
+struct skl_pipe_wm {
+ struct skl_wm_level wm[8];
+ struct skl_wm_level trans_wm;
+ uint32_t linetime;
+};
+
struct intel_crtc_state {
struct drm_crtc_state base;
@@ -468,6 +485,20 @@ struct intel_crtc_state {
/* w/a for waiting 2 vblanks during crtc enable */
enum pipe hsw_workaround_pipe;
+
+ /* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
+ bool disable_lp_wm;
+
+ struct {
+ /*
+ * optimal watermarks, programmed post-vblank when this state
+ * is committed
+ */
+ union {
+ struct intel_pipe_wm ilk;
+ struct skl_pipe_wm skl;
+ } optimal;
+ } wm;
};
struct vlv_wm_state {
@@ -479,26 +510,12 @@ struct vlv_wm_state {
bool cxsr;
};
-struct intel_pipe_wm {
- struct intel_wm_level wm[5];
- uint32_t linetime;
- bool fbc_wm_enabled;
- bool pipe_enabled;
- bool sprites_enabled;
- bool sprites_scaled;
-};
-
struct intel_mmio_flip {
struct work_struct work;
struct drm_i915_private *i915;
struct drm_i915_gem_request *req;
struct intel_crtc *crtc;
-};
-
-struct skl_pipe_wm {
- struct skl_wm_level wm[8];
- struct skl_wm_level trans_wm;
- uint32_t linetime;
+ unsigned int rotation;
};
/*
@@ -509,13 +526,11 @@ struct skl_pipe_wm {
*/
struct intel_crtc_atomic_commit {
/* Sleepable operations to perform before commit */
- bool wait_for_flips;
bool disable_fbc;
bool disable_ips;
bool disable_cxsr;
bool pre_disable_primary;
bool update_wm_pre, update_wm_post;
- unsigned disabled_planes;
/* Sleepable operations to perform after commit */
unsigned fb_bits;
@@ -567,9 +582,10 @@ struct intel_crtc {
/* per-pipe watermark state */
struct {
/* watermarks currently being used */
- struct intel_pipe_wm active;
- /* SKL wm values currently in use */
- struct skl_pipe_wm skl_active;
+ union {
+ struct intel_pipe_wm ilk;
+ struct skl_pipe_wm skl;
+ } active;
/* allow CxSR on this pipe */
bool cxsr_allowed;
} wm;
@@ -677,7 +693,7 @@ struct cxsr_latency {
#define intel_fb_obj(x) (x ? to_intel_framebuffer(x)->obj : NULL)
struct intel_hdmi {
- u32 hdmi_reg;
+ i915_reg_t hdmi_reg;
int ddc_bus;
bool limited_color_range;
bool color_range_auto;
@@ -719,15 +735,10 @@ enum link_m_n_set {
M2_N2
};
-struct sink_crc {
- bool started;
- u8 last_crc[6];
- int last_count;
-};
-
struct intel_dp {
- uint32_t output_reg;
- uint32_t aux_ch_ctl_reg;
+ i915_reg_t output_reg;
+ i915_reg_t aux_ch_ctl_reg;
+ i915_reg_t aux_ch_data_reg[5];
uint32_t DP;
int link_rate;
uint8_t lane_count;
@@ -741,7 +752,6 @@ struct intel_dp {
/* sink rates as reported by DP_SUPPORTED_LINK_RATES */
uint8_t num_sink_rates;
int sink_rates[DP_MAX_SUPPORTED_RATES];
- struct sink_crc sink_crc;
struct drm_dp_aux aux;
uint8_t train_set[4];
int panel_power_up_delay;
@@ -783,6 +793,10 @@ struct intel_dp {
bool has_aux_irq,
int send_bytes,
uint32_t aux_clock_divider);
+
+ /* This is called before a link training is starterd */
+ void (*prepare_link_retrain)(struct intel_dp *intel_dp);
+
bool train_set_valid;
/* Displayport compliance testing */
@@ -799,6 +813,8 @@ struct intel_digital_port {
struct intel_hdmi hdmi;
enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
bool release_cl2_override;
+ /* for communication with audio component; protected by av_mutex */
+ const struct drm_connector *audio_connector;
};
struct intel_dp_mst_encoder {
@@ -942,7 +958,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pipe);
void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum transcoder pch_transcoder);
-void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv);
+void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv);
+void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv);
/* i915_irq.c */
void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
@@ -973,6 +990,8 @@ void intel_crt_init(struct drm_device *dev);
/* intel_ddi.c */
+void intel_ddi_clk_select(struct intel_encoder *encoder,
+ const struct intel_crtc_state *pipe_config);
void intel_prepare_ddi(struct drm_device *dev);
void hsw_fdi_link_train(struct drm_crtc *crtc);
void intel_ddi_init(struct drm_device *dev, enum port port);
@@ -987,7 +1006,7 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
bool intel_ddi_pll_select(struct intel_crtc *crtc,
struct intel_crtc_state *crtc_state);
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
-void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
+void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp);
bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
void intel_ddi_fdi_disable(struct drm_crtc *crtc);
void intel_ddi_get_config(struct intel_encoder *encoder,
@@ -1055,6 +1074,15 @@ intel_wait_for_vblank(struct drm_device *dev, int pipe)
{
drm_wait_one_vblank(dev, pipe);
}
+static inline void
+intel_wait_for_vblank_if_active(struct drm_device *dev, int pipe)
+{
+ const struct intel_crtc *crtc =
+ to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+
+ if (crtc->active)
+ intel_wait_for_vblank(dev, pipe);
+}
int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
struct intel_digital_port *dport,
@@ -1068,9 +1096,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx);
int intel_pin_and_fence_fb_obj(struct drm_plane *plane,
struct drm_framebuffer *fb,
- const struct drm_plane_state *plane_state,
- struct intel_engine_cs *pipelined,
- struct drm_i915_gem_request **pipelined_request);
+ const struct drm_plane_state *plane_state);
struct drm_framebuffer *
__intel_framebuffer_create(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd,
@@ -1151,7 +1177,10 @@ void broxton_ddi_phy_uninit(struct drm_device *dev);
void bxt_enable_dc9(struct drm_i915_private *dev_priv);
void bxt_disable_dc9(struct drm_i915_private *dev_priv);
void skl_init_cdclk(struct drm_i915_private *dev_priv);
+int skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
void skl_uninit_cdclk(struct drm_i915_private *dev_priv);
+void skl_enable_dc6(struct drm_i915_private *dev_priv);
+void skl_disable_dc6(struct drm_i915_private *dev_priv);
void intel_dp_get_m_n(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config);
void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
@@ -1172,31 +1201,26 @@ enum intel_display_power_domain
intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder);
void intel_mode_from_pipe_config(struct drm_display_mode *mode,
struct intel_crtc_state *pipe_config);
-void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc);
void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
- struct drm_i915_gem_object *obj,
- unsigned int plane);
+u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
+ struct drm_i915_gem_object *obj,
+ unsigned int plane);
u32 skl_plane_ctl_format(uint32_t pixel_format);
u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
u32 skl_plane_ctl_rotation(unsigned int rotation);
/* intel_csr.c */
-void intel_csr_ucode_init(struct drm_device *dev);
-enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv);
-void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
- enum csr_state state);
-void intel_csr_load_program(struct drm_device *dev);
-void intel_csr_ucode_fini(struct drm_device *dev);
-void assert_csr_loaded(struct drm_i915_private *dev_priv);
+void intel_csr_ucode_init(struct drm_i915_private *);
+void intel_csr_load_program(struct drm_i915_private *);
+void intel_csr_ucode_fini(struct drm_i915_private *);
/* intel_dp.c */
-void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
+void intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port);
bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector);
void intel_dp_set_link_params(struct intel_dp *intel_dp,
@@ -1234,6 +1258,22 @@ bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
struct intel_digital_port *port);
void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config);
+void
+intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
+ uint8_t dp_train_pat);
+void
+intel_dp_set_signal_levels(struct intel_dp *intel_dp);
+void intel_dp_set_idle_link_train(struct intel_dp *intel_dp);
+uint8_t
+intel_dp_voltage_max(struct intel_dp *intel_dp);
+uint8_t
+intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing);
+void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
+ uint8_t *link_bw, uint8_t *rate_select);
+bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp);
+bool
+intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]);
+
/* intel_dp_mst.c */
int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
@@ -1248,7 +1288,7 @@ void intel_dvo_init(struct drm_device *dev);
/* legacy fbdev emulation in intel_fbdev.c */
#ifdef CONFIG_DRM_FBDEV_EMULATION
extern int intel_fbdev_init(struct drm_device *dev);
-extern void intel_fbdev_initial_config(void *data, async_cookie_t cookie);
+extern void intel_fbdev_initial_config_async(struct drm_device *dev);
extern void intel_fbdev_fini(struct drm_device *dev);
extern void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous);
extern void intel_fbdev_output_poll_changed(struct drm_device *dev);
@@ -1259,7 +1299,7 @@ static inline int intel_fbdev_init(struct drm_device *dev)
return 0;
}
-static inline void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
+static inline void intel_fbdev_initial_config_async(struct drm_device *dev)
{
}
@@ -1287,11 +1327,10 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv,
enum fb_op_origin origin);
void intel_fbc_flush(struct drm_i915_private *dev_priv,
unsigned int frontbuffer_bits, enum fb_op_origin origin);
-const char *intel_no_fbc_reason_str(enum no_fbc_reason reason);
void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
/* intel_hdmi.c */
-void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port);
+void intel_hdmi_init(struct drm_device *dev, i915_reg_t hdmi_reg, enum port port);
void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector);
struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
@@ -1367,7 +1406,10 @@ void intel_psr_single_frame_update(struct drm_device *dev,
/* intel_runtime_pm.c */
int intel_power_domains_init(struct drm_i915_private *);
void intel_power_domains_fini(struct drm_i915_private *);
-void intel_power_domains_init_hw(struct drm_i915_private *dev_priv);
+void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume);
+void intel_power_domains_suspend(struct drm_i915_private *dev_priv);
+void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv);
+void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv);
void intel_runtime_pm_enable(struct drm_i915_private *dev_priv);
bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
@@ -1395,12 +1437,6 @@ void intel_init_clock_gating(struct drm_device *dev);
void intel_suspend_hw(struct drm_device *dev);
int ilk_wm_max_level(const struct drm_device *dev);
void intel_update_watermarks(struct drm_crtc *crtc);
-void intel_update_sprite_watermarks(struct drm_plane *plane,
- struct drm_crtc *crtc,
- uint32_t sprite_width,
- uint32_t sprite_height,
- int pixel_size,
- bool enabled, bool scaled);
void intel_init_pm(struct drm_device *dev);
void intel_pm_setup(struct drm_device *dev);
void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
@@ -1428,7 +1464,8 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config);
/* intel_sdvo.c */
-bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
+bool intel_sdvo_init(struct drm_device *dev,
+ i915_reg_t reg, enum port port);
/* intel_sprite.c */
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 170ae6f4866e..efb5a27dd49c 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -60,7 +60,8 @@ static void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi, enum port port)
DRM_ERROR("DPI FIFOs are not empty\n");
}
-static void write_data(struct drm_i915_private *dev_priv, u32 reg,
+static void write_data(struct drm_i915_private *dev_priv,
+ i915_reg_t reg,
const u8 *data, u32 len)
{
u32 i, j;
@@ -75,7 +76,8 @@ static void write_data(struct drm_i915_private *dev_priv, u32 reg,
}
}
-static void read_data(struct drm_i915_private *dev_priv, u32 reg,
+static void read_data(struct drm_i915_private *dev_priv,
+ i915_reg_t reg,
u8 *data, u32 len)
{
u32 i, j;
@@ -98,7 +100,8 @@ static ssize_t intel_dsi_host_transfer(struct mipi_dsi_host *host,
struct mipi_dsi_packet packet;
ssize_t ret;
const u8 *header, *data;
- u32 data_reg, data_mask, ctrl_reg, ctrl_mask;
+ i915_reg_t data_reg, ctrl_reg;
+ u32 data_mask, ctrl_mask;
ret = mipi_dsi_create_packet(&packet, msg);
if (ret < 0)
@@ -377,10 +380,10 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder)
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
enum port port;
- u32 temp;
- u32 port_ctrl;
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
+ u32 temp;
+
temp = I915_READ(VLV_CHICKEN_3);
temp &= ~PIXEL_OVERLAP_CNT_MASK |
intel_dsi->pixel_overlap <<
@@ -389,8 +392,9 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder)
}
for_each_dsi_port(port, intel_dsi->ports) {
- port_ctrl = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) :
- MIPI_PORT_CTRL(port);
+ i915_reg_t port_ctrl = IS_BROXTON(dev) ?
+ BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
+ u32 temp;
temp = I915_READ(port_ctrl);
@@ -416,13 +420,13 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
enum port port;
- u32 temp;
- u32 port_ctrl;
for_each_dsi_port(port, intel_dsi->ports) {
+ i915_reg_t port_ctrl = IS_BROXTON(dev) ?
+ BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
+ u32 temp;
+
/* de-assert ip_tg_enable signal */
- port_ctrl = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) :
- MIPI_PORT_CTRL(port);
temp = I915_READ(port_ctrl);
I915_WRITE(port_ctrl, temp & ~DPI_ENABLE);
POSTING_READ(port_ctrl);
@@ -580,11 +584,13 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
enum port port;
- u32 val;
- u32 port_ctrl = 0;
DRM_DEBUG_KMS("\n");
for_each_dsi_port(port, intel_dsi->ports) {
+ /* Common bit for both MIPI Port A & MIPI Port C on VLV/CHV */
+ i915_reg_t port_ctrl = IS_BROXTON(dev) ?
+ BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(PORT_A);
+ u32 val;
I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY |
ULPS_STATE_ENTER);
@@ -598,12 +604,6 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
ULPS_STATE_ENTER);
usleep_range(2000, 2500);
- if (IS_BROXTON(dev))
- port_ctrl = BXT_MIPI_PORT_CTRL(port);
- else if (IS_VALLEYVIEW(dev))
- /* Common bit for both MIPI Port A & MIPI Port C */
- port_ctrl = MIPI_PORT_CTRL(PORT_A);
-
/* Wait till Clock lanes are in LP-00 state for MIPI Port A
* only. MIPI Port C has no similar bit for checking
*/
@@ -656,7 +656,6 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
struct drm_device *dev = encoder->base.dev;
enum intel_display_power_domain power_domain;
- u32 dpi_enabled, func, ctrl_reg;
enum port port;
DRM_DEBUG_KMS("\n");
@@ -667,9 +666,11 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
/* XXX: this only works for one DSI output */
for_each_dsi_port(port, intel_dsi->ports) {
+ i915_reg_t ctrl_reg = IS_BROXTON(dev) ?
+ BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
+ u32 dpi_enabled, func;
+
func = I915_READ(MIPI_DSI_FUNC_PRG(port));
- ctrl_reg = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) :
- MIPI_PORT_CTRL(port);
dpi_enabled = I915_READ(ctrl_reg) & DPI_ENABLE;
/* Due to some hardware limitations on BYT, MIPI Port C DPI
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index e6cb25239941..02551ff228c2 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -117,7 +117,7 @@ static inline struct intel_dsi_host *to_intel_dsi_host(struct mipi_dsi_host *h)
#define for_each_dsi_port(__port, __ports_mask) \
for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++) \
- if ((__ports_mask) & (1 << (__port)))
+ for_each_if ((__ports_mask) & (1 << (__port)))
static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
{
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 8492053e0ff0..7161deb2aed8 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -44,6 +44,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.type = INTEL_DVO_CHIP_TMDS,
.name = "sil164",
.dvo_reg = DVOC,
+ .dvo_srcdim_reg = DVOC_SRCDIM,
.slave_addr = SIL164_ADDR,
.dev_ops = &sil164_ops,
},
@@ -51,6 +52,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.type = INTEL_DVO_CHIP_TMDS,
.name = "ch7xxx",
.dvo_reg = DVOC,
+ .dvo_srcdim_reg = DVOC_SRCDIM,
.slave_addr = CH7xxx_ADDR,
.dev_ops = &ch7xxx_ops,
},
@@ -58,6 +60,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.type = INTEL_DVO_CHIP_TMDS,
.name = "ch7xxx",
.dvo_reg = DVOC,
+ .dvo_srcdim_reg = DVOC_SRCDIM,
.slave_addr = 0x75, /* For some ch7010 */
.dev_ops = &ch7xxx_ops,
},
@@ -65,6 +68,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.type = INTEL_DVO_CHIP_LVDS,
.name = "ivch",
.dvo_reg = DVOA,
+ .dvo_srcdim_reg = DVOA_SRCDIM,
.slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */
.dev_ops = &ivch_ops,
},
@@ -72,6 +76,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.type = INTEL_DVO_CHIP_TMDS,
.name = "tfp410",
.dvo_reg = DVOC,
+ .dvo_srcdim_reg = DVOC_SRCDIM,
.slave_addr = TFP410_ADDR,
.dev_ops = &tfp410_ops,
},
@@ -79,6 +84,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.type = INTEL_DVO_CHIP_LVDS,
.name = "ch7017",
.dvo_reg = DVOC,
+ .dvo_srcdim_reg = DVOC_SRCDIM,
.slave_addr = 0x75,
.gpio = GMBUS_PIN_DPB,
.dev_ops = &ch7017_ops,
@@ -87,6 +93,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.type = INTEL_DVO_CHIP_TMDS,
.name = "ns2501",
.dvo_reg = DVOB,
+ .dvo_srcdim_reg = DVOB_SRCDIM,
.slave_addr = NS2501_ADDR,
.dev_ops = &ns2501_ops,
}
@@ -171,7 +178,7 @@ static void intel_disable_dvo(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
- u32 dvo_reg = intel_dvo->dev.dvo_reg;
+ i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg;
u32 temp = I915_READ(dvo_reg);
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
@@ -184,7 +191,7 @@ static void intel_enable_dvo(struct intel_encoder *encoder)
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
- u32 dvo_reg = intel_dvo->dev.dvo_reg;
+ i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg;
u32 temp = I915_READ(dvo_reg);
intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev,
@@ -255,20 +262,8 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder)
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
int pipe = crtc->pipe;
u32 dvo_val;
- u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg;
-
- switch (dvo_reg) {
- case DVOA:
- default:
- dvo_srcdim_reg = DVOA_SRCDIM;
- break;
- case DVOB:
- dvo_srcdim_reg = DVOB_SRCDIM;
- break;
- case DVOC:
- dvo_srcdim_reg = DVOC_SRCDIM;
- break;
- }
+ i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg;
+ i915_reg_t dvo_srcdim_reg = intel_dvo->dev.dvo_srcdim_reg;
/* Save the data order, since I don't know what it should be set to. */
dvo_val = I915_READ(dvo_reg) &
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index cf47352b7b8e..11fc5281e8ef 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -46,6 +46,11 @@ static inline bool fbc_supported(struct drm_i915_private *dev_priv)
return dev_priv->fbc.enable_fbc != NULL;
}
+static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv)
+{
+ return IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8;
+}
+
/*
* In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the
* frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's
@@ -182,7 +187,8 @@ static bool g4x_fbc_enabled(struct drm_i915_private *dev_priv)
return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
}
-static void intel_fbc_nuke(struct drm_i915_private *dev_priv)
+/* This function forces a CFB recompression through the nuke operation. */
+static void intel_fbc_recompress(struct drm_i915_private *dev_priv)
{
I915_WRITE(MSG_FBC_REND_STATE, FBC_REND_NUKE);
POSTING_READ(MSG_FBC_REND_STATE);
@@ -231,7 +237,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc)
I915_WRITE(DPFC_CPU_FENCE_OFFSET, y_offset);
}
- intel_fbc_nuke(dev_priv);
+ intel_fbc_recompress(dev_priv);
DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
}
@@ -310,7 +316,7 @@ static void gen7_fbc_enable(struct intel_crtc *crtc)
SNB_CPU_FENCE_ENABLE | obj->fence_reg);
I915_WRITE(DPFC_CPU_FENCE_OFFSET, get_crtc_fence_y_offset(crtc));
- intel_fbc_nuke(dev_priv);
+ intel_fbc_recompress(dev_priv);
DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane));
}
@@ -370,8 +376,6 @@ static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv)
if (dev_priv->fbc.fbc_work == NULL)
return;
- DRM_DEBUG_KMS("cancelling pending FBC enable\n");
-
/* Synchronisation is provided by struct_mutex and checking of
* dev_priv->fbc.fbc_work, so we can perform the cancellation
* entirely asynchronously.
@@ -432,7 +436,8 @@ static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
intel_fbc_cancel_work(dev_priv);
- dev_priv->fbc.disable_fbc(dev_priv);
+ if (dev_priv->fbc.enabled)
+ dev_priv->fbc.disable_fbc(dev_priv);
dev_priv->fbc.crtc = NULL;
}
@@ -471,78 +476,45 @@ void intel_fbc_disable_crtc(struct intel_crtc *crtc)
mutex_unlock(&dev_priv->fbc.lock);
}
-const char *intel_no_fbc_reason_str(enum no_fbc_reason reason)
-{
- switch (reason) {
- case FBC_OK:
- return "FBC enabled but currently disabled in hardware";
- case FBC_UNSUPPORTED:
- return "unsupported by this chipset";
- case FBC_NO_OUTPUT:
- return "no output";
- case FBC_STOLEN_TOO_SMALL:
- return "not enough stolen memory";
- case FBC_UNSUPPORTED_MODE:
- return "mode incompatible with compression";
- case FBC_MODE_TOO_LARGE:
- return "mode too large for compression";
- case FBC_BAD_PLANE:
- return "FBC unsupported on plane";
- case FBC_NOT_TILED:
- return "framebuffer not tiled or fenced";
- case FBC_MULTIPLE_PIPES:
- return "more than one pipe active";
- case FBC_MODULE_PARAM:
- return "disabled per module param";
- case FBC_CHIP_DEFAULT:
- return "disabled per chip default";
- case FBC_ROTATION:
- return "rotation unsupported";
- case FBC_IN_DBG_MASTER:
- return "Kernel debugger is active";
- case FBC_BAD_STRIDE:
- return "framebuffer stride not supported";
- case FBC_PIXEL_RATE:
- return "pixel rate is too big";
- case FBC_PIXEL_FORMAT:
- return "pixel format is invalid";
- default:
- MISSING_CASE(reason);
- return "unknown reason";
- }
-}
-
static void set_no_fbc_reason(struct drm_i915_private *dev_priv,
- enum no_fbc_reason reason)
+ const char *reason)
{
if (dev_priv->fbc.no_fbc_reason == reason)
return;
dev_priv->fbc.no_fbc_reason = reason;
- DRM_DEBUG_KMS("Disabling FBC: %s\n", intel_no_fbc_reason_str(reason));
+ DRM_DEBUG_KMS("Disabling FBC: %s\n", reason);
+}
+
+static bool crtc_is_valid(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+ if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A)
+ return false;
+
+ if (!intel_crtc_active(&crtc->base))
+ return false;
+
+ if (!to_intel_plane_state(crtc->base.primary->state)->visible)
+ return false;
+
+ return true;
}
static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv)
{
struct drm_crtc *crtc = NULL, *tmp_crtc;
enum pipe pipe;
- bool pipe_a_only = false;
-
- if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
- pipe_a_only = true;
for_each_pipe(dev_priv, pipe) {
tmp_crtc = dev_priv->pipe_to_crtc_mapping[pipe];
- if (intel_crtc_active(tmp_crtc) &&
- to_intel_plane_state(tmp_crtc->primary->state)->visible)
+ if (crtc_is_valid(to_intel_crtc(tmp_crtc)))
crtc = tmp_crtc;
-
- if (pipe_a_only)
- break;
}
- if (!crtc || crtc->primary->fb == NULL)
+ if (!crtc)
return NULL;
return crtc;
@@ -581,7 +553,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
* reserved range size, so it always assumes the maximum (8mb) is used.
* If we enable FBC using a CFB on that memory range we'll get FIFO
* underruns, even if that range is not reserved by the BIOS. */
- if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
+ if (IS_BROADWELL(dev_priv) ||
+ IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024;
else
end = dev_priv->gtt.stolen_usable_size;
@@ -734,6 +707,7 @@ static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc)
if (INTEL_INFO(dev_priv)->gen >= 7)
lines = min(lines, 2048);
+ /* Hardware needs the full buffer stride, not just the active area. */
return lines * fb->pitches[0];
}
@@ -832,84 +806,62 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
* __intel_fbc_update - enable/disable FBC as needed, unlocked
* @dev_priv: i915 device instance
*
- * Set up the framebuffer compression hardware at mode set time. We
- * enable it if possible:
- * - plane A only (on pre-965)
- * - no pixel mulitply/line duplication
- * - no alpha buffer discard
- * - no dual wide
- * - framebuffer <= max_hdisplay in width, max_vdisplay in height
- *
- * We can't assume that any compression will take place (worst case),
- * so the compressed buffer has to be the same size as the uncompressed
- * one. It also must reside (along with the line length buffer) in
- * stolen memory.
- *
- * We need to enable/disable FBC on a global basis.
+ * This function completely reevaluates the status of FBC, then enables,
+ * disables or maintains it on the same state.
*/
static void __intel_fbc_update(struct drm_i915_private *dev_priv)
{
- struct drm_crtc *crtc = NULL;
- struct intel_crtc *intel_crtc;
+ struct drm_crtc *drm_crtc = NULL;
+ struct intel_crtc *crtc;
struct drm_framebuffer *fb;
struct drm_i915_gem_object *obj;
const struct drm_display_mode *adjusted_mode;
WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock));
- /* disable framebuffer compression in vGPU */
if (intel_vgpu_active(dev_priv->dev))
i915.enable_fbc = 0;
if (i915.enable_fbc < 0) {
- set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT);
+ set_no_fbc_reason(dev_priv, "disabled per chip default");
goto out_disable;
}
if (!i915.enable_fbc) {
- set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM);
+ set_no_fbc_reason(dev_priv, "disabled per module param");
goto out_disable;
}
- /*
- * If FBC is already on, we just have to verify that we can
- * keep it that way...
- * Need to disable if:
- * - more than one pipe is active
- * - changing FBC params (stride, fence, mode)
- * - new fb is too large to fit in compressed buffer
- * - going to an unsupported config (interlace, pixel multiply, etc.)
- */
- crtc = intel_fbc_find_crtc(dev_priv);
- if (!crtc) {
- set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT);
+ drm_crtc = intel_fbc_find_crtc(dev_priv);
+ if (!drm_crtc) {
+ set_no_fbc_reason(dev_priv, "no output");
goto out_disable;
}
if (!multiple_pipes_ok(dev_priv)) {
- set_no_fbc_reason(dev_priv, FBC_MULTIPLE_PIPES);
+ set_no_fbc_reason(dev_priv, "more than one pipe active");
goto out_disable;
}
- intel_crtc = to_intel_crtc(crtc);
- fb = crtc->primary->fb;
+ crtc = to_intel_crtc(drm_crtc);
+ fb = crtc->base.primary->fb;
obj = intel_fb_obj(fb);
- adjusted_mode = &intel_crtc->config->base.adjusted_mode;
+ adjusted_mode = &crtc->config->base.adjusted_mode;
if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
(adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
- set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE);
+ set_no_fbc_reason(dev_priv, "incompatible mode");
goto out_disable;
}
- if (!intel_fbc_hw_tracking_covers_screen(intel_crtc)) {
- set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE);
+ if (!intel_fbc_hw_tracking_covers_screen(crtc)) {
+ set_no_fbc_reason(dev_priv, "mode too large for compression");
goto out_disable;
}
if ((INTEL_INFO(dev_priv)->gen < 4 || HAS_DDI(dev_priv)) &&
- intel_crtc->plane != PLANE_A) {
- set_no_fbc_reason(dev_priv, FBC_BAD_PLANE);
+ crtc->plane != PLANE_A) {
+ set_no_fbc_reason(dev_priv, "FBC unsupported on plane");
goto out_disable;
}
@@ -918,41 +870,35 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
*/
if (obj->tiling_mode != I915_TILING_X ||
obj->fence_reg == I915_FENCE_REG_NONE) {
- set_no_fbc_reason(dev_priv, FBC_NOT_TILED);
+ set_no_fbc_reason(dev_priv, "framebuffer not tiled or fenced");
goto out_disable;
}
if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) &&
- crtc->primary->state->rotation != BIT(DRM_ROTATE_0)) {
- set_no_fbc_reason(dev_priv, FBC_ROTATION);
+ crtc->base.primary->state->rotation != BIT(DRM_ROTATE_0)) {
+ set_no_fbc_reason(dev_priv, "rotation unsupported");
goto out_disable;
}
if (!stride_is_valid(dev_priv, fb->pitches[0])) {
- set_no_fbc_reason(dev_priv, FBC_BAD_STRIDE);
+ set_no_fbc_reason(dev_priv, "framebuffer stride not supported");
goto out_disable;
}
if (!pixel_format_is_valid(fb)) {
- set_no_fbc_reason(dev_priv, FBC_PIXEL_FORMAT);
- goto out_disable;
- }
-
- /* If the kernel debugger is active, always disable compression */
- if (in_dbg_master()) {
- set_no_fbc_reason(dev_priv, FBC_IN_DBG_MASTER);
+ set_no_fbc_reason(dev_priv, "pixel format is invalid");
goto out_disable;
}
/* WaFbcExceedCdClockThreshold:hsw,bdw */
if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
- ilk_pipe_pixel_rate(intel_crtc->config) >=
+ ilk_pipe_pixel_rate(crtc->config) >=
dev_priv->cdclk_freq * 95 / 100) {
- set_no_fbc_reason(dev_priv, FBC_PIXEL_RATE);
+ set_no_fbc_reason(dev_priv, "pixel rate is too big");
goto out_disable;
}
- if (intel_fbc_setup_cfb(intel_crtc)) {
- set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL);
+ if (intel_fbc_setup_cfb(crtc)) {
+ set_no_fbc_reason(dev_priv, "not enough stolen memory");
goto out_disable;
}
@@ -961,9 +907,9 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
* cannot be unpinned (and have its GTT offset and fence revoked)
* without first being decoupled from the scanout and FBC disabled.
*/
- if (dev_priv->fbc.crtc == intel_crtc &&
+ if (dev_priv->fbc.crtc == crtc &&
dev_priv->fbc.fb_id == fb->base.id &&
- dev_priv->fbc.y == crtc->y)
+ dev_priv->fbc.y == crtc->base.y)
return;
if (intel_fbc_enabled(dev_priv)) {
@@ -994,8 +940,8 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv)
__intel_fbc_disable(dev_priv);
}
- intel_fbc_schedule_enable(intel_crtc);
- dev_priv->fbc.no_fbc_reason = FBC_OK;
+ intel_fbc_schedule_enable(crtc);
+ dev_priv->fbc.no_fbc_reason = "FBC enabled (not necessarily active)";
return;
out_disable:
@@ -1085,10 +1031,10 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
enum pipe pipe;
mutex_init(&dev_priv->fbc.lock);
+ dev_priv->fbc.enabled = false;
if (!HAS_FBC(dev_priv)) {
- dev_priv->fbc.enabled = false;
- dev_priv->fbc.no_fbc_reason = FBC_UNSUPPORTED;
+ dev_priv->fbc.no_fbc_reason = "unsupported by this chipset";
return;
}
@@ -1096,7 +1042,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
dev_priv->fbc.possible_framebuffer_bits |=
INTEL_FRONTBUFFER_PRIMARY(pipe);
- if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
+ if (fbc_on_pipe_a_only(dev_priv))
break;
}
@@ -1121,5 +1067,9 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
}
- dev_priv->fbc.enabled = dev_priv->fbc.fbc_enabled(dev_priv);
+ /* We still don't have any sort of hardware state readout for FBC, so
+ * disable it in case the BIOS enabled it to make sure software matches
+ * the hardware state. */
+ if (dev_priv->fbc.fbc_enabled(dev_priv))
+ dev_priv->fbc.disable_fbc(dev_priv);
}
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 4fd5fdfef6bd..7ccde58f8c98 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -119,7 +119,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
{
struct intel_fbdev *ifbdev =
container_of(helper, struct intel_fbdev, helper);
- struct drm_framebuffer *fb;
+ struct drm_framebuffer *fb = NULL;
struct drm_device *dev = helper->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_mode_fb_cmd2 mode_cmd = {};
@@ -138,6 +138,8 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
+ mutex_lock(&dev->struct_mutex);
+
size = mode_cmd.pitches[0] * mode_cmd.height;
size = PAGE_ALIGN(size);
@@ -156,26 +158,28 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
if (IS_ERR(fb)) {
+ drm_gem_object_unreference(&obj->base);
ret = PTR_ERR(fb);
- goto out_unref;
+ goto out;
}
/* Flush everything out, we'll be doing GTT only from now on */
- ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL, NULL, NULL);
+ ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL);
if (ret) {
DRM_ERROR("failed to pin obj: %d\n", ret);
- goto out_fb;
+ goto out;
}
+ mutex_unlock(&dev->struct_mutex);
+
ifbdev->fb = to_intel_framebuffer(fb);
return 0;
-out_fb:
- drm_framebuffer_remove(fb);
-out_unref:
- drm_gem_object_unreference(&obj->base);
out:
+ mutex_unlock(&dev->struct_mutex);
+ if (!IS_ERR_OR_NULL(fb))
+ drm_framebuffer_unreference(fb);
return ret;
}
@@ -193,8 +197,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
int size, ret;
bool prealloc = false;
- mutex_lock(&dev->struct_mutex);
-
if (intel_fb &&
(sizes->fb_width > intel_fb->base.width ||
sizes->fb_height > intel_fb->base.height)) {
@@ -209,7 +211,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
ret = intelfb_alloc(helper, sizes);
if (ret)
- goto out_unlock;
+ return ret;
intel_fb = ifbdev->fb;
} else {
DRM_DEBUG_KMS("re-using BIOS fb\n");
@@ -221,8 +223,11 @@ static int intelfb_create(struct drm_fb_helper *helper,
obj = intel_fb->obj;
size = obj->base.size;
+ mutex_lock(&dev->struct_mutex);
+
info = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(info)) {
+ DRM_ERROR("Failed to allocate fb_info\n");
ret = PTR_ERR(info);
goto out_unpin;
}
@@ -249,6 +254,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
size);
if (!info->screen_base) {
+ DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
ret = -ENOSPC;
goto out_destroy_fbi;
}
@@ -281,8 +287,6 @@ out_destroy_fbi:
drm_fb_helper_release_fbi(helper);
out_unpin:
i915_gem_object_ggtt_unpin(obj);
- drm_gem_object_unreference(&obj->base);
-out_unlock:
mutex_unlock(&dev->struct_mutex);
return ret;
}
@@ -526,8 +530,10 @@ static void intel_fbdev_destroy(struct drm_device *dev,
drm_fb_helper_fini(&ifbdev->helper);
- drm_framebuffer_unregister_private(&ifbdev->fb->base);
- drm_framebuffer_remove(&ifbdev->fb->base);
+ if (ifbdev->fb) {
+ drm_framebuffer_unregister_private(&ifbdev->fb->base);
+ drm_framebuffer_remove(&ifbdev->fb->base);
+ }
}
/*
@@ -702,13 +708,20 @@ int intel_fbdev_init(struct drm_device *dev)
return 0;
}
-void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
+static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
{
struct drm_i915_private *dev_priv = data;
struct intel_fbdev *ifbdev = dev_priv->fbdev;
/* Due to peculiar init order wrt to hpd handling this is separate. */
- drm_fb_helper_initial_config(&ifbdev->helper, ifbdev->preferred_bpp);
+ if (drm_fb_helper_initial_config(&ifbdev->helper,
+ ifbdev->preferred_bpp))
+ intel_fbdev_fini(dev_priv->dev);
+}
+
+void intel_fbdev_initial_config_async(struct drm_device *dev)
+{
+ async_schedule(intel_fbdev_initial_config, to_i915(dev));
}
void intel_fbdev_fini(struct drm_device *dev)
@@ -719,7 +732,8 @@ void intel_fbdev_fini(struct drm_device *dev)
flush_work(&dev_priv->fbdev_suspend_work);
- async_synchronize_full();
+ if (!current_is_async())
+ async_synchronize_full();
intel_fbdev_destroy(dev, dev_priv->fbdev);
kfree(dev_priv->fbdev);
dev_priv->fbdev = NULL;
diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c
index 54daa66c6970..7ae182d0594b 100644
--- a/drivers/gpu/drm/i915/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c
@@ -84,38 +84,21 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev)
return true;
}
-/**
- * i9xx_check_fifo_underruns - check for fifo underruns
- * @dev_priv: i915 device instance
- *
- * This function checks for fifo underruns on GMCH platforms. This needs to be
- * done manually on modeset to make sure that we catch all underruns since they
- * do not generate an interrupt by themselves on these platforms.
- */
-void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv)
+static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
{
- struct intel_crtc *crtc;
-
- spin_lock_irq(&dev_priv->irq_lock);
-
- for_each_intel_crtc(dev_priv->dev, crtc) {
- u32 reg = PIPESTAT(crtc->pipe);
- u32 pipestat;
-
- if (crtc->cpu_fifo_underrun_disabled)
- continue;
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ i915_reg_t reg = PIPESTAT(crtc->pipe);
+ u32 pipestat = I915_READ(reg) & 0xffff0000;
- pipestat = I915_READ(reg) & 0xffff0000;
- if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0)
- continue;
+ assert_spin_locked(&dev_priv->irq_lock);
- I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
- POSTING_READ(reg);
+ if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0)
+ return;
- DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
- }
+ I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
+ POSTING_READ(reg);
- spin_unlock_irq(&dev_priv->irq_lock);
+ DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
}
static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
@@ -123,7 +106,7 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
bool enable, bool old)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 reg = PIPESTAT(pipe);
+ i915_reg_t reg = PIPESTAT(pipe);
u32 pipestat = I915_READ(reg) & 0xffff0000;
assert_spin_locked(&dev_priv->irq_lock);
@@ -150,6 +133,23 @@ static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
ironlake_disable_display_irq(dev_priv, bit);
}
+static void ivybridge_check_fifo_underruns(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+ uint32_t err_int = I915_READ(GEN7_ERR_INT);
+
+ assert_spin_locked(&dev_priv->irq_lock);
+
+ if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0)
+ return;
+
+ I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
+ POSTING_READ(GEN7_ERR_INT);
+
+ DRM_ERROR("fifo underrun on pipe %c\n", pipe_name(pipe));
+}
+
static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe,
bool enable, bool old)
@@ -202,6 +202,24 @@ static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
ibx_disable_display_interrupt(dev_priv, bit);
}
+static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum transcoder pch_transcoder = (enum transcoder) crtc->pipe;
+ uint32_t serr_int = I915_READ(SERR_INT);
+
+ assert_spin_locked(&dev_priv->irq_lock);
+
+ if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0)
+ return;
+
+ I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
+ POSTING_READ(SERR_INT);
+
+ DRM_ERROR("pch fifo underrun on pch transcoder %c\n",
+ transcoder_name(pch_transcoder));
+}
+
static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
enum transcoder pch_transcoder,
bool enable, bool old)
@@ -375,3 +393,56 @@ void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
DRM_ERROR("PCH transcoder %c FIFO underrun\n",
transcoder_name(pch_transcoder));
}
+
+/**
+ * intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately
+ * @dev_priv: i915 device instance
+ *
+ * Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared
+ * error interrupt may have been disabled, and so CPU fifo underruns won't
+ * necessarily raise an interrupt, and on GMCH platforms where underruns never
+ * raise an interrupt.
+ */
+void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
+{
+ struct intel_crtc *crtc;
+
+ spin_lock_irq(&dev_priv->irq_lock);
+
+ for_each_intel_crtc(dev_priv->dev, crtc) {
+ if (crtc->cpu_fifo_underrun_disabled)
+ continue;
+
+ if (HAS_GMCH_DISPLAY(dev_priv))
+ i9xx_check_fifo_underruns(crtc);
+ else if (IS_GEN7(dev_priv))
+ ivybridge_check_fifo_underruns(crtc);
+ }
+
+ spin_unlock_irq(&dev_priv->irq_lock);
+}
+
+/**
+ * intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately
+ * @dev_priv: i915 device instance
+ *
+ * Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared
+ * error interrupt may have been disabled, and so PCH fifo underruns won't
+ * necessarily raise an interrupt.
+ */
+void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv)
+{
+ struct intel_crtc *crtc;
+
+ spin_lock_irq(&dev_priv->irq_lock);
+
+ for_each_intel_crtc(dev_priv->dev, crtc) {
+ if (crtc->pch_fifo_underrun_disabled)
+ continue;
+
+ if (HAS_PCH_CPT(dev_priv))
+ cpt_check_pch_fifo_underruns(crtc);
+ }
+
+ spin_unlock_irq(&dev_priv->irq_lock);
+}
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 081d5f648d26..5ba586683c87 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -76,11 +76,17 @@ struct intel_guc_fw {
uint16_t guc_fw_minor_wanted;
uint16_t guc_fw_major_found;
uint16_t guc_fw_minor_found;
+
+ uint32_t header_size;
+ uint32_t header_offset;
+ uint32_t rsa_size;
+ uint32_t rsa_offset;
+ uint32_t ucode_size;
+ uint32_t ucode_offset;
};
struct intel_guc {
struct intel_guc_fw guc_fw;
-
uint32_t log_flags;
struct drm_i915_gem_object *log_obj;
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 593d2f585978..40b2ea572e16 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -122,6 +122,78 @@
#define GUC_CTL_MAX_DWORDS (GUC_CTL_RSRVD + 1)
+/**
+ * DOC: GuC Firmware Layout
+ *
+ * The GuC firmware layout looks like this:
+ *
+ * +-------------------------------+
+ * | guc_css_header |
+ * | contains major/minor version |
+ * +-------------------------------+
+ * | uCode |
+ * +-------------------------------+
+ * | RSA signature |
+ * +-------------------------------+
+ * | modulus key |
+ * +-------------------------------+
+ * | exponent val |
+ * +-------------------------------+
+ *
+ * The firmware may or may not have modulus key and exponent data. The header,
+ * uCode and RSA signature are must-have components that will be used by driver.
+ * Length of each components, which is all in dwords, can be found in header.
+ * In the case that modulus and exponent are not present in fw, a.k.a truncated
+ * image, the length value still appears in header.
+ *
+ * Driver will do some basic fw size validation based on the following rules:
+ *
+ * 1. Header, uCode and RSA are must-have components.
+ * 2. All firmware components, if they present, are in the sequence illustrated
+ * in the layout table above.
+ * 3. Length info of each component can be found in header, in dwords.
+ * 4. Modulus and exponent key are not required by driver. They may not appear
+ * in fw. So driver will load a truncated firmware in this case.
+ */
+
+struct guc_css_header {
+ uint32_t module_type;
+ /* header_size includes all non-uCode bits, including css_header, rsa
+ * key, modulus key and exponent data. */
+ uint32_t header_size_dw;
+ uint32_t header_version;
+ uint32_t module_id;
+ uint32_t module_vendor;
+ union {
+ struct {
+ uint8_t day;
+ uint8_t month;
+ uint16_t year;
+ };
+ uint32_t date;
+ };
+ uint32_t size_dw; /* uCode plus header_size_dw */
+ uint32_t key_size_dw;
+ uint32_t modulus_size_dw;
+ uint32_t exponent_size_dw;
+ union {
+ struct {
+ uint8_t hour;
+ uint8_t min;
+ uint16_t sec;
+ };
+ uint32_t time;
+ };
+
+ char username[8];
+ char buildnumber[12];
+ uint32_t device_id;
+ uint32_t guc_sw_version;
+ uint32_t prod_preprod_fw;
+ uint32_t reserved[12];
+ uint32_t header_info;
+} __packed;
+
struct guc_doorbell_info {
u32 db_status;
u32 cookie;
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index 3541f76c65a7..550921f2ef7d 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -31,7 +31,7 @@
#include "intel_guc.h"
/**
- * DOC: GuC
+ * DOC: GuC-specific firmware loader
*
* intel_guc:
* Top level structure of guc. It handles firmware loading and manages client
@@ -208,16 +208,6 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv,
/*
* Transfer the firmware image to RAM for execution by the microcontroller.
*
- * GuC Firmware layout:
- * +-------------------------------+ ----
- * | CSS header | 128B
- * | contains major/minor version |
- * +-------------------------------+ ----
- * | uCode |
- * +-------------------------------+ ----
- * | RSA signature | 256B
- * +-------------------------------+ ----
- *
* Architecturally, the DMA engine is bidirectional, and can potentially even
* transfer between GTT locations. This functionality is left out of the API
* for now as there is no need for it.
@@ -225,33 +215,29 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv,
* Note that GuC needs the CSS header plus uKernel code to be copied by the
* DMA engine in one operation, whereas the RSA signature is loaded via MMIO.
*/
-
-#define UOS_CSS_HEADER_OFFSET 0
-#define UOS_VER_MINOR_OFFSET 0x44
-#define UOS_VER_MAJOR_OFFSET 0x46
-#define UOS_CSS_HEADER_SIZE 0x80
-#define UOS_RSA_SIG_SIZE 0x100
-
static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
{
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
struct drm_i915_gem_object *fw_obj = guc_fw->guc_fw_obj;
unsigned long offset;
struct sg_table *sg = fw_obj->pages;
- u32 status, ucode_size, rsa[UOS_RSA_SIG_SIZE / sizeof(u32)];
+ u32 status, rsa[UOS_RSA_SCRATCH_MAX_COUNT];
int i, ret = 0;
- /* uCode size, also is where RSA signature starts */
- offset = ucode_size = guc_fw->guc_fw_size - UOS_RSA_SIG_SIZE;
- I915_WRITE(DMA_COPY_SIZE, ucode_size);
+ /* where RSA signature starts */
+ offset = guc_fw->rsa_offset;
/* Copy RSA signature from the fw image to HW for verification */
- sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, UOS_RSA_SIG_SIZE, offset);
- for (i = 0; i < UOS_RSA_SIG_SIZE / sizeof(u32); i++)
+ sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, sizeof(rsa), offset);
+ for (i = 0; i < UOS_RSA_SCRATCH_MAX_COUNT; i++)
I915_WRITE(UOS_RSA_SCRATCH(i), rsa[i]);
+ /* The header plus uCode will be copied to WOPCM via DMA, excluding any
+ * other components */
+ I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size);
+
/* Set the source address for the new blob */
- offset = i915_gem_obj_ggtt_offset(fw_obj);
+ offset = i915_gem_obj_ggtt_offset(fw_obj) + guc_fw->header_offset;
I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset));
I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF);
@@ -322,8 +308,8 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
/* WaDisableMinuteIaClockGating:skl,bxt */
- if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) ||
- (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) {
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) &
~GUC_ENABLE_MIA_CLOCK_GATING));
}
@@ -378,6 +364,9 @@ int intel_guc_ucode_load(struct drm_device *dev)
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
int err = 0;
+ if (!i915.enable_guc_submission)
+ return 0;
+
DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
@@ -457,10 +446,8 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
{
struct drm_i915_gem_object *obj;
const struct firmware *fw;
- const u8 *css_header;
- const size_t minsize = UOS_CSS_HEADER_SIZE + UOS_RSA_SIG_SIZE;
- const size_t maxsize = GUC_WOPCM_SIZE_VALUE + UOS_RSA_SIG_SIZE
- - 0x8000; /* 32k reserved (8K stack + 24k context) */
+ struct guc_css_header *css;
+ size_t size;
int err;
DRM_DEBUG_DRIVER("before requesting firmware: GuC fw fetch status %s\n",
@@ -474,12 +461,52 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
DRM_DEBUG_DRIVER("fetch GuC fw from %s succeeded, fw %p\n",
guc_fw->guc_fw_path, fw);
- DRM_DEBUG_DRIVER("firmware file size %zu (minimum %zu, maximum %zu)\n",
- fw->size, minsize, maxsize);
- /* Check the size of the blob befoe examining buffer contents */
- if (fw->size < minsize || fw->size > maxsize)
+ /* Check the size of the blob before examining buffer contents */
+ if (fw->size < sizeof(struct guc_css_header)) {
+ DRM_ERROR("Firmware header is missing\n");
goto fail;
+ }
+
+ css = (struct guc_css_header *)fw->data;
+
+ /* Firmware bits always start from header */
+ guc_fw->header_offset = 0;
+ guc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
+ css->key_size_dw - css->exponent_size_dw) * sizeof(u32);
+
+ if (guc_fw->header_size != sizeof(struct guc_css_header)) {
+ DRM_ERROR("CSS header definition mismatch\n");
+ goto fail;
+ }
+
+ /* then, uCode */
+ guc_fw->ucode_offset = guc_fw->header_offset + guc_fw->header_size;
+ guc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
+
+ /* now RSA */
+ if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) {
+ DRM_ERROR("RSA key size is bad\n");
+ goto fail;
+ }
+ guc_fw->rsa_offset = guc_fw->ucode_offset + guc_fw->ucode_size;
+ guc_fw->rsa_size = css->key_size_dw * sizeof(u32);
+
+ /* At least, it should have header, uCode and RSA. Size of all three. */
+ size = guc_fw->header_size + guc_fw->ucode_size + guc_fw->rsa_size;
+ if (fw->size < size) {
+ DRM_ERROR("Missing firmware components\n");
+ goto fail;
+ }
+
+ /* Header and uCode will be loaded to WOPCM. Size of the two. */
+ size = guc_fw->header_size + guc_fw->ucode_size;
+
+ /* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
+ if (size > GUC_WOPCM_SIZE_VALUE - 0x8000) {
+ DRM_ERROR("Firmware is too large to fit in WOPCM\n");
+ goto fail;
+ }
/*
* The GuC firmware image has the version number embedded at a well-known
@@ -487,9 +514,8 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
* TWO bytes each (i.e. u16), although all pointers and offsets are defined
* in terms of bytes (u8).
*/
- css_header = fw->data + UOS_CSS_HEADER_OFFSET;
- guc_fw->guc_fw_major_found = *(u16 *)(css_header + UOS_VER_MAJOR_OFFSET);
- guc_fw->guc_fw_minor_found = *(u16 *)(css_header + UOS_VER_MINOR_OFFSET);
+ guc_fw->guc_fw_major_found = css->guc_sw_version >> 16;
+ guc_fw->guc_fw_minor_found = css->guc_sw_version & 0xFFFF;
if (guc_fw->guc_fw_major_found != guc_fw->guc_fw_major_wanted ||
guc_fw->guc_fw_minor_found < guc_fw->guc_fw_minor_wanted) {
@@ -566,6 +592,9 @@ void intel_guc_ucode_init(struct drm_device *dev)
fw_path = ""; /* unknown device */
}
+ if (!i915.enable_guc_submission)
+ return;
+
guc_fw->guc_dev = dev;
guc_fw->guc_fw_path = fw_path;
guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index e6c035b0fc1c..f16cd2a843b2 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -113,10 +113,11 @@ static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
}
}
-static u32 hsw_dip_data_reg(struct drm_i915_private *dev_priv,
- enum transcoder cpu_transcoder,
- enum hdmi_infoframe_type type,
- int i)
+static i915_reg_t
+hsw_dip_data_reg(struct drm_i915_private *dev_priv,
+ enum transcoder cpu_transcoder,
+ enum hdmi_infoframe_type type,
+ int i)
{
switch (type) {
case HDMI_INFOFRAME_TYPE_AVI:
@@ -127,7 +128,7 @@ static u32 hsw_dip_data_reg(struct drm_i915_private *dev_priv,
return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i);
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", type);
- return 0;
+ return INVALID_MMIO_REG;
}
}
@@ -193,8 +194,9 @@ static void ibx_write_infoframe(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
- int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
u32 val = I915_READ(reg);
+ int i;
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
@@ -229,7 +231,7 @@ static bool ibx_infoframe_enabled(struct drm_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
- int reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
u32 val = I915_READ(reg);
if ((val & VIDEO_DIP_ENABLE) == 0)
@@ -251,8 +253,9 @@ static void cpt_write_infoframe(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
- int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
u32 val = I915_READ(reg);
+ int i;
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
@@ -289,8 +292,7 @@ static bool cpt_infoframe_enabled(struct drm_encoder *encoder)
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
- int reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
- u32 val = I915_READ(reg);
+ u32 val = I915_READ(TVIDEO_DIP_CTL(intel_crtc->pipe));
if ((val & VIDEO_DIP_ENABLE) == 0)
return false;
@@ -308,8 +310,9 @@ static void vlv_write_infoframe(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
- int i, reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
u32 val = I915_READ(reg);
+ int i;
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n");
@@ -344,8 +347,7 @@ static bool vlv_infoframe_enabled(struct drm_encoder *encoder)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
- int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
- u32 val = I915_READ(reg);
+ u32 val = I915_READ(VLV_TVIDEO_DIP_CTL(intel_crtc->pipe));
if ((val & VIDEO_DIP_ENABLE) == 0)
return false;
@@ -367,13 +369,13 @@ static void hsw_write_infoframe(struct drm_encoder *encoder,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
- u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
- u32 data_reg;
+ i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
+ i915_reg_t data_reg;
int i;
u32 val = I915_READ(ctl_reg);
data_reg = hsw_dip_data_reg(dev_priv, cpu_transcoder, type, 0);
- if (data_reg == 0)
+ if (i915_mmio_reg_valid(data_reg))
return;
val &= ~hsw_infoframe_enable(type);
@@ -401,8 +403,7 @@ static bool hsw_infoframe_enabled(struct drm_encoder *encoder)
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
- u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder);
- u32 val = I915_READ(ctl_reg);
+ u32 val = I915_READ(HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder));
return val & (VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW |
VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW |
@@ -513,7 +514,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
- u32 reg = VIDEO_DIP_CTL;
+ i915_reg_t reg = VIDEO_DIP_CTL;
u32 val = I915_READ(reg);
u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
@@ -633,7 +634,8 @@ static bool intel_hdmi_set_gcp_infoframe(struct drm_encoder *encoder)
{
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
- u32 reg, val = 0;
+ i915_reg_t reg;
+ u32 val = 0;
if (HAS_DDI(dev_priv))
reg = HSW_TVIDEO_DIP_GCP(crtc->config->cpu_transcoder);
@@ -666,7 +668,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
- u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
u32 val = I915_READ(reg);
u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
@@ -717,7 +719,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
- u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
u32 val = I915_READ(reg);
assert_hdmi_port_disabled(intel_hdmi);
@@ -760,7 +762,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
- u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
+ i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
u32 val = I915_READ(reg);
u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
@@ -811,7 +813,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
- u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder);
+ i915_reg_t reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder);
u32 val = I915_READ(reg);
assert_hdmi_port_disabled(intel_hdmi);
@@ -1108,6 +1110,13 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
* matching DP port to be enabled on transcoder A.
*/
if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B) {
+ /*
+ * We get CPU/PCH FIFO underruns on the other pipe when
+ * doing the workaround. Sweep them under the rug.
+ */
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false);
+ intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
+
temp &= ~SDVO_PIPE_B_SELECT;
temp |= SDVO_ENABLE;
/*
@@ -1122,6 +1131,10 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
temp &= ~SDVO_ENABLE;
I915_WRITE(intel_hdmi->hdmi_reg, temp);
POSTING_READ(intel_hdmi->hdmi_reg);
+
+ intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A);
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
+ intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
}
intel_hdmi->set_infoframes(&encoder->base, false, NULL);
@@ -1338,14 +1351,15 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force)
struct edid *edid = NULL;
bool connected = false;
- intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+ if (force) {
+ intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
- if (force)
edid = drm_get_edid(connector,
intel_gmbus_get_adapter(dev_priv,
intel_hdmi->ddc_bus));
- intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+ intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+ }
to_intel_connector(connector)->detect_edid = edid;
if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
@@ -2040,7 +2054,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
* On BXT A0/A1, sw needs to activate DDIA HPD logic and
* interrupts to check the external panel connection.
*/
- if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0))
+ if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
intel_encoder->hpd_pin = HPD_PORT_A;
else
intel_encoder->hpd_pin = HPD_PORT_B;
@@ -2132,8 +2146,10 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
}
}
-void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
+void intel_hdmi_init(struct drm_device *dev,
+ i915_reg_t hdmi_reg, enum port port)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_digital_port *intel_dig_port;
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
@@ -2202,8 +2218,9 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
intel_dig_port->port = port;
+ dev_priv->dig_port_map[port] = intel_encoder;
intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
- intel_dig_port->dp.output_reg = 0;
+ intel_dig_port->dp.output_reg = INVALID_MMIO_REG;
intel_hdmi_init_connector(intel_dig_port, intel_connector);
}
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 8324654037b6..1110c83953cf 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -36,7 +36,7 @@
struct gmbus_pin {
const char *name;
- int reg;
+ i915_reg_t reg;
};
/* Map gmbus pin pairs to names and registers. */
@@ -63,9 +63,9 @@ static const struct gmbus_pin gmbus_pins_skl[] = {
};
static const struct gmbus_pin gmbus_pins_bxt[] = {
- [GMBUS_PIN_1_BXT] = { "dpb", PCH_GPIOB },
- [GMBUS_PIN_2_BXT] = { "dpc", PCH_GPIOC },
- [GMBUS_PIN_3_BXT] = { "misc", PCH_GPIOD },
+ [GMBUS_PIN_1_BXT] = { "dpb", GPIOB },
+ [GMBUS_PIN_2_BXT] = { "dpc", GPIOC },
+ [GMBUS_PIN_3_BXT] = { "misc", GPIOD },
};
/* pin is expected to be valid */
@@ -74,7 +74,7 @@ static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *dev_priv,
{
if (IS_BROXTON(dev_priv))
return &gmbus_pins_bxt[pin];
- else if (IS_SKYLAKE(dev_priv))
+ else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
return &gmbus_pins_skl[pin];
else if (IS_BROADWELL(dev_priv))
return &gmbus_pins_bdw[pin];
@@ -89,14 +89,15 @@ bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
if (IS_BROXTON(dev_priv))
size = ARRAY_SIZE(gmbus_pins_bxt);
- else if (IS_SKYLAKE(dev_priv))
+ else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
size = ARRAY_SIZE(gmbus_pins_skl);
else if (IS_BROADWELL(dev_priv))
size = ARRAY_SIZE(gmbus_pins_bdw);
else
size = ARRAY_SIZE(gmbus_pins);
- return pin < size && get_gmbus_pin(dev_priv, pin)->reg;
+ return pin < size &&
+ i915_mmio_reg_valid(get_gmbus_pin(dev_priv, pin)->reg);
}
/* Intel GPIO access functions */
@@ -240,9 +241,8 @@ intel_gpio_setup(struct intel_gmbus *bus, unsigned int pin)
algo = &bus->bit_algo;
- bus->gpio_reg = dev_priv->gpio_mmio_base +
- get_gmbus_pin(dev_priv, pin)->reg;
-
+ bus->gpio_reg = _MMIO(dev_priv->gpio_mmio_base +
+ i915_mmio_reg_offset(get_gmbus_pin(dev_priv, pin)->reg));
bus->adapter.algo_data = algo;
algo->setsda = set_data;
algo->setscl = set_clock;
@@ -628,12 +628,13 @@ int intel_setup_gmbus(struct drm_device *dev)
if (HAS_PCH_NOP(dev))
return 0;
- else if (HAS_PCH_SPLIT(dev))
- dev_priv->gpio_mmio_base = PCH_GPIOA - GPIOA;
- else if (IS_VALLEYVIEW(dev))
+
+ if (IS_VALLEYVIEW(dev))
dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE;
- else
- dev_priv->gpio_mmio_base = 0;
+ else if (!HAS_GMCH_DISPLAY(dev_priv))
+ dev_priv->gpio_mmio_base =
+ i915_mmio_reg_offset(PCH_GPIOA) -
+ i915_mmio_reg_offset(GPIOA);
mutex_init(&dev_priv->gmbus_mutex);
init_waitqueue_head(&dev_priv->gmbus_wait_queue);
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 88e12bdf79e2..4ebafab53f30 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -190,16 +190,21 @@
#define GEN8_CTX_L3LLC_COHERENT (1<<5)
#define GEN8_CTX_PRIVILEGE (1<<8)
-#define ASSIGN_CTX_PDP(ppgtt, reg_state, n) { \
+#define ASSIGN_CTX_REG(reg_state, pos, reg, val) do { \
+ (reg_state)[(pos)+0] = i915_mmio_reg_offset(reg); \
+ (reg_state)[(pos)+1] = (val); \
+} while (0)
+
+#define ASSIGN_CTX_PDP(ppgtt, reg_state, n) do { \
const u64 _addr = i915_page_dir_dma_addr((ppgtt), (n)); \
reg_state[CTX_PDP ## n ## _UDW+1] = upper_32_bits(_addr); \
reg_state[CTX_PDP ## n ## _LDW+1] = lower_32_bits(_addr); \
-}
+} while (0)
-#define ASSIGN_CTX_PML4(ppgtt, reg_state) { \
+#define ASSIGN_CTX_PML4(ppgtt, reg_state) do { \
reg_state[CTX_PDP0_UDW + 1] = upper_32_bits(px_dma(&ppgtt->pml4)); \
reg_state[CTX_PDP0_LDW + 1] = lower_32_bits(px_dma(&ppgtt->pml4)); \
-}
+} while (0)
enum {
ADVANCED_CONTEXT = 0,
@@ -284,8 +289,8 @@ static bool disable_lite_restore_wa(struct intel_engine_cs *ring)
{
struct drm_device *dev = ring->dev;
- return ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) ||
- (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) &&
+ return (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1)) &&
(ring->id == VCS || ring->id == VCS2);
}
@@ -921,7 +926,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
intel_logical_ring_emit(ringbuf, MI_NOOP);
intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1));
- intel_logical_ring_emit(ringbuf, INSTPM);
+ intel_logical_ring_emit_reg(ringbuf, INSTPM);
intel_logical_ring_emit(ringbuf, instp_mask << 16 | instp_mode);
intel_logical_ring_advance(ringbuf);
@@ -1096,7 +1101,7 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(w->count));
for (i = 0; i < w->count; i++) {
- intel_logical_ring_emit(ringbuf, w->reg[i].addr);
+ intel_logical_ring_emit_reg(ringbuf, w->reg[i].addr);
intel_logical_ring_emit(ringbuf, w->reg[i].value);
}
intel_logical_ring_emit(ringbuf, MI_NOOP);
@@ -1120,6 +1125,8 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
batch[__index] = (cmd); \
} while (0)
+#define wa_ctx_emit_reg(batch, index, reg) \
+ wa_ctx_emit((batch), (index), i915_mmio_reg_offset(reg))
/*
* In this WA we need to set GEN8_L3SQCREG4[21:21] and reset it after
@@ -1149,17 +1156,17 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring,
* this batch updates GEN8_L3SQCREG4 with default value we need to
* set this bit here to retain the WA during flush.
*/
- if (IS_SKYLAKE(ring->dev) && INTEL_REVID(ring->dev) <= SKL_REVID_E0)
+ if (IS_SKL_REVID(ring->dev, 0, SKL_REVID_E0))
l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS;
wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
MI_SRM_LRM_GLOBAL_GTT));
- wa_ctx_emit(batch, index, GEN8_L3SQCREG4);
+ wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256);
wa_ctx_emit(batch, index, 0);
wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1));
- wa_ctx_emit(batch, index, GEN8_L3SQCREG4);
+ wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
wa_ctx_emit(batch, index, l3sqc4_flush);
wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6));
@@ -1172,7 +1179,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring,
wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8 |
MI_SRM_LRM_GLOBAL_GTT));
- wa_ctx_emit(batch, index, GEN8_L3SQCREG4);
+ wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256);
wa_ctx_emit(batch, index, 0);
@@ -1314,8 +1321,8 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *ring,
uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
/* WaDisableCtxRestoreArbitration:skl,bxt */
- if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) <= SKL_REVID_D0)) ||
- (IS_BROXTON(dev) && (INTEL_REVID(dev) == BXT_REVID_A0)))
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) ||
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1))
wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE);
/* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */
@@ -1340,18 +1347,18 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *ring,
uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
- if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) <= SKL_REVID_B0)) ||
- (IS_BROXTON(dev) && (INTEL_REVID(dev) == BXT_REVID_A0))) {
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1));
- wa_ctx_emit(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0);
+ wa_ctx_emit_reg(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0);
wa_ctx_emit(batch, index,
_MASKED_BIT_ENABLE(DISABLE_PIXEL_MASK_CAMMING));
wa_ctx_emit(batch, index, MI_NOOP);
}
/* WaDisableCtxRestoreArbitration:skl,bxt */
- if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) <= SKL_REVID_D0)) ||
- (IS_BROXTON(dev) && (INTEL_REVID(dev) == BXT_REVID_A0)))
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) ||
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1))
wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_ENABLE);
wa_ctx_emit(batch, index, MI_BATCH_BUFFER_END);
@@ -1472,12 +1479,6 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
- if (ring->status_page.obj) {
- I915_WRITE(RING_HWS_PGA(ring->mmio_base),
- (u32)ring->status_page.gfx_addr);
- POSTING_READ(RING_HWS_PGA(ring->mmio_base));
- }
-
I915_WRITE(RING_MODE_GEN7(ring),
_MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
_MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
@@ -1562,9 +1563,9 @@ static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req)
for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) {
const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
- intel_logical_ring_emit(ringbuf, GEN8_RING_PDP_UDW(ring, i));
+ intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_UDW(ring, i));
intel_logical_ring_emit(ringbuf, upper_32_bits(pd_daddr));
- intel_logical_ring_emit(ringbuf, GEN8_RING_PDP_LDW(ring, i));
+ intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_LDW(ring, i));
intel_logical_ring_emit(ringbuf, lower_32_bits(pd_daddr));
}
@@ -1923,6 +1924,7 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin
i915_gem_batch_pool_init(dev, &ring->batch_pool);
init_waitqueue_head(&ring->irq_queue);
+ INIT_LIST_HEAD(&ring->buffers);
INIT_LIST_HEAD(&ring->execlist_queue);
INIT_LIST_HEAD(&ring->execlist_retired_req_list);
spin_lock_init(&ring->execlist_lock);
@@ -1972,7 +1974,7 @@ static int logical_render_ring_init(struct drm_device *dev)
ring->init_hw = gen8_init_render_ring;
ring->init_context = gen8_init_rcs_context;
ring->cleanup = intel_fini_pipe_control;
- if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) {
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
ring->get_seqno = bxt_a_get_seqno;
ring->set_seqno = bxt_a_set_seqno;
} else {
@@ -2024,7 +2026,7 @@ static int logical_bsd_ring_init(struct drm_device *dev)
GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT;
ring->init_hw = gen8_init_common_ring;
- if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) {
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
ring->get_seqno = bxt_a_get_seqno;
ring->set_seqno = bxt_a_set_seqno;
} else {
@@ -2079,7 +2081,7 @@ static int logical_blt_ring_init(struct drm_device *dev)
GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
ring->init_hw = gen8_init_common_ring;
- if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) {
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
ring->get_seqno = bxt_a_get_seqno;
ring->set_seqno = bxt_a_set_seqno;
} else {
@@ -2109,7 +2111,7 @@ static int logical_vebox_ring_init(struct drm_device *dev)
GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT;
ring->init_hw = gen8_init_common_ring;
- if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) {
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
ring->get_seqno = bxt_a_get_seqno;
ring->set_seqno = bxt_a_set_seqno;
} else {
@@ -2263,46 +2265,31 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
* only for the first context restore: on a subsequent save, the GPU will
* recreate this batchbuffer with new values (including all the missing
* MI_LOAD_REGISTER_IMM commands that we are not initializing here). */
- if (ring->id == RCS)
- reg_state[CTX_LRI_HEADER_0] = MI_LOAD_REGISTER_IMM(14);
- else
- reg_state[CTX_LRI_HEADER_0] = MI_LOAD_REGISTER_IMM(11);
- reg_state[CTX_LRI_HEADER_0] |= MI_LRI_FORCE_POSTED;
- reg_state[CTX_CONTEXT_CONTROL] = RING_CONTEXT_CONTROL(ring);
- reg_state[CTX_CONTEXT_CONTROL+1] =
- _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH |
- CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT |
- CTX_CTRL_RS_CTX_ENABLE);
- reg_state[CTX_RING_HEAD] = RING_HEAD(ring->mmio_base);
- reg_state[CTX_RING_HEAD+1] = 0;
- reg_state[CTX_RING_TAIL] = RING_TAIL(ring->mmio_base);
- reg_state[CTX_RING_TAIL+1] = 0;
- reg_state[CTX_RING_BUFFER_START] = RING_START(ring->mmio_base);
+ reg_state[CTX_LRI_HEADER_0] =
+ MI_LOAD_REGISTER_IMM(ring->id == RCS ? 14 : 11) | MI_LRI_FORCE_POSTED;
+ ASSIGN_CTX_REG(reg_state, CTX_CONTEXT_CONTROL, RING_CONTEXT_CONTROL(ring),
+ _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH |
+ CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT |
+ CTX_CTRL_RS_CTX_ENABLE));
+ ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(ring->mmio_base), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(ring->mmio_base), 0);
/* Ring buffer start address is not known until the buffer is pinned.
* It is written to the context image in execlists_update_context()
*/
- reg_state[CTX_RING_BUFFER_CONTROL] = RING_CTL(ring->mmio_base);
- reg_state[CTX_RING_BUFFER_CONTROL+1] =
- ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID;
- reg_state[CTX_BB_HEAD_U] = ring->mmio_base + 0x168;
- reg_state[CTX_BB_HEAD_U+1] = 0;
- reg_state[CTX_BB_HEAD_L] = ring->mmio_base + 0x140;
- reg_state[CTX_BB_HEAD_L+1] = 0;
- reg_state[CTX_BB_STATE] = ring->mmio_base + 0x110;
- reg_state[CTX_BB_STATE+1] = (1<<5);
- reg_state[CTX_SECOND_BB_HEAD_U] = ring->mmio_base + 0x11c;
- reg_state[CTX_SECOND_BB_HEAD_U+1] = 0;
- reg_state[CTX_SECOND_BB_HEAD_L] = ring->mmio_base + 0x114;
- reg_state[CTX_SECOND_BB_HEAD_L+1] = 0;
- reg_state[CTX_SECOND_BB_STATE] = ring->mmio_base + 0x118;
- reg_state[CTX_SECOND_BB_STATE+1] = 0;
+ ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START, RING_START(ring->mmio_base), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, RING_CTL(ring->mmio_base),
+ ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID);
+ ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U, RING_BBADDR_UDW(ring->mmio_base), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L, RING_BBADDR(ring->mmio_base), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_BB_STATE, RING_BBSTATE(ring->mmio_base),
+ RING_BB_PPGTT);
+ ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_U, RING_SBBADDR_UDW(ring->mmio_base), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_L, RING_SBBADDR(ring->mmio_base), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_STATE, RING_SBBSTATE(ring->mmio_base), 0);
if (ring->id == RCS) {
- reg_state[CTX_BB_PER_CTX_PTR] = ring->mmio_base + 0x1c0;
- reg_state[CTX_BB_PER_CTX_PTR+1] = 0;
- reg_state[CTX_RCS_INDIRECT_CTX] = ring->mmio_base + 0x1c4;
- reg_state[CTX_RCS_INDIRECT_CTX+1] = 0;
- reg_state[CTX_RCS_INDIRECT_CTX_OFFSET] = ring->mmio_base + 0x1c8;
- reg_state[CTX_RCS_INDIRECT_CTX_OFFSET+1] = 0;
+ ASSIGN_CTX_REG(reg_state, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(ring->mmio_base), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX, RING_INDIRECT_CTX(ring->mmio_base), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX_OFFSET, RING_INDIRECT_CTX_OFFSET(ring->mmio_base), 0);
if (ring->wa_ctx.obj) {
struct i915_ctx_workarounds *wa_ctx = &ring->wa_ctx;
uint32_t ggtt_offset = i915_gem_obj_ggtt_offset(wa_ctx->obj);
@@ -2319,18 +2306,17 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
0x01;
}
}
- reg_state[CTX_LRI_HEADER_1] = MI_LOAD_REGISTER_IMM(9);
- reg_state[CTX_LRI_HEADER_1] |= MI_LRI_FORCE_POSTED;
- reg_state[CTX_CTX_TIMESTAMP] = ring->mmio_base + 0x3a8;
- reg_state[CTX_CTX_TIMESTAMP+1] = 0;
- reg_state[CTX_PDP3_UDW] = GEN8_RING_PDP_UDW(ring, 3);
- reg_state[CTX_PDP3_LDW] = GEN8_RING_PDP_LDW(ring, 3);
- reg_state[CTX_PDP2_UDW] = GEN8_RING_PDP_UDW(ring, 2);
- reg_state[CTX_PDP2_LDW] = GEN8_RING_PDP_LDW(ring, 2);
- reg_state[CTX_PDP1_UDW] = GEN8_RING_PDP_UDW(ring, 1);
- reg_state[CTX_PDP1_LDW] = GEN8_RING_PDP_LDW(ring, 1);
- reg_state[CTX_PDP0_UDW] = GEN8_RING_PDP_UDW(ring, 0);
- reg_state[CTX_PDP0_LDW] = GEN8_RING_PDP_LDW(ring, 0);
+ reg_state[CTX_LRI_HEADER_1] = MI_LOAD_REGISTER_IMM(9) | MI_LRI_FORCE_POSTED;
+ ASSIGN_CTX_REG(reg_state, CTX_CTX_TIMESTAMP, RING_CTX_TIMESTAMP(ring->mmio_base), 0);
+ /* PDP values well be assigned later if needed */
+ ASSIGN_CTX_REG(reg_state, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(ring, 3), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(ring, 3), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(ring, 2), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(ring, 2), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(ring, 1), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(ring, 1), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(ring, 0), 0);
+ ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(ring, 0), 0);
if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
/* 64b PPGTT (48bit canonical)
@@ -2352,8 +2338,8 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
if (ring->id == RCS) {
reg_state[CTX_LRI_HEADER_2] = MI_LOAD_REGISTER_IMM(1);
- reg_state[CTX_R_PWR_CLK_STATE] = GEN8_R_PWR_CLK_STATE;
- reg_state[CTX_R_PWR_CLK_STATE+1] = make_rpcs(dev);
+ ASSIGN_CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE,
+ make_rpcs(dev));
}
kunmap_atomic(reg_state);
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 4e60d54ba66d..0b821b91723a 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -29,16 +29,16 @@
#define GEN8_CSB_PTR_MASK 0x07
/* Execlists regs */
-#define RING_ELSP(ring) ((ring)->mmio_base+0x230)
-#define RING_EXECLIST_STATUS_LO(ring) ((ring)->mmio_base+0x234)
-#define RING_EXECLIST_STATUS_HI(ring) ((ring)->mmio_base+0x234 + 4)
-#define RING_CONTEXT_CONTROL(ring) ((ring)->mmio_base+0x244)
+#define RING_ELSP(ring) _MMIO((ring)->mmio_base + 0x230)
+#define RING_EXECLIST_STATUS_LO(ring) _MMIO((ring)->mmio_base + 0x234)
+#define RING_EXECLIST_STATUS_HI(ring) _MMIO((ring)->mmio_base + 0x234 + 4)
+#define RING_CONTEXT_CONTROL(ring) _MMIO((ring)->mmio_base + 0x244)
#define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH (1 << 3)
#define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT (1 << 0)
#define CTX_CTRL_RS_CTX_ENABLE (1 << 1)
-#define RING_CONTEXT_STATUS_BUF_LO(ring, i) ((ring)->mmio_base+0x370 + (i) * 8)
-#define RING_CONTEXT_STATUS_BUF_HI(ring, i) ((ring)->mmio_base+0x370 + (i) * 8 + 4)
-#define RING_CONTEXT_STATUS_PTR(ring) ((ring)->mmio_base+0x3a0)
+#define RING_CONTEXT_STATUS_BUF_LO(ring, i) _MMIO((ring)->mmio_base + 0x370 + (i) * 8)
+#define RING_CONTEXT_STATUS_BUF_HI(ring, i) _MMIO((ring)->mmio_base + 0x370 + (i) * 8 + 4)
+#define RING_CONTEXT_STATUS_PTR(ring) _MMIO((ring)->mmio_base + 0x3a0)
/* Logical Rings */
int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request);
@@ -70,6 +70,11 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf,
iowrite32(data, ringbuf->virtual_start + ringbuf->tail);
ringbuf->tail += 4;
}
+static inline void intel_logical_ring_emit_reg(struct intel_ringbuffer *ringbuf,
+ i915_reg_t reg)
+{
+ intel_logical_ring_emit(ringbuf, i915_mmio_reg_offset(reg));
+}
/* Logical Ring Contexts */
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 7f39b8ad88ae..61f1145f6579 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -51,7 +51,7 @@ struct intel_lvds_encoder {
struct intel_encoder base;
bool is_dual_link;
- u32 reg;
+ i915_reg_t reg;
u32 a3_power;
struct intel_lvds_connector *attached_connector;
@@ -210,7 +210,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
struct intel_connector *intel_connector =
&lvds_encoder->attached_connector->base;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 ctl_reg, stat_reg;
+ i915_reg_t ctl_reg, stat_reg;
if (HAS_PCH_SPLIT(dev)) {
ctl_reg = PCH_PP_CONTROL;
@@ -235,7 +235,7 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
struct drm_device *dev = encoder->base.dev;
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 ctl_reg, stat_reg;
+ i915_reg_t ctl_reg, stat_reg;
if (HAS_PCH_SPLIT(dev)) {
ctl_reg = PCH_PP_CONTROL;
@@ -939,7 +939,7 @@ void intel_lvds_init(struct drm_device *dev)
struct drm_display_mode *downclock_mode = NULL;
struct edid *edid;
struct drm_crtc *crtc;
- u32 lvds_reg;
+ i915_reg_t lvds_reg;
u32 lvds;
int pipe;
u8 pin;
@@ -1164,8 +1164,7 @@ out:
DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
lvds_encoder->is_dual_link ? "dual" : "single");
- lvds_encoder->a3_power = I915_READ(lvds_encoder->reg) &
- LVDS_A3_POWER_MASK;
+ lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;
lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c
index 6d3c6c0a5c62..fed7bea19cc9 100644
--- a/drivers/gpu/drm/i915/intel_mocs.c
+++ b/drivers/gpu/drm/i915/intel_mocs.c
@@ -143,7 +143,7 @@ static bool get_mocs_settings(struct drm_device *dev,
{
bool result = false;
- if (IS_SKYLAKE(dev)) {
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
table->size = ARRAY_SIZE(skylake_mocs_table);
table->table = skylake_mocs_table;
result = true;
@@ -159,11 +159,30 @@ static bool get_mocs_settings(struct drm_device *dev,
return result;
}
+static i915_reg_t mocs_register(enum intel_ring_id ring, int index)
+{
+ switch (ring) {
+ case RCS:
+ return GEN9_GFX_MOCS(index);
+ case VCS:
+ return GEN9_MFX0_MOCS(index);
+ case BCS:
+ return GEN9_BLT_MOCS(index);
+ case VECS:
+ return GEN9_VEBOX_MOCS(index);
+ case VCS2:
+ return GEN9_MFX1_MOCS(index);
+ default:
+ MISSING_CASE(ring);
+ return INVALID_MMIO_REG;
+ }
+}
+
/**
* emit_mocs_control_table() - emit the mocs control table
* @req: Request to set up the MOCS table for.
* @table: The values to program into the control regs.
- * @reg_base: The base for the engine that needs to be programmed.
+ * @ring: The engine for whom to emit the registers.
*
* This function simply emits a MI_LOAD_REGISTER_IMM command for the
* given table starting at the given address.
@@ -172,7 +191,7 @@ static bool get_mocs_settings(struct drm_device *dev,
*/
static int emit_mocs_control_table(struct drm_i915_gem_request *req,
const struct drm_i915_mocs_table *table,
- u32 reg_base)
+ enum intel_ring_id ring)
{
struct intel_ringbuffer *ringbuf = req->ringbuf;
unsigned int index;
@@ -191,7 +210,7 @@ static int emit_mocs_control_table(struct drm_i915_gem_request *req,
MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES));
for (index = 0; index < table->size; index++) {
- intel_logical_ring_emit(ringbuf, reg_base + index * 4);
+ intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index));
intel_logical_ring_emit(ringbuf,
table->table[index].control_value);
}
@@ -205,7 +224,7 @@ static int emit_mocs_control_table(struct drm_i915_gem_request *req,
* that value to all the used entries.
*/
for (; index < GEN9_NUM_MOCS_ENTRIES; index++) {
- intel_logical_ring_emit(ringbuf, reg_base + index * 4);
+ intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index));
intel_logical_ring_emit(ringbuf, table->table[0].control_value);
}
@@ -253,7 +272,7 @@ static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req,
value = (table->table[count].l3cc_value & 0xffff) |
((table->table[count + 1].l3cc_value & 0xffff) << 16);
- intel_logical_ring_emit(ringbuf, GEN9_LNCFCMOCS0 + i * 4);
+ intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
intel_logical_ring_emit(ringbuf, value);
}
@@ -270,7 +289,7 @@ static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req,
* they are reserved by the hardware.
*/
for (; i < GEN9_NUM_MOCS_ENTRIES / 2; i++) {
- intel_logical_ring_emit(ringbuf, GEN9_LNCFCMOCS0 + i * 4);
+ intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
intel_logical_ring_emit(ringbuf, value);
value = filler;
@@ -304,26 +323,16 @@ int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req)
int ret;
if (get_mocs_settings(req->ring->dev, &t)) {
- /* Program the control registers */
- ret = emit_mocs_control_table(req, &t, GEN9_GFX_MOCS_0);
- if (ret)
- return ret;
-
- ret = emit_mocs_control_table(req, &t, GEN9_MFX0_MOCS_0);
- if (ret)
- return ret;
+ struct drm_i915_private *dev_priv = req->i915;
+ struct intel_engine_cs *ring;
+ enum intel_ring_id ring_id;
- ret = emit_mocs_control_table(req, &t, GEN9_MFX1_MOCS_0);
- if (ret)
- return ret;
-
- ret = emit_mocs_control_table(req, &t, GEN9_VEBOX_MOCS_0);
- if (ret)
- return ret;
-
- ret = emit_mocs_control_table(req, &t, GEN9_BLT_MOCS_0);
- if (ret)
- return ret;
+ /* Program the control registers */
+ for_each_ring(ring, dev_priv, ring_id) {
+ ret = emit_mocs_control_table(req, &t, ring_id);
+ if (ret)
+ return ret;
+ }
/* Now program the l3cc registers */
ret = emit_mocs_l3cc_table(req, &t);
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 6dc13c02c28e..e362a30776fa 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -682,7 +682,7 @@ static void intel_didl_outputs(struct drm_device *dev)
}
if (!acpi_video_bus) {
- DRM_ERROR("No ACPI video bus found\n");
+ DRM_DEBUG_KMS("No ACPI video bus found\n");
return;
}
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 444542696a2c..76f1980a7541 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -749,7 +749,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
if (ret != 0)
return ret;
- ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL, NULL,
+ ret = i915_gem_object_pin_to_display_plane(new_bo, 0,
&i915_ggtt_view_normal);
if (ret != 0)
return ret;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f091ad12d694..038a81d03b17 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1708,13 +1708,6 @@ static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
}
-struct skl_pipe_wm_parameters {
- bool active;
- uint32_t pipe_htotal;
- uint32_t pixel_rate; /* in KHz */
- struct intel_plane_wm_parameters plane[I915_MAX_PLANES];
-};
-
struct ilk_wm_maximums {
uint16_t pri;
uint16_t spr;
@@ -1722,13 +1715,6 @@ struct ilk_wm_maximums {
uint16_t fbc;
};
-/* used in computing the new watermarks state */
-struct intel_wm_config {
- unsigned int num_pipes_active;
- bool sprites_enabled;
- bool sprites_scaled;
-};
-
/*
* For both WM_PIPE and WM_LP.
* mem_value must be in 0.1us units.
@@ -1979,9 +1965,11 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
const struct intel_crtc *intel_crtc,
int level,
struct intel_crtc_state *cstate,
+ struct intel_plane_state *pristate,
+ struct intel_plane_state *sprstate,
+ struct intel_plane_state *curstate,
struct intel_wm_level *result)
{
- struct intel_plane *intel_plane;
uint16_t pri_latency = dev_priv->wm.pri_latency[level];
uint16_t spr_latency = dev_priv->wm.spr_latency[level];
uint16_t cur_latency = dev_priv->wm.cur_latency[level];
@@ -1993,29 +1981,11 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
cur_latency *= 5;
}
- for_each_intel_plane_on_crtc(dev_priv->dev, intel_crtc, intel_plane) {
- struct intel_plane_state *pstate =
- to_intel_plane_state(intel_plane->base.state);
-
- switch (intel_plane->base.type) {
- case DRM_PLANE_TYPE_PRIMARY:
- result->pri_val = ilk_compute_pri_wm(cstate, pstate,
- pri_latency,
- level);
- result->fbc_val = ilk_compute_fbc_wm(cstate, pstate,
- result->pri_val);
- break;
- case DRM_PLANE_TYPE_OVERLAY:
- result->spr_val = ilk_compute_spr_wm(cstate, pstate,
- spr_latency);
- break;
- case DRM_PLANE_TYPE_CURSOR:
- result->cur_val = ilk_compute_cur_wm(cstate, pstate,
- cur_latency);
- break;
- }
- }
-
+ result->pri_val = ilk_compute_pri_wm(cstate, pristate,
+ pri_latency, level);
+ result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
+ result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
+ result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
result->enable = true;
}
@@ -2274,34 +2244,19 @@ static void skl_setup_wm_latency(struct drm_device *dev)
intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
}
-static void ilk_compute_wm_config(struct drm_device *dev,
- struct intel_wm_config *config)
-{
- struct intel_crtc *intel_crtc;
-
- /* Compute the currently _active_ config */
- for_each_intel_crtc(dev, intel_crtc) {
- const struct intel_pipe_wm *wm = &intel_crtc->wm.active;
-
- if (!wm->pipe_enabled)
- continue;
-
- config->sprites_enabled |= wm->sprites_enabled;
- config->sprites_scaled |= wm->sprites_scaled;
- config->num_pipes_active++;
- }
-}
-
/* Compute new watermarks for the pipe */
-static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
- struct intel_pipe_wm *pipe_wm)
+static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc,
+ struct drm_atomic_state *state)
{
- struct drm_crtc *crtc = cstate->base.crtc;
- struct drm_device *dev = crtc->dev;
+ struct intel_pipe_wm *pipe_wm;
+ struct drm_device *dev = intel_crtc->base.dev;
const struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc_state *cstate = NULL;
struct intel_plane *intel_plane;
+ struct drm_plane_state *ps;
+ struct intel_plane_state *pristate = NULL;
struct intel_plane_state *sprstate = NULL;
+ struct intel_plane_state *curstate = NULL;
int level, max_level = ilk_wm_max_level(dev);
/* LP0 watermark maximums depend on this pipe alone */
struct intel_wm_config config = {
@@ -2309,11 +2264,24 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
};
struct ilk_wm_maximums max;
+ cstate = intel_atomic_get_crtc_state(state, intel_crtc);
+ if (IS_ERR(cstate))
+ return PTR_ERR(cstate);
+
+ pipe_wm = &cstate->wm.optimal.ilk;
+
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY) {
- sprstate = to_intel_plane_state(intel_plane->base.state);
- break;
- }
+ ps = drm_atomic_get_plane_state(state,
+ &intel_plane->base);
+ if (IS_ERR(ps))
+ return PTR_ERR(ps);
+
+ if (intel_plane->base.type == DRM_PLANE_TYPE_PRIMARY)
+ pristate = to_intel_plane_state(ps);
+ else if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY)
+ sprstate = to_intel_plane_state(ps);
+ else if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
+ curstate = to_intel_plane_state(ps);
}
config.sprites_enabled = sprstate->visible;
@@ -2322,7 +2290,7 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16);
pipe_wm->pipe_enabled = cstate->base.active;
- pipe_wm->sprites_enabled = sprstate->visible;
+ pipe_wm->sprites_enabled = config.sprites_enabled;
pipe_wm->sprites_scaled = config.sprites_scaled;
/* ILK/SNB: LP2+ watermarks only w/o sprites */
@@ -2333,24 +2301,27 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
if (config.sprites_scaled)
max_level = 0;
- ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, &pipe_wm->wm[0]);
+ ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate,
+ pristate, sprstate, curstate, &pipe_wm->wm[0]);
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
- pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
+ pipe_wm->linetime = hsw_compute_linetime_wm(dev,
+ &intel_crtc->base);
/* LP0 watermarks always use 1/2 DDB partitioning */
ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
/* At least LP0 must be valid */
if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
- return false;
+ return -EINVAL;
ilk_compute_wm_reg_maximums(dev, 1, &max);
for (level = 1; level <= max_level; level++) {
struct intel_wm_level wm = {};
- ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate, &wm);
+ ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate,
+ pristate, sprstate, curstate, &wm);
/*
* Disable any watermark level that exceeds the
@@ -2363,7 +2334,7 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate,
pipe_wm->wm[level] = wm;
}
- return true;
+ return 0;
}
/*
@@ -2378,7 +2349,9 @@ static void ilk_merge_wm_level(struct drm_device *dev,
ret_wm->enable = true;
for_each_intel_crtc(dev, intel_crtc) {
- const struct intel_pipe_wm *active = &intel_crtc->wm.active;
+ const struct intel_crtc_state *cstate =
+ to_intel_crtc_state(intel_crtc->base.state);
+ const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
const struct intel_wm_level *wm = &active->wm[level];
if (!active->pipe_enabled)
@@ -2526,14 +2499,15 @@ static void ilk_compute_wm_results(struct drm_device *dev,
/* LP0 register values */
for_each_intel_crtc(dev, intel_crtc) {
+ const struct intel_crtc_state *cstate =
+ to_intel_crtc_state(intel_crtc->base.state);
enum pipe pipe = intel_crtc->pipe;
- const struct intel_wm_level *r =
- &intel_crtc->wm.active.wm[0];
+ const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0];
if (WARN_ON(!r->enable))
continue;
- results->wm_linetime[pipe] = intel_crtc->wm.active.linetime;
+ results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime;
results->wm_pipe[pipe] =
(r->pri_val << WM0_PIPE_PLANE_SHIFT) |
@@ -2755,18 +2729,40 @@ static bool ilk_disable_lp_wm(struct drm_device *dev)
#define SKL_DDB_SIZE 896 /* in blocks */
#define BXT_DDB_SIZE 512
+/*
+ * Return the index of a plane in the SKL DDB and wm result arrays. Primary
+ * plane is always in slot 0, cursor is always in slot I915_MAX_PLANES-1, and
+ * other universal planes are in indices 1..n. Note that this may leave unused
+ * indices between the top "sprite" plane and the cursor.
+ */
+static int
+skl_wm_plane_id(const struct intel_plane *plane)
+{
+ switch (plane->base.type) {
+ case DRM_PLANE_TYPE_PRIMARY:
+ return 0;
+ case DRM_PLANE_TYPE_CURSOR:
+ return PLANE_CURSOR;
+ case DRM_PLANE_TYPE_OVERLAY:
+ return plane->plane + 1;
+ default:
+ MISSING_CASE(plane->base.type);
+ return plane->plane;
+ }
+}
+
static void
skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
- struct drm_crtc *for_crtc,
+ const struct intel_crtc_state *cstate,
const struct intel_wm_config *config,
- const struct skl_pipe_wm_parameters *params,
struct skl_ddb_entry *alloc /* out */)
{
+ struct drm_crtc *for_crtc = cstate->base.crtc;
struct drm_crtc *crtc;
unsigned int pipe_size, ddb_size;
int nth_active_pipe;
- if (!params->active) {
+ if (!cstate->base.active) {
alloc->start = 0;
alloc->end = 0;
return;
@@ -2837,19 +2833,29 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
}
static unsigned int
-skl_plane_relative_data_rate(const struct intel_plane_wm_parameters *p, int y)
+skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
+ const struct drm_plane_state *pstate,
+ int y)
{
+ struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
+ struct drm_framebuffer *fb = pstate->fb;
/* for planar format */
- if (p->y_bytes_per_pixel) {
+ if (fb->pixel_format == DRM_FORMAT_NV12) {
if (y) /* y-plane data rate */
- return p->horiz_pixels * p->vert_pixels * p->y_bytes_per_pixel;
+ return intel_crtc->config->pipe_src_w *
+ intel_crtc->config->pipe_src_h *
+ drm_format_plane_cpp(fb->pixel_format, 0);
else /* uv-plane data rate */
- return (p->horiz_pixels/2) * (p->vert_pixels/2) * p->bytes_per_pixel;
+ return (intel_crtc->config->pipe_src_w/2) *
+ (intel_crtc->config->pipe_src_h/2) *
+ drm_format_plane_cpp(fb->pixel_format, 1);
}
/* for packed formats */
- return p->horiz_pixels * p->vert_pixels * p->bytes_per_pixel;
+ return intel_crtc->config->pipe_src_w *
+ intel_crtc->config->pipe_src_h *
+ drm_format_plane_cpp(fb->pixel_format, 0);
}
/*
@@ -2858,46 +2864,55 @@ skl_plane_relative_data_rate(const struct intel_plane_wm_parameters *p, int y)
* 3 * 4096 * 8192 * 4 < 2^32
*/
static unsigned int
-skl_get_total_relative_data_rate(struct intel_crtc *intel_crtc,
- const struct skl_pipe_wm_parameters *params)
+skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate)
{
+ struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
+ struct drm_device *dev = intel_crtc->base.dev;
+ const struct intel_plane *intel_plane;
unsigned int total_data_rate = 0;
- int plane;
- for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
- const struct intel_plane_wm_parameters *p;
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ const struct drm_plane_state *pstate = intel_plane->base.state;
- p = &params->plane[plane];
- if (!p->enabled)
+ if (pstate->fb == NULL)
continue;
- total_data_rate += skl_plane_relative_data_rate(p, 0); /* packed/uv */
- if (p->y_bytes_per_pixel) {
- total_data_rate += skl_plane_relative_data_rate(p, 1); /* y-plane */
- }
+ if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
+ continue;
+
+ /* packed/uv */
+ total_data_rate += skl_plane_relative_data_rate(cstate,
+ pstate,
+ 0);
+
+ if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
+ /* y-plane */
+ total_data_rate += skl_plane_relative_data_rate(cstate,
+ pstate,
+ 1);
}
return total_data_rate;
}
static void
-skl_allocate_pipe_ddb(struct drm_crtc *crtc,
- const struct intel_wm_config *config,
- const struct skl_pipe_wm_parameters *params,
+skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
struct skl_ddb_allocation *ddb /* out */)
{
+ struct drm_crtc *crtc = cstate->base.crtc;
struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_wm_config *config = &dev_priv->wm.config;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_plane *intel_plane;
enum pipe pipe = intel_crtc->pipe;
struct skl_ddb_entry *alloc = &ddb->pipe[pipe];
uint16_t alloc_size, start, cursor_blocks;
uint16_t minimum[I915_MAX_PLANES];
uint16_t y_minimum[I915_MAX_PLANES];
unsigned int total_data_rate;
- int plane;
- skl_ddb_get_pipe_allocation_limits(dev, crtc, config, params, alloc);
+ skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc);
alloc_size = skl_ddb_entry_size(alloc);
if (alloc_size == 0) {
memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
@@ -2914,17 +2929,20 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc,
alloc->end -= cursor_blocks;
/* 1. Allocate the mininum required blocks for each active plane */
- for_each_plane(dev_priv, pipe, plane) {
- const struct intel_plane_wm_parameters *p;
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ struct drm_plane *plane = &intel_plane->base;
+ struct drm_framebuffer *fb = plane->state->fb;
+ int id = skl_wm_plane_id(intel_plane);
- p = &params->plane[plane];
- if (!p->enabled)
+ if (fb == NULL)
+ continue;
+ if (plane->type == DRM_PLANE_TYPE_CURSOR)
continue;
- minimum[plane] = 8;
- alloc_size -= minimum[plane];
- y_minimum[plane] = p->y_bytes_per_pixel ? 8 : 0;
- alloc_size -= y_minimum[plane];
+ minimum[id] = 8;
+ alloc_size -= minimum[id];
+ y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0;
+ alloc_size -= y_minimum[id];
}
/*
@@ -2933,45 +2951,50 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc,
*
* FIXME: we may not allocate every single block here.
*/
- total_data_rate = skl_get_total_relative_data_rate(intel_crtc, params);
+ total_data_rate = skl_get_total_relative_data_rate(cstate);
start = alloc->start;
- for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
- const struct intel_plane_wm_parameters *p;
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ struct drm_plane *plane = &intel_plane->base;
+ struct drm_plane_state *pstate = intel_plane->base.state;
unsigned int data_rate, y_data_rate;
uint16_t plane_blocks, y_plane_blocks = 0;
+ int id = skl_wm_plane_id(intel_plane);
- p = &params->plane[plane];
- if (!p->enabled)
+ if (pstate->fb == NULL)
+ continue;
+ if (plane->type == DRM_PLANE_TYPE_CURSOR)
continue;
- data_rate = skl_plane_relative_data_rate(p, 0);
+ data_rate = skl_plane_relative_data_rate(cstate, pstate, 0);
/*
* allocation for (packed formats) or (uv-plane part of planar format):
* promote the expression to 64 bits to avoid overflowing, the
* result is < available as data_rate / total_data_rate < 1
*/
- plane_blocks = minimum[plane];
+ plane_blocks = minimum[id];
plane_blocks += div_u64((uint64_t)alloc_size * data_rate,
total_data_rate);
- ddb->plane[pipe][plane].start = start;
- ddb->plane[pipe][plane].end = start + plane_blocks;
+ ddb->plane[pipe][id].start = start;
+ ddb->plane[pipe][id].end = start + plane_blocks;
start += plane_blocks;
/*
* allocation for y_plane part of planar format:
*/
- if (p->y_bytes_per_pixel) {
- y_data_rate = skl_plane_relative_data_rate(p, 1);
- y_plane_blocks = y_minimum[plane];
+ if (pstate->fb->pixel_format == DRM_FORMAT_NV12) {
+ y_data_rate = skl_plane_relative_data_rate(cstate,
+ pstate,
+ 1);
+ y_plane_blocks = y_minimum[id];
y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
total_data_rate);
- ddb->y_plane[pipe][plane].start = start;
- ddb->y_plane[pipe][plane].end = start + y_plane_blocks;
+ ddb->y_plane[pipe][id].start = start;
+ ddb->y_plane[pipe][id].end = start + y_plane_blocks;
start += y_plane_blocks;
}
@@ -3041,104 +3064,27 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
const struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb;
- enum pipe pipe = intel_crtc->pipe;
-
- if (memcmp(new_ddb->plane[pipe], cur_ddb->plane[pipe],
- sizeof(new_ddb->plane[pipe])))
- return true;
- if (memcmp(&new_ddb->plane[pipe][PLANE_CURSOR], &cur_ddb->plane[pipe][PLANE_CURSOR],
- sizeof(new_ddb->plane[pipe][PLANE_CURSOR])))
+ /*
+ * If ddb allocation of pipes changed, it may require recalculation of
+ * watermarks
+ */
+ if (memcmp(new_ddb->pipe, cur_ddb->pipe, sizeof(new_ddb->pipe)))
return true;
return false;
}
-static void skl_compute_wm_global_parameters(struct drm_device *dev,
- struct intel_wm_config *config)
-{
- struct drm_crtc *crtc;
- struct drm_plane *plane;
-
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
- config->num_pipes_active += to_intel_crtc(crtc)->active;
-
- /* FIXME: I don't think we need those two global parameters on SKL */
- list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
- struct intel_plane *intel_plane = to_intel_plane(plane);
-
- config->sprites_enabled |= intel_plane->wm.enabled;
- config->sprites_scaled |= intel_plane->wm.scaled;
- }
-}
-
-static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc,
- struct skl_pipe_wm_parameters *p)
-{
- struct drm_device *dev = crtc->dev;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum pipe pipe = intel_crtc->pipe;
- struct drm_plane *plane;
- struct drm_framebuffer *fb;
- int i = 1; /* Index for sprite planes start */
-
- p->active = intel_crtc->active;
- if (p->active) {
- p->pipe_htotal = intel_crtc->config->base.adjusted_mode.crtc_htotal;
- p->pixel_rate = skl_pipe_pixel_rate(intel_crtc->config);
-
- fb = crtc->primary->state->fb;
- /* For planar: Bpp is for uv plane, y_Bpp is for y plane */
- if (fb) {
- p->plane[0].enabled = true;
- p->plane[0].bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ?
- drm_format_plane_cpp(fb->pixel_format, 1) :
- drm_format_plane_cpp(fb->pixel_format, 0);
- p->plane[0].y_bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ?
- drm_format_plane_cpp(fb->pixel_format, 0) : 0;
- p->plane[0].tiling = fb->modifier[0];
- } else {
- p->plane[0].enabled = false;
- p->plane[0].bytes_per_pixel = 0;
- p->plane[0].y_bytes_per_pixel = 0;
- p->plane[0].tiling = DRM_FORMAT_MOD_NONE;
- }
- p->plane[0].horiz_pixels = intel_crtc->config->pipe_src_w;
- p->plane[0].vert_pixels = intel_crtc->config->pipe_src_h;
- p->plane[0].rotation = crtc->primary->state->rotation;
-
- fb = crtc->cursor->state->fb;
- p->plane[PLANE_CURSOR].y_bytes_per_pixel = 0;
- if (fb) {
- p->plane[PLANE_CURSOR].enabled = true;
- p->plane[PLANE_CURSOR].bytes_per_pixel = fb->bits_per_pixel / 8;
- p->plane[PLANE_CURSOR].horiz_pixels = crtc->cursor->state->crtc_w;
- p->plane[PLANE_CURSOR].vert_pixels = crtc->cursor->state->crtc_h;
- } else {
- p->plane[PLANE_CURSOR].enabled = false;
- p->plane[PLANE_CURSOR].bytes_per_pixel = 0;
- p->plane[PLANE_CURSOR].horiz_pixels = 64;
- p->plane[PLANE_CURSOR].vert_pixels = 64;
- }
- }
-
- list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
- struct intel_plane *intel_plane = to_intel_plane(plane);
-
- if (intel_plane->pipe == pipe &&
- plane->type == DRM_PLANE_TYPE_OVERLAY)
- p->plane[i++] = intel_plane->wm;
- }
-}
-
static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
- struct skl_pipe_wm_parameters *p,
- struct intel_plane_wm_parameters *p_params,
+ struct intel_crtc_state *cstate,
+ struct intel_plane *intel_plane,
uint16_t ddb_allocation,
int level,
uint16_t *out_blocks, /* out */
uint8_t *out_lines /* out */)
{
+ struct drm_plane *plane = &intel_plane->base;
+ struct drm_framebuffer *fb = plane->state->fb;
uint32_t latency = dev_priv->wm.skl_latency[level];
uint32_t method1, method2;
uint32_t plane_bytes_per_line, plane_blocks_per_line;
@@ -3146,31 +3092,33 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
uint32_t selected_result;
uint8_t bytes_per_pixel;
- if (latency == 0 || !p->active || !p_params->enabled)
+ if (latency == 0 || !cstate->base.active || !fb)
return false;
- bytes_per_pixel = p_params->y_bytes_per_pixel ?
- p_params->y_bytes_per_pixel :
- p_params->bytes_per_pixel;
- method1 = skl_wm_method1(p->pixel_rate,
+ bytes_per_pixel = drm_format_plane_cpp(fb->pixel_format, 0);
+ method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
bytes_per_pixel,
latency);
- method2 = skl_wm_method2(p->pixel_rate,
- p->pipe_htotal,
- p_params->horiz_pixels,
+ method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate),
+ cstate->base.adjusted_mode.crtc_htotal,
+ cstate->pipe_src_w,
bytes_per_pixel,
- p_params->tiling,
+ fb->modifier[0],
latency);
- plane_bytes_per_line = p_params->horiz_pixels * bytes_per_pixel;
+ plane_bytes_per_line = cstate->pipe_src_w * bytes_per_pixel;
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512);
- if (p_params->tiling == I915_FORMAT_MOD_Y_TILED ||
- p_params->tiling == I915_FORMAT_MOD_Yf_TILED) {
+ if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
+ fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
uint32_t min_scanlines = 4;
uint32_t y_tile_minimum;
- if (intel_rotation_90_or_270(p_params->rotation)) {
- switch (p_params->bytes_per_pixel) {
+ if (intel_rotation_90_or_270(plane->state->rotation)) {
+ int bpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
+ drm_format_plane_cpp(fb->pixel_format, 1) :
+ drm_format_plane_cpp(fb->pixel_format, 0);
+
+ switch (bpp) {
case 1:
min_scanlines = 16;
break;
@@ -3194,8 +3142,8 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line);
if (level >= 1 && level <= 7) {
- if (p_params->tiling == I915_FORMAT_MOD_Y_TILED ||
- p_params->tiling == I915_FORMAT_MOD_Yf_TILED)
+ if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
+ fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)
res_lines += 4;
else
res_blocks++;
@@ -3212,84 +3160,80 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
static void skl_compute_wm_level(const struct drm_i915_private *dev_priv,
struct skl_ddb_allocation *ddb,
- struct skl_pipe_wm_parameters *p,
- enum pipe pipe,
+ struct intel_crtc_state *cstate,
int level,
- int num_planes,
struct skl_wm_level *result)
{
+ struct drm_device *dev = dev_priv->dev;
+ struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
+ struct intel_plane *intel_plane;
uint16_t ddb_blocks;
- int i;
+ enum pipe pipe = intel_crtc->pipe;
+
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ int i = skl_wm_plane_id(intel_plane);
- for (i = 0; i < num_planes; i++) {
ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
result->plane_en[i] = skl_compute_plane_wm(dev_priv,
- p, &p->plane[i],
+ cstate,
+ intel_plane,
ddb_blocks,
level,
&result->plane_res_b[i],
&result->plane_res_l[i]);
}
-
- ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][PLANE_CURSOR]);
- result->plane_en[PLANE_CURSOR] = skl_compute_plane_wm(dev_priv, p,
- &p->plane[PLANE_CURSOR],
- ddb_blocks, level,
- &result->plane_res_b[PLANE_CURSOR],
- &result->plane_res_l[PLANE_CURSOR]);
}
static uint32_t
-skl_compute_linetime_wm(struct drm_crtc *crtc, struct skl_pipe_wm_parameters *p)
+skl_compute_linetime_wm(struct intel_crtc_state *cstate)
{
- if (!to_intel_crtc(crtc)->active)
+ if (!cstate->base.active)
return 0;
- if (WARN_ON(p->pixel_rate == 0))
+ if (WARN_ON(skl_pipe_pixel_rate(cstate) == 0))
return 0;
- return DIV_ROUND_UP(8 * p->pipe_htotal * 1000, p->pixel_rate);
+ return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000,
+ skl_pipe_pixel_rate(cstate));
}
-static void skl_compute_transition_wm(struct drm_crtc *crtc,
- struct skl_pipe_wm_parameters *params,
+static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
struct skl_wm_level *trans_wm /* out */)
{
+ struct drm_crtc *crtc = cstate->base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int i;
+ struct intel_plane *intel_plane;
- if (!params->active)
+ if (!cstate->base.active)
return;
/* Until we know more, just disable transition WMs */
- for (i = 0; i < intel_num_planes(intel_crtc); i++)
+ for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) {
+ int i = skl_wm_plane_id(intel_plane);
+
trans_wm->plane_en[i] = false;
- trans_wm->plane_en[PLANE_CURSOR] = false;
+ }
}
-static void skl_compute_pipe_wm(struct drm_crtc *crtc,
+static void skl_compute_pipe_wm(struct intel_crtc_state *cstate,
struct skl_ddb_allocation *ddb,
- struct skl_pipe_wm_parameters *params,
struct skl_pipe_wm *pipe_wm)
{
- struct drm_device *dev = crtc->dev;
+ struct drm_device *dev = cstate->base.crtc->dev;
const struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int level, max_level = ilk_wm_max_level(dev);
for (level = 0; level <= max_level; level++) {
- skl_compute_wm_level(dev_priv, ddb, params, intel_crtc->pipe,
- level, intel_num_planes(intel_crtc),
- &pipe_wm->wm[level]);
+ skl_compute_wm_level(dev_priv, ddb, cstate,
+ level, &pipe_wm->wm[level]);
}
- pipe_wm->linetime = skl_compute_linetime_wm(crtc, params);
+ pipe_wm->linetime = skl_compute_linetime_wm(cstate);
- skl_compute_transition_wm(crtc, params, &pipe_wm->trans_wm);
+ skl_compute_transition_wm(cstate, &pipe_wm->trans_wm);
}
static void skl_compute_wm_results(struct drm_device *dev,
- struct skl_pipe_wm_parameters *p,
struct skl_pipe_wm *p_wm,
struct skl_wm_values *r,
struct intel_crtc *intel_crtc)
@@ -3346,7 +3290,8 @@ static void skl_compute_wm_results(struct drm_device *dev,
r->wm_linetime[pipe] = p_wm->linetime;
}
-static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, uint32_t reg,
+static void skl_ddb_entry_write(struct drm_i915_private *dev_priv,
+ i915_reg_t reg,
const struct skl_ddb_entry *entry)
{
if (entry->end)
@@ -3533,28 +3478,25 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
}
static bool skl_update_pipe_wm(struct drm_crtc *crtc,
- struct skl_pipe_wm_parameters *params,
- struct intel_wm_config *config,
struct skl_ddb_allocation *ddb, /* out */
struct skl_pipe_wm *pipe_wm /* out */)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
- skl_compute_wm_pipe_parameters(crtc, params);
- skl_allocate_pipe_ddb(crtc, config, params, ddb);
- skl_compute_pipe_wm(crtc, ddb, params, pipe_wm);
+ skl_allocate_pipe_ddb(cstate, ddb);
+ skl_compute_pipe_wm(cstate, ddb, pipe_wm);
- if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm)))
+ if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
return false;
- intel_crtc->wm.skl_active = *pipe_wm;
+ intel_crtc->wm.active.skl = *pipe_wm;
return true;
}
static void skl_update_other_pipe_wm(struct drm_device *dev,
struct drm_crtc *crtc,
- struct intel_wm_config *config,
struct skl_wm_values *r)
{
struct intel_crtc *intel_crtc;
@@ -3575,7 +3517,6 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
*/
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
base.head) {
- struct skl_pipe_wm_parameters params = {};
struct skl_pipe_wm pipe_wm = {};
bool wm_changed;
@@ -3586,7 +3527,6 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
continue;
wm_changed = skl_update_pipe_wm(&intel_crtc->base,
- &params, config,
&r->ddb, &pipe_wm);
/*
@@ -3596,7 +3536,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
*/
WARN_ON(!wm_changed);
- skl_compute_wm_results(dev, &params, &pipe_wm, r, intel_crtc);
+ skl_compute_wm_results(dev, &pipe_wm, r, intel_crtc);
r->dirty[intel_crtc->pipe] = true;
}
}
@@ -3626,10 +3566,9 @@ static void skl_update_wm(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct skl_pipe_wm_parameters params = {};
struct skl_wm_values *results = &dev_priv->wm.skl_results;
- struct skl_pipe_wm pipe_wm = {};
- struct intel_wm_config config = {};
+ struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+ struct skl_pipe_wm *pipe_wm = &cstate->wm.optimal.skl;
/* Clear all dirty flags */
@@ -3637,16 +3576,13 @@ static void skl_update_wm(struct drm_crtc *crtc)
skl_clear_wm(results, intel_crtc->pipe);
- skl_compute_wm_global_parameters(dev, &config);
-
- if (!skl_update_pipe_wm(crtc, &params, &config,
- &results->ddb, &pipe_wm))
+ if (!skl_update_pipe_wm(crtc, &results->ddb, pipe_wm))
return;
- skl_compute_wm_results(dev, &params, &pipe_wm, results, intel_crtc);
+ skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
results->dirty[intel_crtc->pipe] = true;
- skl_update_other_pipe_wm(dev, crtc, &config, results);
+ skl_update_other_pipe_wm(dev, crtc, results);
skl_write_wm_values(dev_priv, results);
skl_flush_wm_values(dev_priv, results);
@@ -3654,71 +3590,23 @@ static void skl_update_wm(struct drm_crtc *crtc)
dev_priv->wm.skl_hw = *results;
}
-static void
-skl_update_sprite_wm(struct drm_plane *plane, struct drm_crtc *crtc,
- uint32_t sprite_width, uint32_t sprite_height,
- int pixel_size, bool enabled, bool scaled)
-{
- struct intel_plane *intel_plane = to_intel_plane(plane);
- struct drm_framebuffer *fb = plane->state->fb;
-
- intel_plane->wm.enabled = enabled;
- intel_plane->wm.scaled = scaled;
- intel_plane->wm.horiz_pixels = sprite_width;
- intel_plane->wm.vert_pixels = sprite_height;
- intel_plane->wm.tiling = DRM_FORMAT_MOD_NONE;
-
- /* For planar: Bpp is for UV plane, y_Bpp is for Y plane */
- intel_plane->wm.bytes_per_pixel =
- (fb && fb->pixel_format == DRM_FORMAT_NV12) ?
- drm_format_plane_cpp(plane->state->fb->pixel_format, 1) : pixel_size;
- intel_plane->wm.y_bytes_per_pixel =
- (fb && fb->pixel_format == DRM_FORMAT_NV12) ?
- drm_format_plane_cpp(plane->state->fb->pixel_format, 0) : 0;
-
- /*
- * Framebuffer can be NULL on plane disable, but it does not
- * matter for watermarks if we assume no tiling in that case.
- */
- if (fb)
- intel_plane->wm.tiling = fb->modifier[0];
- intel_plane->wm.rotation = plane->state->rotation;
-
- skl_update_wm(crtc);
-}
-
-static void ilk_update_wm(struct drm_crtc *crtc)
+static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_device *dev = dev_priv->dev;
+ struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
struct ilk_wm_maximums max;
+ struct intel_wm_config *config = &dev_priv->wm.config;
struct ilk_wm_values results = {};
enum intel_ddb_partitioning partitioning;
- struct intel_pipe_wm pipe_wm = {};
- struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
- struct intel_wm_config config = {};
-
- WARN_ON(cstate->base.active != intel_crtc->active);
-
- intel_compute_pipe_wm(cstate, &pipe_wm);
- if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
- return;
-
- intel_crtc->wm.active = pipe_wm;
-
- ilk_compute_wm_config(dev, &config);
-
- ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
- ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
+ ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_1_2, &max);
+ ilk_wm_merge(dev, config, &max, &lp_wm_1_2);
/* 5/6 split only in single pipe config on IVB+ */
if (INTEL_INFO(dev)->gen >= 7 &&
- config.num_pipes_active == 1 && config.sprites_enabled) {
- ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
- ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
+ config->num_pipes_active == 1 && config->sprites_enabled) {
+ ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_5_6, &max);
+ ilk_wm_merge(dev, config, &max, &lp_wm_5_6);
best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
} else {
@@ -3733,14 +3621,13 @@ static void ilk_update_wm(struct drm_crtc *crtc)
ilk_write_wm_values(dev_priv, &results);
}
-static void
-ilk_update_sprite_wm(struct drm_plane *plane,
- struct drm_crtc *crtc,
- uint32_t sprite_width, uint32_t sprite_height,
- int pixel_size, bool enabled, bool scaled)
+static void ilk_update_wm(struct drm_crtc *crtc)
{
- struct drm_device *dev = plane->dev;
- struct intel_plane *intel_plane = to_intel_plane(plane);
+ struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+
+ WARN_ON(cstate->base.active != intel_crtc->active);
/*
* IVB workaround: must disable low power watermarks for at least
@@ -3749,10 +3636,14 @@ ilk_update_sprite_wm(struct drm_plane *plane,
*
* WaCxSRDisabledForSpriteScaling:ivb
*/
- if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev))
- intel_wait_for_vblank(dev, intel_plane->pipe);
+ if (cstate->disable_lp_wm) {
+ ilk_disable_lp_wm(crtc->dev);
+ intel_wait_for_vblank(crtc->dev, intel_crtc->pipe);
+ }
+
+ intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
- ilk_update_wm(crtc);
+ ilk_program_watermarks(dev_priv);
}
static void skl_pipe_wm_active_state(uint32_t val,
@@ -3805,7 +3696,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct skl_wm_values *hw = &dev_priv->wm.skl_hw;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct skl_pipe_wm *active = &intel_crtc->wm.skl_active;
+ struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+ struct skl_pipe_wm *active = &cstate->wm.optimal.skl;
enum pipe pipe = intel_crtc->pipe;
int level, i, max_level;
uint32_t temp;
@@ -3849,6 +3741,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
temp = hw->plane_trans[pipe][PLANE_CURSOR];
skl_pipe_wm_active_state(temp, active, true, true, i, 0);
+
+ intel_crtc->wm.active.skl = *active;
}
void skl_wm_get_hw_state(struct drm_device *dev)
@@ -3868,9 +3762,10 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct ilk_wm_values *hw = &dev_priv->wm.hw;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_pipe_wm *active = &intel_crtc->wm.active;
+ struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+ struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
enum pipe pipe = intel_crtc->pipe;
- static const unsigned int wm0_pipe_reg[] = {
+ static const i915_reg_t wm0_pipe_reg[] = {
[PIPE_A] = WM0_PIPEA_ILK,
[PIPE_B] = WM0_PIPEB_ILK,
[PIPE_C] = WM0_PIPEC_IVB,
@@ -3907,6 +3802,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
for (level = 0; level <= max_level; level++)
active->wm[level].enable = true;
}
+
+ intel_crtc->wm.active.ilk = *active;
}
#define _FW_WM(value, plane) \
@@ -4132,21 +4029,6 @@ void intel_update_watermarks(struct drm_crtc *crtc)
dev_priv->display.update_wm(crtc);
}
-void intel_update_sprite_watermarks(struct drm_plane *plane,
- struct drm_crtc *crtc,
- uint32_t sprite_width,
- uint32_t sprite_height,
- int pixel_size,
- bool enabled, bool scaled)
-{
- struct drm_i915_private *dev_priv = plane->dev->dev_private;
-
- if (dev_priv->display.update_sprite_wm)
- dev_priv->display.update_sprite_wm(plane, crtc,
- sprite_width, sprite_height,
- pixel_size, enabled, scaled);
-}
-
/**
* Lock protecting IPS related data structures
*/
@@ -4414,7 +4296,7 @@ static void gen6_set_rps(struct drm_device *dev, u8 val)
struct drm_i915_private *dev_priv = dev->dev_private;
/* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */
- if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0))
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
return;
WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -4689,7 +4571,8 @@ static void gen6_init_rps_frequencies(struct drm_device *dev)
dev_priv->rps.max_freq = dev_priv->rps.rp0_freq;
dev_priv->rps.efficient_freq = dev_priv->rps.rp1_freq;
- if (IS_HASWELL(dev) || IS_BROADWELL(dev) || IS_SKYLAKE(dev)) {
+ if (IS_HASWELL(dev) || IS_BROADWELL(dev) ||
+ IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
ret = sandybridge_pcode_read(dev_priv,
HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL,
&ddcc_status);
@@ -4701,7 +4584,7 @@ static void gen6_init_rps_frequencies(struct drm_device *dev)
dev_priv->rps.max_freq);
}
- if (IS_SKYLAKE(dev)) {
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
/* Store the frequency values in 16.66 MHZ units, which is
the natural hardware unit for SKL */
dev_priv->rps.rp0_freq *= GEN9_FREQ_SCALER;
@@ -4738,7 +4621,7 @@ static void gen9_enable_rps(struct drm_device *dev)
gen6_init_rps_frequencies(dev);
/* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */
- if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) {
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
return;
}
@@ -4806,8 +4689,8 @@ static void gen9_enable_rc6(struct drm_device *dev)
DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
"on" : "off");
/* WaRsUseTimeoutMode */
- if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_D0) ||
- (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_A0)) {
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) ||
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */
I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
GEN7_RC_CTL_TO_MODE |
@@ -5055,7 +4938,7 @@ static void __gen6_update_ring_freq(struct drm_device *dev)
/* convert DDR frequency from units of 266.6MHz to bandwidth */
min_ring_freq = mult_frac(min_ring_freq, 8, 3);
- if (IS_SKYLAKE(dev)) {
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
/* Convert GT frequency to 50 HZ units */
min_gpu_freq = dev_priv->rps.min_freq / GEN9_FREQ_SCALER;
max_gpu_freq = dev_priv->rps.max_freq / GEN9_FREQ_SCALER;
@@ -5073,7 +4956,7 @@ static void __gen6_update_ring_freq(struct drm_device *dev)
int diff = max_gpu_freq - gpu_freq;
unsigned int ia_freq = 0, ring_freq = 0;
- if (IS_SKYLAKE(dev)) {
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
/*
* ring_freq = 2 * GT. ring_freq is in 100MHz units
* No floor required for ring frequency on SKL.
@@ -6201,7 +6084,7 @@ static void intel_gen6_powersave_work(struct work_struct *work)
} else if (INTEL_INFO(dev)->gen >= 9) {
gen9_enable_rc6(dev);
gen9_enable_rps(dev);
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
__gen6_update_ring_freq(dev);
} else if (IS_BROADWELL(dev)) {
gen8_enable_rps(dev);
@@ -7057,7 +6940,6 @@ void intel_init_pm(struct drm_device *dev)
dev_priv->display.init_clock_gating =
bxt_init_clock_gating;
dev_priv->display.update_wm = skl_update_wm;
- dev_priv->display.update_sprite_wm = skl_update_sprite_wm;
} else if (HAS_PCH_SPLIT(dev)) {
ilk_setup_wm_latency(dev);
@@ -7066,7 +6948,7 @@ void intel_init_pm(struct drm_device *dev)
(!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
dev_priv->display.update_wm = ilk_update_wm;
- dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
+ dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
} else {
DRM_DEBUG_KMS("Failed to read display plane latency. "
"Disable CxSR\n");
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 213581c215b3..bc5ea2a6cf4c 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -80,7 +80,7 @@ static void intel_psr_write_vsc(struct intel_dp *intel_dp,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc);
enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
- u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
+ i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
uint32_t *data = (uint32_t *) vsc_psr;
unsigned int i;
@@ -151,13 +151,31 @@ static void vlv_psr_enable_sink(struct intel_dp *intel_dp)
DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE);
}
+static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv,
+ enum port port)
+{
+ if (INTEL_INFO(dev_priv)->gen >= 9)
+ return DP_AUX_CH_CTL(port);
+ else
+ return EDP_PSR_AUX_CTL;
+}
+
+static i915_reg_t psr_aux_data_reg(struct drm_i915_private *dev_priv,
+ enum port port, int index)
+{
+ if (INTEL_INFO(dev_priv)->gen >= 9)
+ return DP_AUX_CH_DATA(port, index);
+ else
+ return EDP_PSR_AUX_DATA(index);
+}
+
static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t aux_clock_divider;
- uint32_t aux_data_reg, aux_ctl_reg;
+ i915_reg_t aux_ctl_reg;
int precharge = 0x3;
static const uint8_t aux_msg[] = {
[0] = DP_AUX_NATIVE_WRITE << 4,
@@ -166,6 +184,7 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
[3] = 1 - 1,
[4] = DP_SET_POWER_D0,
};
+ enum port port = dig_port->port;
int i;
BUILD_BUG_ON(sizeof(aux_msg) > 20);
@@ -181,14 +200,11 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp)
DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF,
DP_AUX_FRAME_SYNC_ENABLE);
- aux_data_reg = (INTEL_INFO(dev)->gen >= 9) ?
- DPA_AUX_CH_DATA1 : EDP_PSR_AUX_DATA1(dev);
- aux_ctl_reg = (INTEL_INFO(dev)->gen >= 9) ?
- DPA_AUX_CH_CTL : EDP_PSR_AUX_CTL(dev);
+ aux_ctl_reg = psr_aux_ctl_reg(dev_priv, port);
/* Setup AUX registers */
for (i = 0; i < sizeof(aux_msg); i += 4)
- I915_WRITE(aux_data_reg + i,
+ I915_WRITE(psr_aux_data_reg(dev_priv, port, i >> 2),
intel_dp_pack_aux(&aux_msg[i], sizeof(aux_msg) - i));
if (INTEL_INFO(dev)->gen >= 9) {
@@ -267,16 +283,11 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) {
- /* It doesn't mean we shouldn't send TPS patters, so let's
- send the minimal TP1 possible and skip TP2. */
- val |= EDP_PSR_TP1_TIME_100us;
- val |= EDP_PSR_TP2_TP3_TIME_0us;
- val |= EDP_PSR_SKIP_AUX_EXIT;
/* Sink should be able to train with the 5 or 6 idle patterns */
idle_frames += 4;
}
- I915_WRITE(EDP_PSR_CTL(dev), val |
+ I915_WRITE(EDP_PSR_CTL, val |
(IS_BROADWELL(dev) ? 0 : link_entry_time) |
max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
@@ -340,7 +351,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE);
+ WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
WARN_ON(dev_priv->psr.active);
lockdep_assert_held(&dev_priv->psr.lock);
@@ -404,7 +415,7 @@ void intel_psr_enable(struct intel_dp *intel_dp)
}
/* Avoid continuous PSR exit by masking memup and hpd */
- I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP |
+ I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP |
EDP_PSR_DEBUG_MASK_HPD);
/* Enable PSR on the panel */
@@ -427,6 +438,19 @@ void intel_psr_enable(struct intel_dp *intel_dp)
vlv_psr_enable_source(intel_dp);
}
+ /*
+ * FIXME: Activation should happen immediately since this function
+ * is just called after pipe is fully trained and enabled.
+ * However on every platform we face issues when first activation
+ * follows a modeset so quickly.
+ * - On VLV/CHV we get bank screen on first activation
+ * - On HSW/BDW we get a recoverable frozen screen until next
+ * exit-activate sequence.
+ */
+ if (INTEL_INFO(dev)->gen < 9)
+ schedule_delayed_work(&dev_priv->psr.work,
+ msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
+
dev_priv->psr.enabled = intel_dp;
unlock:
mutex_unlock(&dev_priv->psr.lock);
@@ -466,17 +490,17 @@ static void hsw_psr_disable(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dev->dev_private;
if (dev_priv->psr.active) {
- I915_WRITE(EDP_PSR_CTL(dev),
- I915_READ(EDP_PSR_CTL(dev)) & ~EDP_PSR_ENABLE);
+ I915_WRITE(EDP_PSR_CTL,
+ I915_READ(EDP_PSR_CTL) & ~EDP_PSR_ENABLE);
/* Wait till PSR is idle */
- if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
+ if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL) &
EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
DRM_ERROR("Timed out waiting for PSR Idle State\n");
dev_priv->psr.active = false;
} else {
- WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE);
+ WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
}
}
@@ -523,7 +547,7 @@ static void intel_psr_work(struct work_struct *work)
* and be ready for re-enable.
*/
if (HAS_DDI(dev_priv->dev)) {
- if (wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev_priv->dev)) &
+ if (wait_for((I915_READ(EDP_PSR_STATUS_CTL) &
EDP_PSR_STATUS_STATE_MASK) == 0, 50)) {
DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n");
return;
@@ -566,11 +590,11 @@ static void intel_psr_exit(struct drm_device *dev)
return;
if (HAS_DDI(dev)) {
- val = I915_READ(EDP_PSR_CTL(dev));
+ val = I915_READ(EDP_PSR_CTL);
WARN_ON(!(val & EDP_PSR_ENABLE));
- I915_WRITE(EDP_PSR_CTL(dev), val & ~EDP_PSR_ENABLE);
+ I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_ENABLE);
} else {
val = I915_READ(VLV_PSRCTL(pipe));
@@ -700,7 +724,6 @@ void intel_psr_flush(struct drm_device *dev,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
enum pipe pipe;
- int delay_ms = HAS_DDI(dev) ? 100 : 500;
mutex_lock(&dev_priv->psr.lock);
if (!dev_priv->psr.enabled) {
@@ -735,8 +758,9 @@ void intel_psr_flush(struct drm_device *dev,
}
if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits)
- schedule_delayed_work(&dev_priv->psr.work,
- msecs_to_jiffies(delay_ms));
+ if (!work_busy(&dev_priv->psr.work.work))
+ schedule_delayed_work(&dev_priv->psr.work,
+ msecs_to_jiffies(100));
mutex_unlock(&dev_priv->psr.lock);
}
@@ -751,6 +775,9 @@ void intel_psr_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ dev_priv->psr_mmio_base = IS_HASWELL(dev_priv) ?
+ HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE;
+
INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work);
mutex_init(&dev_priv->psr.lock);
}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 9461a238f5d5..57d78f264b53 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -481,7 +481,7 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring)
{
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = ring->dev->dev_private;
- u32 mmio = 0;
+ i915_reg_t mmio;
/* The ring status page addresses are no longer next to the rest of
* the ring registers as of gen7.
@@ -524,7 +524,7 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring)
* invalidating the TLB?
*/
if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) {
- u32 reg = RING_INSTPM(ring->mmio_base);
+ i915_reg_t reg = RING_INSTPM(ring->mmio_base);
/* ring should be idle before issuing a sync flush*/
WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
@@ -733,7 +733,7 @@ static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count));
for (i = 0; i < w->count; i++) {
- intel_ring_emit(ring, w->reg[i].addr);
+ intel_ring_emit_reg(ring, w->reg[i].addr);
intel_ring_emit(ring, w->reg[i].value);
}
intel_ring_emit(ring, MI_NOOP);
@@ -766,7 +766,8 @@ static int intel_rcs_ctx_init(struct drm_i915_gem_request *req)
}
static int wa_add(struct drm_i915_private *dev_priv,
- const u32 addr, const u32 mask, const u32 val)
+ i915_reg_t addr,
+ const u32 mask, const u32 val)
{
const u32 idx = dev_priv->workarounds.count;
@@ -924,17 +925,15 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
- if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) == SKL_REVID_A0 ||
- INTEL_REVID(dev) == SKL_REVID_B0)) ||
- (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) {
- /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */
+ /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1))
WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
GEN9_DG_MIRROR_FIX_ENABLE);
- }
- if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) ||
- (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) {
- /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
+ /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
GEN9_RHWO_OPTIMIZATION_DISABLE);
/*
@@ -944,12 +943,10 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
*/
}
- if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) >= SKL_REVID_C0) ||
- IS_BROXTON(dev)) {
- /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */
+ /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */
+ if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER) || IS_BROXTON(dev))
WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
GEN9_ENABLE_YV12_BUGFIX);
- }
/* Wa4x4STCOptimizationDisable:skl,bxt */
/* WaDisablePartialResolveInVc:skl,bxt */
@@ -961,24 +958,22 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
GEN9_CCS_TLB_PREFETCH_ENABLE);
/* WaDisableMaskBasedCammingInRCC:skl,bxt */
- if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_C0) ||
- (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0))
+ if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_C0) ||
+ IS_BXT_REVID(dev, 0, BXT_REVID_A1))
WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
PIXEL_MASK_CAMMING_DISABLE);
/* WaForceContextSaveRestoreNonCoherent:skl,bxt */
tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT;
- if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_F0) ||
- (IS_BROXTON(dev) && INTEL_REVID(dev) >= BXT_REVID_B0))
+ if (IS_SKL_REVID(dev, SKL_REVID_F0, SKL_REVID_F0) ||
+ IS_BXT_REVID(dev, BXT_REVID_B0, REVID_FOREVER))
tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE;
WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp);
/* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt */
- if (IS_SKYLAKE(dev) ||
- (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_B0)) {
+ if (IS_SKYLAKE(dev) || IS_BXT_REVID(dev, 0, BXT_REVID_B0))
WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
GEN8_SAMPLER_POWER_BYPASS_DIS);
- }
/* WaDisableSTUnitPowerOptimization:skl,bxt */
WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
@@ -1038,7 +1033,7 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
if (ret)
return ret;
- if (INTEL_REVID(dev) <= SKL_REVID_D0) {
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) {
/* WaDisableHDCInvalidation:skl */
I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
BDW_DISABLE_HDC_INVALIDATION);
@@ -1051,23 +1046,23 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
/* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
* involving this register should also be added to WA batch as required.
*/
- if (INTEL_REVID(dev) <= SKL_REVID_E0)
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_E0))
/* WaDisableLSQCROPERFforOCL:skl */
I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
GEN8_LQSC_RO_PERF_DIS);
/* WaEnableGapsTsvCreditFix:skl */
- if (IS_SKYLAKE(dev) && (INTEL_REVID(dev) >= SKL_REVID_C0)) {
+ if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER)) {
I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
GEN9_GAPS_TSV_CREDIT_DISABLE));
}
/* WaDisablePowerCompilerClockGating:skl */
- if (INTEL_REVID(dev) == SKL_REVID_B0)
+ if (IS_SKL_REVID(dev, SKL_REVID_B0, SKL_REVID_B0))
WA_SET_BIT_MASKED(HIZ_CHICKEN,
BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
- if (INTEL_REVID(dev) <= SKL_REVID_D0) {
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) {
/*
*Use Force Non-Coherent whenever executing a 3D context. This
* is a workaround for a possible hang in the unlikely event
@@ -1078,19 +1073,17 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
HDC_FORCE_NON_COHERENT);
}
- if (INTEL_REVID(dev) == SKL_REVID_C0 ||
- INTEL_REVID(dev) == SKL_REVID_D0)
- /* WaBarrierPerformanceFixDisable:skl */
+ /* WaBarrierPerformanceFixDisable:skl */
+ if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_D0))
WA_SET_BIT_MASKED(HDC_CHICKEN0,
HDC_FENCE_DEST_SLM_DISABLE |
HDC_BARRIER_PERFORMANCE_DISABLE);
/* WaDisableSbeCacheDispatchPortSharing:skl */
- if (INTEL_REVID(dev) <= SKL_REVID_F0) {
+ if (IS_SKL_REVID(dev, 0, SKL_REVID_F0))
WA_SET_BIT_MASKED(
GEN7_HALF_SLICE_CHICKEN1,
GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
- }
return skl_tune_iz_hashing(ring);
}
@@ -1107,11 +1100,11 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring)
/* WaStoreMultiplePTEenable:bxt */
/* This is a requirement according to Hardware specification */
- if (INTEL_REVID(dev) == BXT_REVID_A0)
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
/* WaSetClckGatingDisableMedia:bxt */
- if (INTEL_REVID(dev) == BXT_REVID_A0) {
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
}
@@ -1121,7 +1114,7 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring)
STALL_DOP_GATING_DISABLE);
/* WaDisableSbeCacheDispatchPortSharing:bxt */
- if (INTEL_REVID(dev) <= BXT_REVID_B0) {
+ if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) {
WA_SET_BIT_MASKED(
GEN7_HALF_SLICE_CHICKEN1,
GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
@@ -1319,11 +1312,13 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req,
return ret;
for_each_ring(useless, dev_priv, i) {
- u32 mbox_reg = signaller->semaphore.mbox.signal[i];
- if (mbox_reg != GEN6_NOSYNC) {
+ i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[i];
+
+ if (i915_mmio_reg_valid(mbox_reg)) {
u32 seqno = i915_gem_request_get_seqno(signaller_req);
+
intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(signaller, mbox_reg);
+ intel_ring_emit_reg(signaller, mbox_reg);
intel_ring_emit(signaller, seqno);
}
}
@@ -2004,11 +1999,35 @@ static int init_phys_status_page(struct intel_engine_cs *ring)
void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
{
- iounmap(ringbuf->virtual_start);
+ if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen)
+ vunmap(ringbuf->virtual_start);
+ else
+ iounmap(ringbuf->virtual_start);
ringbuf->virtual_start = NULL;
i915_gem_object_ggtt_unpin(ringbuf->obj);
}
+static u32 *vmap_obj(struct drm_i915_gem_object *obj)
+{
+ struct sg_page_iter sg_iter;
+ struct page **pages;
+ void *addr;
+ int i;
+
+ pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
+ if (pages == NULL)
+ return NULL;
+
+ i = 0;
+ for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
+ pages[i++] = sg_page_iter_page(&sg_iter);
+
+ addr = vmap(pages, i, 0, PAGE_KERNEL);
+ drm_free_large(pages);
+
+ return addr;
+}
+
int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
struct intel_ringbuffer *ringbuf)
{
@@ -2016,21 +2035,39 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
struct drm_i915_gem_object *obj = ringbuf->obj;
int ret;
- ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
- if (ret)
- return ret;
+ if (HAS_LLC(dev_priv) && !obj->stolen) {
+ ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 0);
+ if (ret)
+ return ret;
- ret = i915_gem_object_set_to_gtt_domain(obj, true);
- if (ret) {
- i915_gem_object_ggtt_unpin(obj);
- return ret;
- }
+ ret = i915_gem_object_set_to_cpu_domain(obj, true);
+ if (ret) {
+ i915_gem_object_ggtt_unpin(obj);
+ return ret;
+ }
+
+ ringbuf->virtual_start = vmap_obj(obj);
+ if (ringbuf->virtual_start == NULL) {
+ i915_gem_object_ggtt_unpin(obj);
+ return -ENOMEM;
+ }
+ } else {
+ ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
+ if (ret)
+ return ret;
- ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base +
- i915_gem_obj_ggtt_offset(obj), ringbuf->size);
- if (ringbuf->virtual_start == NULL) {
- i915_gem_object_ggtt_unpin(obj);
- return -EINVAL;
+ ret = i915_gem_object_set_to_gtt_domain(obj, true);
+ if (ret) {
+ i915_gem_object_ggtt_unpin(obj);
+ return ret;
+ }
+
+ ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base +
+ i915_gem_obj_ggtt_offset(obj), ringbuf->size);
+ if (ringbuf->virtual_start == NULL) {
+ i915_gem_object_ggtt_unpin(obj);
+ return -EINVAL;
+ }
}
return 0;
@@ -2070,10 +2107,14 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)
int ret;
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
- if (ring == NULL)
+ if (ring == NULL) {
+ DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n",
+ engine->name);
return ERR_PTR(-ENOMEM);
+ }
ring->ring = engine;
+ list_add(&ring->link, &engine->buffers);
ring->size = size;
/* Workaround an erratum on the i830 which causes a hang if
@@ -2089,8 +2130,9 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)
ret = intel_alloc_ringbuffer_obj(engine->dev, ring);
if (ret) {
- DRM_ERROR("Failed to allocate ringbuffer %s: %d\n",
- engine->name, ret);
+ DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n",
+ engine->name, ret);
+ list_del(&ring->link);
kfree(ring);
return ERR_PTR(ret);
}
@@ -2102,6 +2144,7 @@ void
intel_ringbuffer_free(struct intel_ringbuffer *ring)
{
intel_destroy_ringbuffer_obj(ring);
+ list_del(&ring->link);
kfree(ring);
}
@@ -2117,6 +2160,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
INIT_LIST_HEAD(&ring->active_list);
INIT_LIST_HEAD(&ring->request_list);
INIT_LIST_HEAD(&ring->execlist_queue);
+ INIT_LIST_HEAD(&ring->buffers);
i915_gem_batch_pool_init(dev, &ring->batch_pool);
memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno));
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 49fa41dc0eb6..5d1eb206151d 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -100,6 +100,7 @@ struct intel_ringbuffer {
void __iomem *virtual_start;
struct intel_engine_cs *ring;
+ struct list_head link;
u32 head;
u32 tail;
@@ -157,6 +158,7 @@ struct intel_engine_cs {
u32 mmio_base;
struct drm_device *dev;
struct intel_ringbuffer *buffer;
+ struct list_head buffers;
/*
* A pool of objects to use as shadow copies of client batch buffers
@@ -247,7 +249,7 @@ struct intel_engine_cs {
/* our mbox written by others */
u32 wait[I915_NUM_RINGS];
/* mboxes this ring signals to */
- u32 signal[I915_NUM_RINGS];
+ i915_reg_t signal[I915_NUM_RINGS];
} mbox;
u64 signal_ggtt[I915_NUM_RINGS];
};
@@ -441,6 +443,11 @@ static inline void intel_ring_emit(struct intel_engine_cs *ring,
iowrite32(data, ringbuf->virtual_start + ringbuf->tail);
ringbuf->tail += 4;
}
+static inline void intel_ring_emit_reg(struct intel_engine_cs *ring,
+ i915_reg_t reg)
+{
+ intel_ring_emit(ring, i915_mmio_reg_offset(reg));
+}
static inline void intel_ring_advance(struct intel_engine_cs *ring)
{
struct intel_ringbuffer *ringbuf = ring->buffer;
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 7e23d65c9b24..afca6c940b9a 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -49,21 +49,18 @@
* present for a given platform.
*/
-#define GEN9_ENABLE_DC5(dev) 0
-#define SKL_ENABLE_DC6(dev) IS_SKYLAKE(dev)
-
#define for_each_power_well(i, power_well, domain_mask, power_domains) \
for (i = 0; \
i < (power_domains)->power_well_count && \
((power_well) = &(power_domains)->power_wells[i]); \
i++) \
- if ((power_well)->domains & (domain_mask))
+ for_each_if ((power_well)->domains & (domain_mask))
#define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \
for (i = (power_domains)->power_well_count - 1; \
i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\
i--) \
- if ((power_well)->domains & (domain_mask))
+ for_each_if ((power_well)->domains & (domain_mask))
bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
int power_well_id);
@@ -244,12 +241,6 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv,
gen8_irq_power_well_post_enable(dev_priv,
1 << PIPE_C | 1 << PIPE_B);
}
-
- if (power_well->data == SKL_DISP_PW_1) {
- if (!dev_priv->power_domains.initializing)
- intel_prepare_ddi(dev);
- gen8_irq_power_well_post_enable(dev_priv, 1 << PIPE_A);
- }
}
static void hsw_set_power_well(struct drm_i915_private *dev_priv,
@@ -292,58 +283,38 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
BIT(POWER_DOMAIN_TRANSCODER_C) | \
BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \
BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_E_2_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_D_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_E_LANES) | \
BIT(POWER_DOMAIN_AUX_B) | \
BIT(POWER_DOMAIN_AUX_C) | \
BIT(POWER_DOMAIN_AUX_D) | \
BIT(POWER_DOMAIN_AUDIO) | \
BIT(POWER_DOMAIN_VGA) | \
BIT(POWER_DOMAIN_INIT))
-#define SKL_DISPLAY_POWERWELL_1_POWER_DOMAINS ( \
- SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \
- BIT(POWER_DOMAIN_PLLS) | \
- BIT(POWER_DOMAIN_PIPE_A) | \
- BIT(POWER_DOMAIN_TRANSCODER_EDP) | \
- BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \
- BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \
- BIT(POWER_DOMAIN_AUX_A) | \
- BIT(POWER_DOMAIN_INIT))
#define SKL_DISPLAY_DDI_A_E_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_E_2_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_A_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_E_LANES) | \
BIT(POWER_DOMAIN_INIT))
#define SKL_DISPLAY_DDI_B_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \
BIT(POWER_DOMAIN_INIT))
#define SKL_DISPLAY_DDI_C_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \
BIT(POWER_DOMAIN_INIT))
#define SKL_DISPLAY_DDI_D_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_D_LANES) | \
BIT(POWER_DOMAIN_INIT))
-#define SKL_DISPLAY_MISC_IO_POWER_DOMAINS ( \
- SKL_DISPLAY_POWERWELL_1_POWER_DOMAINS | \
- BIT(POWER_DOMAIN_PLLS) | \
+#define SKL_DISPLAY_DC_OFF_POWER_DOMAINS ( \
+ SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \
+ BIT(POWER_DOMAIN_MODESET) | \
+ BIT(POWER_DOMAIN_AUX_A) | \
BIT(POWER_DOMAIN_INIT))
#define SKL_DISPLAY_ALWAYS_ON_POWER_DOMAINS ( \
- (POWER_DOMAIN_MASK & ~(SKL_DISPLAY_POWERWELL_1_POWER_DOMAINS | \
+ (POWER_DOMAIN_MASK & ~( \
SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \
- SKL_DISPLAY_DDI_A_E_POWER_DOMAINS | \
- SKL_DISPLAY_DDI_B_POWER_DOMAINS | \
- SKL_DISPLAY_DDI_C_POWER_DOMAINS | \
- SKL_DISPLAY_DDI_D_POWER_DOMAINS | \
- SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) | \
+ SKL_DISPLAY_DC_OFF_POWER_DOMAINS)) | \
BIT(POWER_DOMAIN_INIT))
#define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \
@@ -354,10 +325,8 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
BIT(POWER_DOMAIN_TRANSCODER_C) | \
BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \
BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \
BIT(POWER_DOMAIN_AUX_B) | \
BIT(POWER_DOMAIN_AUX_C) | \
BIT(POWER_DOMAIN_AUDIO) | \
@@ -369,11 +338,15 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
BIT(POWER_DOMAIN_PIPE_A) | \
BIT(POWER_DOMAIN_TRANSCODER_EDP) | \
BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \
- BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_A_LANES) | \
BIT(POWER_DOMAIN_AUX_A) | \
BIT(POWER_DOMAIN_PLLS) | \
BIT(POWER_DOMAIN_INIT))
+#define BXT_DISPLAY_DC_OFF_POWER_DOMAINS ( \
+ BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS | \
+ BIT(POWER_DOMAIN_MODESET) | \
+ BIT(POWER_DOMAIN_AUX_A) | \
+ BIT(POWER_DOMAIN_INIT))
#define BXT_DISPLAY_ALWAYS_ON_POWER_DOMAINS ( \
(POWER_DOMAIN_MASK & ~(BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS | \
BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS)) | \
@@ -417,46 +390,74 @@ static void assert_can_disable_dc9(struct drm_i915_private *dev_priv)
*/
}
-void bxt_enable_dc9(struct drm_i915_private *dev_priv)
+static void gen9_set_dc_state_debugmask_memory_up(
+ struct drm_i915_private *dev_priv)
{
uint32_t val;
- assert_can_enable_dc9(dev_priv);
+ /* The below bit doesn't need to be cleared ever afterwards */
+ val = I915_READ(DC_STATE_DEBUG);
+ if (!(val & DC_STATE_DEBUG_MASK_MEMORY_UP)) {
+ val |= DC_STATE_DEBUG_MASK_MEMORY_UP;
+ I915_WRITE(DC_STATE_DEBUG, val);
+ POSTING_READ(DC_STATE_DEBUG);
+ }
+}
- DRM_DEBUG_KMS("Enabling DC9\n");
+static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
+{
+ uint32_t val;
+ uint32_t mask;
+
+ mask = DC_STATE_EN_UPTO_DC5;
+ if (IS_BROXTON(dev_priv))
+ mask |= DC_STATE_EN_DC9;
+ else
+ mask |= DC_STATE_EN_UPTO_DC6;
+
+ WARN_ON_ONCE(state & ~mask);
+
+ if (i915.enable_dc == 0)
+ state = DC_STATE_DISABLE;
+ else if (i915.enable_dc == 1 && state > DC_STATE_EN_UPTO_DC5)
+ state = DC_STATE_EN_UPTO_DC5;
+
+ if (state & DC_STATE_EN_UPTO_DC5_DC6_MASK)
+ gen9_set_dc_state_debugmask_memory_up(dev_priv);
val = I915_READ(DC_STATE_EN);
- val |= DC_STATE_EN_DC9;
+ DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n",
+ val & mask, state);
+ val &= ~mask;
+ val |= state;
I915_WRITE(DC_STATE_EN, val);
POSTING_READ(DC_STATE_EN);
}
-void bxt_disable_dc9(struct drm_i915_private *dev_priv)
+void bxt_enable_dc9(struct drm_i915_private *dev_priv)
{
- uint32_t val;
+ assert_can_enable_dc9(dev_priv);
+
+ DRM_DEBUG_KMS("Enabling DC9\n");
+
+ gen9_set_dc_state(dev_priv, DC_STATE_EN_DC9);
+}
+void bxt_disable_dc9(struct drm_i915_private *dev_priv)
+{
assert_can_disable_dc9(dev_priv);
DRM_DEBUG_KMS("Disabling DC9\n");
- val = I915_READ(DC_STATE_EN);
- val &= ~DC_STATE_EN_DC9;
- I915_WRITE(DC_STATE_EN, val);
- POSTING_READ(DC_STATE_EN);
+ gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
}
-static void gen9_set_dc_state_debugmask_memory_up(
- struct drm_i915_private *dev_priv)
+static void assert_csr_loaded(struct drm_i915_private *dev_priv)
{
- uint32_t val;
-
- /* The below bit doesn't need to be cleared ever afterwards */
- val = I915_READ(DC_STATE_DEBUG);
- if (!(val & DC_STATE_DEBUG_MASK_MEMORY_UP)) {
- val |= DC_STATE_DEBUG_MASK_MEMORY_UP;
- I915_WRITE(DC_STATE_DEBUG, val);
- POSTING_READ(DC_STATE_DEBUG);
- }
+ WARN_ONCE(!I915_READ(CSR_PROGRAM(0)),
+ "CSR program storage start is NULL\n");
+ WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n");
+ WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
}
static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
@@ -479,8 +480,6 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
{
- bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
- SKL_DISP_PW_2);
/*
* During initialization, the firmware may not be loaded yet.
* We still want to make sure that the DC enabling flag is cleared.
@@ -488,40 +487,17 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
if (dev_priv->power_domains.initializing)
return;
- WARN_ONCE(!pg2_enabled, "PG2 not enabled to disable DC5.\n");
WARN_ONCE(dev_priv->pm.suspended,
"Disabling of DC5 while platform is runtime-suspended should never happen.\n");
}
static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
{
- uint32_t val;
-
assert_can_enable_dc5(dev_priv);
DRM_DEBUG_KMS("Enabling DC5\n");
- gen9_set_dc_state_debugmask_memory_up(dev_priv);
-
- val = I915_READ(DC_STATE_EN);
- val &= ~DC_STATE_EN_UPTO_DC5_DC6_MASK;
- val |= DC_STATE_EN_UPTO_DC5;
- I915_WRITE(DC_STATE_EN, val);
- POSTING_READ(DC_STATE_EN);
-}
-
-static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
-{
- uint32_t val;
-
- assert_can_disable_dc5(dev_priv);
-
- DRM_DEBUG_KMS("Disabling DC5\n");
-
- val = I915_READ(DC_STATE_EN);
- val &= ~DC_STATE_EN_UPTO_DC5;
- I915_WRITE(DC_STATE_EN, val);
- POSTING_READ(DC_STATE_EN);
+ gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5);
}
static void assert_can_enable_dc6(struct drm_i915_private *dev_priv)
@@ -547,40 +523,37 @@ static void assert_can_disable_dc6(struct drm_i915_private *dev_priv)
if (dev_priv->power_domains.initializing)
return;
- assert_csr_loaded(dev_priv);
WARN_ONCE(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
"DC6 already programmed to be disabled.\n");
}
-static void skl_enable_dc6(struct drm_i915_private *dev_priv)
+static void gen9_disable_dc5_dc6(struct drm_i915_private *dev_priv)
{
- uint32_t val;
+ assert_can_disable_dc5(dev_priv);
+
+ if (IS_SKYLAKE(dev_priv) && i915.enable_dc != 0 && i915.enable_dc != 1)
+ assert_can_disable_dc6(dev_priv);
+ gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+}
+
+void skl_enable_dc6(struct drm_i915_private *dev_priv)
+{
assert_can_enable_dc6(dev_priv);
DRM_DEBUG_KMS("Enabling DC6\n");
- gen9_set_dc_state_debugmask_memory_up(dev_priv);
+ gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
- val = I915_READ(DC_STATE_EN);
- val &= ~DC_STATE_EN_UPTO_DC5_DC6_MASK;
- val |= DC_STATE_EN_UPTO_DC6;
- I915_WRITE(DC_STATE_EN, val);
- POSTING_READ(DC_STATE_EN);
}
-static void skl_disable_dc6(struct drm_i915_private *dev_priv)
+void skl_disable_dc6(struct drm_i915_private *dev_priv)
{
- uint32_t val;
-
assert_can_disable_dc6(dev_priv);
DRM_DEBUG_KMS("Disabling DC6\n");
- val = I915_READ(DC_STATE_EN);
- val &= ~DC_STATE_EN_UPTO_DC6;
- I915_WRITE(DC_STATE_EN, val);
- POSTING_READ(DC_STATE_EN);
+ gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
}
static void skl_set_power_well(struct drm_i915_private *dev_priv,
@@ -630,20 +603,16 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
!I915_READ(HSW_PWR_WELL_BIOS),
"Invalid for power well status to be enabled, unless done by the BIOS, \
when request is to disable!\n");
- if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
- power_well->data == SKL_DISP_PW_2) {
- if (SKL_ENABLE_DC6(dev)) {
- skl_disable_dc6(dev_priv);
- /*
- * DDI buffer programming unnecessary during driver-load/resume
- * as it's already done during modeset initialization then.
- * It's also invalid here as encoder list is still uninitialized.
- */
- if (!dev_priv->power_domains.initializing)
- intel_prepare_ddi(dev);
- } else {
- gen9_disable_dc5(dev_priv);
- }
+ if (power_well->data == SKL_DISP_PW_2) {
+ /*
+ * DDI buffer programming unnecessary during
+ * driver-load/resume as it's already done
+ * during modeset initialization then. It's
+ * also invalid here as encoder list is still
+ * uninitialized.
+ */
+ if (!dev_priv->power_domains.initializing)
+ intel_prepare_ddi(dev);
}
I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
}
@@ -658,34 +627,9 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
}
} else {
if (enable_requested) {
- if (IS_SKYLAKE(dev) &&
- (power_well->data == SKL_DISP_PW_1) &&
- (intel_csr_load_status_get(dev_priv) == FW_LOADED))
- DRM_DEBUG_KMS("Not Disabling PW1, dmc will handle\n");
- else {
- I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask);
- POSTING_READ(HSW_PWR_WELL_DRIVER);
- DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
- }
-
- if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
- power_well->data == SKL_DISP_PW_2) {
- enum csr_state state;
- /* TODO: wait for a completion event or
- * similar here instead of busy
- * waiting using wait_for function.
- */
- wait_for((state = intel_csr_load_status_get(dev_priv)) !=
- FW_UNINITIALIZED, 1000);
- if (state != FW_LOADED)
- DRM_DEBUG("CSR firmware not ready (%d)\n",
- state);
- else
- if (SKL_ENABLE_DC6(dev))
- skl_enable_dc6(dev_priv);
- else
- gen9_enable_dc5(dev_priv);
- }
+ I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask);
+ POSTING_READ(HSW_PWR_WELL_DRIVER);
+ DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
}
}
@@ -760,6 +704,41 @@ static void skl_power_well_disable(struct drm_i915_private *dev_priv,
skl_set_power_well(dev_priv, power_well, false);
}
+static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ return (I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0;
+}
+
+static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ gen9_disable_dc5_dc6(dev_priv);
+}
+
+static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ if (IS_SKYLAKE(dev_priv) && i915.enable_dc != 0 && i915.enable_dc != 1)
+ skl_enable_dc6(dev_priv);
+ else
+ gen9_enable_dc5(dev_priv);
+}
+
+static void gen9_dc_off_power_well_sync_hw(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ if (power_well->count > 0) {
+ gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+ } else {
+ if (IS_SKYLAKE(dev_priv) && i915.enable_dc != 0 &&
+ i915.enable_dc != 1)
+ gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
+ else
+ gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5);
+ }
+}
+
static void i9xx_always_on_power_well_noop(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
@@ -974,10 +953,12 @@ static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_pr
int power_well_id)
{
struct i915_power_domains *power_domains = &dev_priv->power_domains;
- struct i915_power_well *power_well;
int i;
- for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
+ for (i = 0; i < power_domains->power_well_count; i++) {
+ struct i915_power_well *power_well;
+
+ power_well = &power_domains->power_wells[i];
if (power_well->data == power_well_id)
return power_well;
}
@@ -1458,7 +1439,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
WARN_ON(!power_well->count);
- if (!--power_well->count && i915.disable_power_well)
+ if (!--power_well->count)
intel_power_well_disable(dev_priv, power_well);
}
@@ -1470,14 +1451,10 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
#define HSW_ALWAYS_ON_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PIPE_A) | \
BIT(POWER_DOMAIN_TRANSCODER_EDP) | \
- BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_A_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_D_LANES) | \
BIT(POWER_DOMAIN_PORT_CRT) | \
BIT(POWER_DOMAIN_PLLS) | \
BIT(POWER_DOMAIN_AUX_A) | \
@@ -1501,49 +1478,42 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
#define VLV_DISPLAY_POWER_DOMAINS POWER_DOMAIN_MASK
#define VLV_DPIO_CMN_BC_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \
BIT(POWER_DOMAIN_PORT_CRT) | \
BIT(POWER_DOMAIN_AUX_B) | \
BIT(POWER_DOMAIN_AUX_C) | \
BIT(POWER_DOMAIN_INIT))
#define VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \
BIT(POWER_DOMAIN_AUX_B) | \
BIT(POWER_DOMAIN_INIT))
#define VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \
BIT(POWER_DOMAIN_AUX_B) | \
BIT(POWER_DOMAIN_INIT))
#define VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \
BIT(POWER_DOMAIN_AUX_C) | \
BIT(POWER_DOMAIN_INIT))
#define VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \
BIT(POWER_DOMAIN_AUX_C) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_DPIO_CMN_BC_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \
BIT(POWER_DOMAIN_AUX_B) | \
BIT(POWER_DOMAIN_AUX_C) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_DPIO_CMN_D_POWER_DOMAINS ( \
- BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \
- BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
+ BIT(POWER_DOMAIN_PORT_DDI_D_LANES) | \
BIT(POWER_DOMAIN_AUX_D) | \
BIT(POWER_DOMAIN_INIT))
@@ -1591,6 +1561,13 @@ static const struct i915_power_well_ops skl_power_well_ops = {
.is_enabled = skl_power_well_enabled,
};
+static const struct i915_power_well_ops gen9_dc_off_power_well_ops = {
+ .sync_hw = gen9_dc_off_power_well_sync_hw,
+ .enable = gen9_dc_off_power_well_enable,
+ .disable = gen9_dc_off_power_well_disable,
+ .is_enabled = gen9_dc_off_power_well_enabled,
+};
+
static struct i915_power_well hsw_power_wells[] = {
{
.name = "always-on",
@@ -1646,6 +1623,7 @@ static struct i915_power_well vlv_power_wells[] = {
.always_on = 1,
.domains = VLV_ALWAYS_ON_POWER_DOMAINS,
.ops = &i9xx_always_on_power_well_ops,
+ .data = PUNIT_POWER_WELL_ALWAYS_ON,
},
{
.name = "display",
@@ -1747,20 +1725,29 @@ static struct i915_power_well skl_power_wells[] = {
.always_on = 1,
.domains = SKL_DISPLAY_ALWAYS_ON_POWER_DOMAINS,
.ops = &i9xx_always_on_power_well_ops,
+ .data = SKL_DISP_PW_ALWAYS_ON,
},
{
.name = "power well 1",
- .domains = SKL_DISPLAY_POWERWELL_1_POWER_DOMAINS,
+ /* Handled by the DMC firmware */
+ .domains = 0,
.ops = &skl_power_well_ops,
.data = SKL_DISP_PW_1,
},
{
.name = "MISC IO power well",
- .domains = SKL_DISPLAY_MISC_IO_POWER_DOMAINS,
+ /* Handled by the DMC firmware */
+ .domains = 0,
.ops = &skl_power_well_ops,
.data = SKL_DISP_PW_MISC_IO,
},
{
+ .name = "DC off",
+ .domains = SKL_DISPLAY_DC_OFF_POWER_DOMAINS,
+ .ops = &gen9_dc_off_power_well_ops,
+ .data = SKL_DISP_PW_DC_OFF,
+ },
+ {
.name = "power well 2",
.domains = SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS,
.ops = &skl_power_well_ops,
@@ -1792,6 +1779,34 @@ static struct i915_power_well skl_power_wells[] = {
},
};
+void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv)
+{
+ struct i915_power_well *well;
+
+ if (!IS_SKYLAKE(dev_priv))
+ return;
+
+ well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
+ intel_power_well_enable(dev_priv, well);
+
+ well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO);
+ intel_power_well_enable(dev_priv, well);
+}
+
+void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv)
+{
+ struct i915_power_well *well;
+
+ if (!IS_SKYLAKE(dev_priv))
+ return;
+
+ well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
+ intel_power_well_disable(dev_priv, well);
+
+ well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO);
+ intel_power_well_disable(dev_priv, well);
+}
+
static struct i915_power_well bxt_power_wells[] = {
{
.name = "always-on",
@@ -1806,11 +1821,17 @@ static struct i915_power_well bxt_power_wells[] = {
.data = SKL_DISP_PW_1,
},
{
+ .name = "DC off",
+ .domains = BXT_DISPLAY_DC_OFF_POWER_DOMAINS,
+ .ops = &gen9_dc_off_power_well_ops,
+ .data = SKL_DISP_PW_DC_OFF,
+ },
+ {
.name = "power well 2",
.domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS,
.ops = &skl_power_well_ops,
.data = SKL_DISP_PW_2,
- }
+ },
};
static int
@@ -1859,7 +1880,7 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
set_power_wells(power_domains, hsw_power_wells);
} else if (IS_BROADWELL(dev_priv->dev)) {
set_power_wells(power_domains, bdw_power_wells);
- } else if (IS_SKYLAKE(dev_priv->dev)) {
+ } else if (IS_SKYLAKE(dev_priv->dev) || IS_KABYLAKE(dev_priv->dev)) {
set_power_wells(power_domains, skl_power_wells);
} else if (IS_BROXTON(dev_priv->dev)) {
set_power_wells(power_domains, bxt_power_wells);
@@ -1874,21 +1895,6 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
return 0;
}
-static void intel_runtime_pm_disable(struct drm_i915_private *dev_priv)
-{
- struct drm_device *dev = dev_priv->dev;
- struct device *device = &dev->pdev->dev;
-
- if (!HAS_RUNTIME_PM(dev))
- return;
-
- if (!intel_enable_rc6(dev))
- return;
-
- /* Make sure we're not suspended first. */
- pm_runtime_get_sync(device);
-}
-
/**
* intel_power_domains_fini - finalizes the power domain structures
* @dev_priv: i915 device instance
@@ -1899,15 +1905,17 @@ static void intel_runtime_pm_disable(struct drm_i915_private *dev_priv)
*/
void intel_power_domains_fini(struct drm_i915_private *dev_priv)
{
- intel_runtime_pm_disable(dev_priv);
-
/* The i915.ko module is still not prepared to be loaded when
* the power well is not enabled, so just enable it in case
* we're going to unload/reload. */
intel_display_set_init_power(dev_priv, true);
+
+ /* Remove the refcount we took to keep power well support disabled. */
+ if (!i915.disable_power_well)
+ intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
}
-static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
+static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
{
struct i915_power_domains *power_domains = &dev_priv->power_domains;
struct i915_power_well *power_well;
@@ -1922,6 +1930,47 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
mutex_unlock(&power_domains->lock);
}
+static void skl_display_core_init(struct drm_i915_private *dev_priv,
+ bool resume)
+{
+ struct i915_power_domains *power_domains = &dev_priv->power_domains;
+ uint32_t val;
+
+ gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+ /* enable PCH reset handshake */
+ val = I915_READ(HSW_NDE_RSTWRN_OPT);
+ I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE);
+
+ /* enable PG1 and Misc I/O */
+ mutex_lock(&power_domains->lock);
+ skl_pw1_misc_io_init(dev_priv);
+ mutex_unlock(&power_domains->lock);
+
+ if (!resume)
+ return;
+
+ skl_init_cdclk(dev_priv);
+
+ if (dev_priv->csr.dmc_payload)
+ intel_csr_load_program(dev_priv);
+}
+
+static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
+{
+ struct i915_power_domains *power_domains = &dev_priv->power_domains;
+
+ gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+ skl_uninit_cdclk(dev_priv);
+
+ /* The spec doesn't call for removing the reset handshake flag */
+ /* disable PG1 and Misc I/O */
+ mutex_lock(&power_domains->lock);
+ skl_pw1_misc_io_fini(dev_priv);
+ mutex_unlock(&power_domains->lock);
+}
+
static void chv_phy_control_init(struct drm_i915_private *dev_priv)
{
struct i915_power_well *cmn_bc =
@@ -2044,14 +2093,16 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
* This function initializes the hardware power domain state and enables all
* power domains using intel_display_set_init_power().
*/
-void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
+void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
{
struct drm_device *dev = dev_priv->dev;
struct i915_power_domains *power_domains = &dev_priv->power_domains;
power_domains->initializing = true;
- if (IS_CHERRYVIEW(dev)) {
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+ skl_display_core_init(dev_priv, resume);
+ } else if (IS_CHERRYVIEW(dev)) {
mutex_lock(&power_domains->lock);
chv_phy_control_init(dev_priv);
mutex_unlock(&power_domains->lock);
@@ -2063,11 +2114,34 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
/* For now, we need the power well to be always enabled. */
intel_display_set_init_power(dev_priv, true);
- intel_power_domains_resume(dev_priv);
+ /* Disable power support if the user asked so. */
+ if (!i915.disable_power_well)
+ intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+ intel_power_domains_sync_hw(dev_priv);
power_domains->initializing = false;
}
/**
+ * intel_power_domains_suspend - suspend power domain state
+ * @dev_priv: i915 device instance
+ *
+ * This function prepares the hardware power domain state before entering
+ * system suspend. It must be paired with intel_power_domains_init_hw().
+ */
+void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
+{
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
+ skl_display_core_uninit(dev_priv);
+
+ /*
+ * Even if power well support was disabled we still want to disable
+ * power wells while we are system suspended.
+ */
+ if (!i915.disable_power_well)
+ intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+}
+
+/**
* intel_runtime_pm_get - grab a runtime pm reference
* @dev_priv: i915 device instance
*
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index c42b636c2087..06679f164b3e 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -74,7 +74,7 @@ struct intel_sdvo {
struct i2c_adapter ddc;
/* Register for the SDVO device: SDVOB or SDVOC */
- uint32_t sdvo_reg;
+ i915_reg_t sdvo_reg;
/* Active outputs controlled by this SDVO output */
uint16_t controlled_output;
@@ -120,8 +120,7 @@ struct intel_sdvo {
*/
bool is_tv;
- /* On different gens SDVOB is at different places. */
- bool is_sdvob;
+ enum port port;
/* This is for current tv format name */
int tv_format_index;
@@ -245,7 +244,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
u32 bval = val, cval = val;
int i;
- if (intel_sdvo->sdvo_reg == PCH_SDVOB) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
I915_WRITE(intel_sdvo->sdvo_reg, val);
POSTING_READ(intel_sdvo->sdvo_reg);
/*
@@ -259,7 +258,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
return;
}
- if (intel_sdvo->sdvo_reg == GEN3_SDVOB)
+ if (intel_sdvo->port == PORT_B)
cval = I915_READ(GEN3_SDVOC);
else
bval = I915_READ(GEN3_SDVOB);
@@ -422,7 +421,7 @@ static const struct _sdvo_cmd_name {
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),
};
-#define SDVO_NAME(svdo) ((svdo)->is_sdvob ? "SDVOB" : "SDVOC")
+#define SDVO_NAME(svdo) ((svdo)->port == PORT_B ? "SDVOB" : "SDVOC")
static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
const void *args, int args_len)
@@ -1282,14 +1281,10 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder)
sdvox |= SDVO_BORDER_ENABLE;
} else {
sdvox = I915_READ(intel_sdvo->sdvo_reg);
- switch (intel_sdvo->sdvo_reg) {
- case GEN3_SDVOB:
+ if (intel_sdvo->port == PORT_B)
sdvox &= SDVOB_PRESERVE_MASK;
- break;
- case GEN3_SDVOC:
+ else
sdvox &= SDVOC_PRESERVE_MASK;
- break;
- }
sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
}
@@ -1464,12 +1459,23 @@ static void intel_disable_sdvo(struct intel_encoder *encoder)
* matching DP port to be enabled on transcoder A.
*/
if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) {
+ /*
+ * We get CPU/PCH FIFO underruns on the other pipe when
+ * doing the workaround. Sweep them under the rug.
+ */
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false);
+ intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
+
temp &= ~SDVO_PIPE_B_SELECT;
temp |= SDVO_ENABLE;
intel_sdvo_write_sdvox(intel_sdvo, temp);
temp &= ~SDVO_ENABLE;
intel_sdvo_write_sdvox(intel_sdvo, temp);
+
+ intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A);
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
+ intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
}
}
@@ -2251,7 +2257,7 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
{
struct sdvo_device_mapping *mapping;
- if (sdvo->is_sdvob)
+ if (sdvo->port == PORT_B)
mapping = &(dev_priv->sdvo_mappings[0]);
else
mapping = &(dev_priv->sdvo_mappings[1]);
@@ -2269,7 +2275,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
struct sdvo_device_mapping *mapping;
u8 pin;
- if (sdvo->is_sdvob)
+ if (sdvo->port == PORT_B)
mapping = &dev_priv->sdvo_mappings[0];
else
mapping = &dev_priv->sdvo_mappings[1];
@@ -2307,7 +2313,7 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo)
struct drm_i915_private *dev_priv = dev->dev_private;
struct sdvo_device_mapping *my_mapping, *other_mapping;
- if (sdvo->is_sdvob) {
+ if (sdvo->port == PORT_B) {
my_mapping = &dev_priv->sdvo_mappings[0];
other_mapping = &dev_priv->sdvo_mappings[1];
} else {
@@ -2332,7 +2338,7 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo)
/* No SDVO device info is found for another DVO port,
* so use mapping assumption we had before BIOS parsing.
*/
- if (sdvo->is_sdvob)
+ if (sdvo->port == PORT_B)
return 0x70;
else
return 0x72;
@@ -2939,18 +2945,31 @@ intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo,
return i2c_add_adapter(&sdvo->ddc) == 0;
}
-bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
+static void assert_sdvo_port_valid(const struct drm_i915_private *dev_priv,
+ enum port port)
+{
+ if (HAS_PCH_SPLIT(dev_priv))
+ WARN_ON(port != PORT_B);
+ else
+ WARN_ON(port != PORT_B && port != PORT_C);
+}
+
+bool intel_sdvo_init(struct drm_device *dev,
+ i915_reg_t sdvo_reg, enum port port)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder;
struct intel_sdvo *intel_sdvo;
int i;
+
+ assert_sdvo_port_valid(dev_priv, port);
+
intel_sdvo = kzalloc(sizeof(*intel_sdvo), GFP_KERNEL);
if (!intel_sdvo)
return false;
intel_sdvo->sdvo_reg = sdvo_reg;
- intel_sdvo->is_sdvob = is_sdvob;
+ intel_sdvo->port = port;
intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1;
intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo);
if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev))
@@ -3000,8 +3019,10 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
* hotplug lines.
*/
if (intel_sdvo->hotplug_active) {
- intel_encoder->hpd_pin =
- intel_sdvo->is_sdvob ? HPD_SDVO_B : HPD_SDVO_C;
+ if (intel_sdvo->port == PORT_B)
+ intel_encoder->hpd_pin = HPD_SDVO_B;
+ else
+ intel_encoder->hpd_pin = HPD_SDVO_C;
}
/*
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 56dc132e8e20..2b96f336589e 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -192,10 +192,9 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
const int pipe = intel_plane->pipe;
const int plane = intel_plane->plane + 1;
u32 plane_ctl, stride_div, stride;
- int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
const struct drm_intel_sprite_colorkey *key =
&to_intel_plane_state(drm_plane->state)->ckey;
- unsigned long surf_addr;
+ u32 surf_addr;
u32 tile_height, plane_offset, plane_size;
unsigned int rotation;
int x_offset, y_offset;
@@ -212,10 +211,6 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
rotation = drm_plane->state->rotation;
plane_ctl |= skl_plane_ctl_rotation(rotation);
- intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h,
- pixel_size, true,
- src_w != crtc_w || src_h != crtc_h);
-
stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
fb->pixel_format);
@@ -297,8 +292,6 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
I915_WRITE(PLANE_SURF(pipe, plane), 0);
POSTING_READ(PLANE_SURF(pipe, plane));
-
- intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
}
static void
@@ -541,10 +534,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
sprctl |= SPRITE_PIPE_CSC_ENABLE;
- intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
- true,
- src_w != crtc_w || src_h != crtc_h);
-
/* Sizes are 0 based */
src_w--;
src_h--;
@@ -678,10 +667,6 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
if (IS_GEN6(dev))
dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
- intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
- pixel_size, true,
- src_w != crtc_w || src_h != crtc_h);
-
/* Sizes are 0 based */
src_w--;
src_h--;
@@ -832,8 +817,8 @@ intel_check_sprite_plane(struct drm_plane *plane,
hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
if (hscale < 0) {
DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
- drm_rect_debug_print(src, true);
- drm_rect_debug_print(dst, false);
+ drm_rect_debug_print("src: ", src, true);
+ drm_rect_debug_print("dst: ", dst, false);
return hscale;
}
@@ -841,8 +826,8 @@ intel_check_sprite_plane(struct drm_plane *plane,
vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
if (vscale < 0) {
DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
- drm_rect_debug_print(src, true);
- drm_rect_debug_print(dst, false);
+ drm_rect_debug_print("src: ", src, true);
+ drm_rect_debug_print("dst: ", dst, false);
return vscale;
}
@@ -938,9 +923,6 @@ intel_commit_sprite_plane(struct drm_plane *plane,
crtc = crtc ? crtc : plane->crtc;
- if (!crtc->state->active)
- return;
-
if (state->visible) {
intel_plane->update_plane(plane, crtc, fb,
state->dst.x1, state->dst.y1,
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 43cba129a0c0..c2358ba78b30 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -29,19 +29,7 @@
#define FORCEWAKE_ACK_TIMEOUT_MS 50
-#define __raw_i915_read8(dev_priv__, reg__) readb((dev_priv__)->regs + (reg__))
-#define __raw_i915_write8(dev_priv__, reg__, val__) writeb(val__, (dev_priv__)->regs + (reg__))
-
-#define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__))
-#define __raw_i915_write16(dev_priv__, reg__, val__) writew(val__, (dev_priv__)->regs + (reg__))
-
-#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__))
-#define __raw_i915_write32(dev_priv__, reg__, val__) writel(val__, (dev_priv__)->regs + (reg__))
-
-#define __raw_i915_read64(dev_priv__, reg__) readq((dev_priv__)->regs + (reg__))
-#define __raw_i915_write64(dev_priv__, reg__, val__) writeq(val__, (dev_priv__)->regs + (reg__))
-
-#define __raw_posting_read(dev_priv__, reg__) (void)__raw_i915_read32(dev_priv__, reg__)
+#define __raw_posting_read(dev_priv__, reg__) (void)__raw_i915_read32((dev_priv__), (reg__))
static const char * const forcewake_domain_names[] = {
"render",
@@ -72,7 +60,7 @@ assert_device_not_suspended(struct drm_i915_private *dev_priv)
static inline void
fw_domain_reset(const struct intel_uncore_forcewake_domain *d)
{
- WARN_ON(d->reg_set == 0);
+ WARN_ON(!i915_mmio_reg_valid(d->reg_set));
__raw_i915_write32(d->i915, d->reg_set, d->val_reset);
}
@@ -118,7 +106,7 @@ static inline void
fw_domain_posting_read(const struct intel_uncore_forcewake_domain *d)
{
/* something from same cacheline, but not from the set register */
- if (d->reg_post)
+ if (i915_mmio_reg_valid(d->reg_post))
__raw_posting_read(d->i915, d->reg_post);
}
@@ -525,8 +513,7 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv)
}
/* We give fast paths for the really cool registers */
-#define NEEDS_FORCE_WAKE(reg) \
- ((reg) < 0x40000 && (reg) != FORCEWAKE)
+#define NEEDS_FORCE_WAKE(reg) ((reg) < 0x40000)
#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
@@ -589,7 +576,7 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv)
REG_RANGE((reg), 0x9400, 0x9800)
#define FORCEWAKE_GEN9_BLITTER_RANGE_OFFSET(reg) \
- ((reg) < 0x40000 &&\
+ ((reg) < 0x40000 && \
!FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) && \
!FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) && \
!FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) && \
@@ -605,8 +592,8 @@ ilk_dummy_write(struct drm_i915_private *dev_priv)
}
static void
-hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, u32 reg, bool read,
- bool before)
+hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv,
+ i915_reg_t reg, bool read, bool before)
{
const char *op = read ? "reading" : "writing to";
const char *when = before ? "before" : "after";
@@ -616,7 +603,7 @@ hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, u32 reg, bool read,
if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) {
WARN(1, "Unclaimed register detected %s %s register 0x%x\n",
- when, op, reg);
+ when, op, i915_mmio_reg_offset(reg));
__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
i915.mmio_debug--; /* Only report the first N failures */
}
@@ -649,7 +636,7 @@ hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv)
#define __gen2_read(x) \
static u##x \
-gen2_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+gen2_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
GEN2_READ_HEADER(x); \
val = __raw_i915_read##x(dev_priv, reg); \
GEN2_READ_FOOTER; \
@@ -657,7 +644,7 @@ gen2_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
#define __gen5_read(x) \
static u##x \
-gen5_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+gen5_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
GEN2_READ_HEADER(x); \
ilk_dummy_write(dev_priv); \
val = __raw_i915_read##x(dev_priv, reg); \
@@ -680,6 +667,7 @@ __gen2_read(64)
#undef GEN2_READ_HEADER
#define GEN6_READ_HEADER(x) \
+ u32 offset = i915_mmio_reg_offset(reg); \
unsigned long irqflags; \
u##x val = 0; \
assert_device_not_suspended(dev_priv); \
@@ -714,20 +702,12 @@ static inline void __force_wake_get(struct drm_i915_private *dev_priv,
dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
}
-#define __vgpu_read(x) \
-static u##x \
-vgpu_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
- GEN6_READ_HEADER(x); \
- val = __raw_i915_read##x(dev_priv, reg); \
- GEN6_READ_FOOTER; \
-}
-
#define __gen6_read(x) \
static u##x \
-gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+gen6_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
GEN6_READ_HEADER(x); \
hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \
- if (NEEDS_FORCE_WAKE(reg)) \
+ if (NEEDS_FORCE_WAKE(offset)) \
__force_wake_get(dev_priv, FORCEWAKE_RENDER); \
val = __raw_i915_read##x(dev_priv, reg); \
hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \
@@ -736,47 +716,56 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
#define __vlv_read(x) \
static u##x \
-vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
+ enum forcewake_domains fw_engine = 0; \
GEN6_READ_HEADER(x); \
- if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) \
- __force_wake_get(dev_priv, FORCEWAKE_RENDER); \
- else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) \
- __force_wake_get(dev_priv, FORCEWAKE_MEDIA); \
+ if (!NEEDS_FORCE_WAKE(offset)) \
+ fw_engine = 0; \
+ else if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(offset)) \
+ fw_engine = FORCEWAKE_RENDER; \
+ else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \
+ fw_engine = FORCEWAKE_MEDIA; \
+ if (fw_engine) \
+ __force_wake_get(dev_priv, fw_engine); \
val = __raw_i915_read##x(dev_priv, reg); \
GEN6_READ_FOOTER; \
}
#define __chv_read(x) \
static u##x \
-chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
+ enum forcewake_domains fw_engine = 0; \
GEN6_READ_HEADER(x); \
- if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \
- __force_wake_get(dev_priv, FORCEWAKE_RENDER); \
- else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \
- __force_wake_get(dev_priv, FORCEWAKE_MEDIA); \
- else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \
- __force_wake_get(dev_priv, \
- FORCEWAKE_RENDER | FORCEWAKE_MEDIA); \
+ if (!NEEDS_FORCE_WAKE(offset)) \
+ fw_engine = 0; \
+ else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
+ fw_engine = FORCEWAKE_RENDER; \
+ else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
+ fw_engine = FORCEWAKE_MEDIA; \
+ else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
+ fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+ if (fw_engine) \
+ __force_wake_get(dev_priv, fw_engine); \
val = __raw_i915_read##x(dev_priv, reg); \
GEN6_READ_FOOTER; \
}
#define SKL_NEEDS_FORCE_WAKE(reg) \
- ((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg))
+ ((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg))
#define __gen9_read(x) \
static u##x \
-gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
enum forcewake_domains fw_engine; \
GEN6_READ_HEADER(x); \
hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \
- if (!SKL_NEEDS_FORCE_WAKE(reg)) \
+ if (!SKL_NEEDS_FORCE_WAKE(offset)) \
fw_engine = 0; \
- else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \
+ else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
fw_engine = FORCEWAKE_RENDER; \
- else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) \
+ else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
fw_engine = FORCEWAKE_MEDIA; \
- else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) \
+ else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
else \
fw_engine = FORCEWAKE_BLITTER; \
@@ -787,10 +776,6 @@ gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
GEN6_READ_FOOTER; \
}
-__vgpu_read(8)
-__vgpu_read(16)
-__vgpu_read(32)
-__vgpu_read(64)
__gen9_read(8)
__gen9_read(16)
__gen9_read(32)
@@ -812,10 +797,37 @@ __gen6_read(64)
#undef __chv_read
#undef __vlv_read
#undef __gen6_read
-#undef __vgpu_read
#undef GEN6_READ_FOOTER
#undef GEN6_READ_HEADER
+#define VGPU_READ_HEADER(x) \
+ unsigned long irqflags; \
+ u##x val = 0; \
+ assert_device_not_suspended(dev_priv); \
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
+
+#define VGPU_READ_FOOTER \
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+ trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \
+ return val
+
+#define __vgpu_read(x) \
+static u##x \
+vgpu_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
+ VGPU_READ_HEADER(x); \
+ val = __raw_i915_read##x(dev_priv, reg); \
+ VGPU_READ_FOOTER; \
+}
+
+__vgpu_read(8)
+__vgpu_read(16)
+__vgpu_read(32)
+__vgpu_read(64)
+
+#undef __vgpu_read
+#undef VGPU_READ_FOOTER
+#undef VGPU_READ_HEADER
+
#define GEN2_WRITE_HEADER \
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
assert_device_not_suspended(dev_priv); \
@@ -824,7 +836,7 @@ __gen6_read(64)
#define __gen2_write(x) \
static void \
-gen2_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
+gen2_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
GEN2_WRITE_HEADER; \
__raw_i915_write##x(dev_priv, reg, val); \
GEN2_WRITE_FOOTER; \
@@ -832,7 +844,7 @@ gen2_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
#define __gen5_write(x) \
static void \
-gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
+gen5_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
GEN2_WRITE_HEADER; \
ilk_dummy_write(dev_priv); \
__raw_i915_write##x(dev_priv, reg, val); \
@@ -855,6 +867,7 @@ __gen2_write(64)
#undef GEN2_WRITE_HEADER
#define GEN6_WRITE_HEADER \
+ u32 offset = i915_mmio_reg_offset(reg); \
unsigned long irqflags; \
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
assert_device_not_suspended(dev_priv); \
@@ -865,10 +878,10 @@ __gen2_write(64)
#define __gen6_write(x) \
static void \
-gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
+gen6_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
u32 __fifo_ret = 0; \
GEN6_WRITE_HEADER; \
- if (NEEDS_FORCE_WAKE(reg)) { \
+ if (NEEDS_FORCE_WAKE(offset)) { \
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
} \
__raw_i915_write##x(dev_priv, reg, val); \
@@ -880,10 +893,10 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
#define __hsw_write(x) \
static void \
-hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
+hsw_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
u32 __fifo_ret = 0; \
GEN6_WRITE_HEADER; \
- if (NEEDS_FORCE_WAKE(reg)) { \
+ if (NEEDS_FORCE_WAKE(offset)) { \
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
} \
hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
@@ -896,15 +909,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
GEN6_WRITE_FOOTER; \
}
-#define __vgpu_write(x) \
-static void vgpu_write##x(struct drm_i915_private *dev_priv, \
- off_t reg, u##x val, bool trace) { \
- GEN6_WRITE_HEADER; \
- __raw_i915_write##x(dev_priv, reg, val); \
- GEN6_WRITE_FOOTER; \
-}
-
-static const u32 gen8_shadowed_regs[] = {
+static const i915_reg_t gen8_shadowed_regs[] = {
FORCEWAKE_MT,
GEN6_RPNSWREQ,
GEN6_RC_VIDEO_FREQ,
@@ -915,11 +920,12 @@ static const u32 gen8_shadowed_regs[] = {
/* TODO: Other registers are not yet used */
};
-static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg)
+static bool is_gen8_shadowed(struct drm_i915_private *dev_priv,
+ i915_reg_t reg)
{
int i;
for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++)
- if (reg == gen8_shadowed_regs[i])
+ if (i915_mmio_reg_equal(reg, gen8_shadowed_regs[i]))
return true;
return false;
@@ -927,10 +933,10 @@ static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg)
#define __gen8_write(x) \
static void \
-gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
+gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
GEN6_WRITE_HEADER; \
hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
- if (reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg)) \
+ if (NEEDS_FORCE_WAKE(offset) && !is_gen8_shadowed(dev_priv, reg)) \
__force_wake_get(dev_priv, FORCEWAKE_RENDER); \
__raw_i915_write##x(dev_priv, reg, val); \
hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \
@@ -940,22 +946,25 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
#define __chv_write(x) \
static void \
-chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
- bool shadowed = is_gen8_shadowed(dev_priv, reg); \
+chv_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
+ enum forcewake_domains fw_engine = 0; \
GEN6_WRITE_HEADER; \
- if (!shadowed) { \
- if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \
- __force_wake_get(dev_priv, FORCEWAKE_RENDER); \
- else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \
- __force_wake_get(dev_priv, FORCEWAKE_MEDIA); \
- else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \
- __force_wake_get(dev_priv, FORCEWAKE_RENDER | FORCEWAKE_MEDIA); \
- } \
+ if (!NEEDS_FORCE_WAKE(offset) || \
+ is_gen8_shadowed(dev_priv, reg)) \
+ fw_engine = 0; \
+ else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
+ fw_engine = FORCEWAKE_RENDER; \
+ else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
+ fw_engine = FORCEWAKE_MEDIA; \
+ else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
+ fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+ if (fw_engine) \
+ __force_wake_get(dev_priv, fw_engine); \
__raw_i915_write##x(dev_priv, reg, val); \
GEN6_WRITE_FOOTER; \
}
-static const u32 gen9_shadowed_regs[] = {
+static const i915_reg_t gen9_shadowed_regs[] = {
RING_TAIL(RENDER_RING_BASE),
RING_TAIL(GEN6_BSD_RING_BASE),
RING_TAIL(VEBOX_RING_BASE),
@@ -968,11 +977,12 @@ static const u32 gen9_shadowed_regs[] = {
/* TODO: Other registers are not yet used */
};
-static bool is_gen9_shadowed(struct drm_i915_private *dev_priv, u32 reg)
+static bool is_gen9_shadowed(struct drm_i915_private *dev_priv,
+ i915_reg_t reg)
{
int i;
for (i = 0; i < ARRAY_SIZE(gen9_shadowed_regs); i++)
- if (reg == gen9_shadowed_regs[i])
+ if (i915_mmio_reg_equal(reg, gen9_shadowed_regs[i]))
return true;
return false;
@@ -980,19 +990,19 @@ static bool is_gen9_shadowed(struct drm_i915_private *dev_priv, u32 reg)
#define __gen9_write(x) \
static void \
-gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \
+gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \
bool trace) { \
enum forcewake_domains fw_engine; \
GEN6_WRITE_HEADER; \
hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
- if (!SKL_NEEDS_FORCE_WAKE(reg) || \
+ if (!SKL_NEEDS_FORCE_WAKE(offset) || \
is_gen9_shadowed(dev_priv, reg)) \
fw_engine = 0; \
- else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \
+ else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
fw_engine = FORCEWAKE_RENDER; \
- else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) \
+ else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
fw_engine = FORCEWAKE_MEDIA; \
- else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) \
+ else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
else \
fw_engine = FORCEWAKE_BLITTER; \
@@ -1024,20 +1034,41 @@ __gen6_write(8)
__gen6_write(16)
__gen6_write(32)
__gen6_write(64)
-__vgpu_write(8)
-__vgpu_write(16)
-__vgpu_write(32)
-__vgpu_write(64)
#undef __gen9_write
#undef __chv_write
#undef __gen8_write
#undef __hsw_write
#undef __gen6_write
-#undef __vgpu_write
#undef GEN6_WRITE_FOOTER
#undef GEN6_WRITE_HEADER
+#define VGPU_WRITE_HEADER \
+ unsigned long irqflags; \
+ trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
+ assert_device_not_suspended(dev_priv); \
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
+
+#define VGPU_WRITE_FOOTER \
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags)
+
+#define __vgpu_write(x) \
+static void vgpu_write##x(struct drm_i915_private *dev_priv, \
+ i915_reg_t reg, u##x val, bool trace) { \
+ VGPU_WRITE_HEADER; \
+ __raw_i915_write##x(dev_priv, reg, val); \
+ VGPU_WRITE_FOOTER; \
+}
+
+__vgpu_write(8)
+__vgpu_write(16)
+__vgpu_write(32)
+__vgpu_write(64)
+
+#undef __vgpu_write
+#undef VGPU_WRITE_FOOTER
+#undef VGPU_WRITE_HEADER
+
#define ASSIGN_WRITE_MMIO_VFUNCS(x) \
do { \
dev_priv->uncore.funcs.mmio_writeb = x##_write8; \
@@ -1057,7 +1088,8 @@ do { \
static void fw_domain_init(struct drm_i915_private *dev_priv,
enum forcewake_domain_id domain_id,
- u32 reg_set, u32 reg_ack)
+ i915_reg_t reg_set,
+ i915_reg_t reg_ack)
{
struct intel_uncore_forcewake_domain *d;
@@ -1087,8 +1119,6 @@ static void fw_domain_init(struct drm_i915_private *dev_priv,
d->reg_post = FORCEWAKE_ACK_VLV;
else if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv) || IS_GEN8(dev_priv))
d->reg_post = ECOBUS;
- else
- d->reg_post = 0;
d->i915 = dev_priv;
d->id = domain_id;
@@ -1262,12 +1292,14 @@ void intel_uncore_fini(struct drm_device *dev)
#define GEN_RANGE(l, h) GENMASK(h, l)
static const struct register_whitelist {
- uint64_t offset;
+ i915_reg_t offset_ldw, offset_udw;
uint32_t size;
/* supported gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
uint32_t gen_bitmask;
} whitelist[] = {
- { RING_TIMESTAMP(RENDER_RING_BASE), 8, GEN_RANGE(4, 9) },
+ { .offset_ldw = RING_TIMESTAMP(RENDER_RING_BASE),
+ .offset_udw = RING_TIMESTAMP_UDW(RENDER_RING_BASE),
+ .size = 8, .gen_bitmask = GEN_RANGE(4, 9) },
};
int i915_reg_read_ioctl(struct drm_device *dev,
@@ -1277,11 +1309,11 @@ int i915_reg_read_ioctl(struct drm_device *dev,
struct drm_i915_reg_read *reg = data;
struct register_whitelist const *entry = whitelist;
unsigned size;
- u64 offset;
+ i915_reg_t offset_ldw, offset_udw;
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
- if (entry->offset == (reg->offset & -entry->size) &&
+ if (i915_mmio_reg_offset(entry->offset_ldw) == (reg->offset & -entry->size) &&
(1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
break;
}
@@ -1293,27 +1325,28 @@ int i915_reg_read_ioctl(struct drm_device *dev,
* be naturally aligned (and those that are not so aligned merely
* limit the available flags for that register).
*/
- offset = entry->offset;
+ offset_ldw = entry->offset_ldw;
+ offset_udw = entry->offset_udw;
size = entry->size;
- size |= reg->offset ^ offset;
+ size |= reg->offset ^ i915_mmio_reg_offset(offset_ldw);
intel_runtime_pm_get(dev_priv);
switch (size) {
case 8 | 1:
- reg->val = I915_READ64_2x32(offset, offset+4);
+ reg->val = I915_READ64_2x32(offset_ldw, offset_udw);
break;
case 8:
- reg->val = I915_READ64(offset);
+ reg->val = I915_READ64(offset_ldw);
break;
case 4:
- reg->val = I915_READ(offset);
+ reg->val = I915_READ(offset_ldw);
break;
case 2:
- reg->val = I915_READ16(offset);
+ reg->val = I915_READ16(offset_ldw);
break;
case 1:
- reg->val = I915_READ8(offset);
+ reg->val = I915_READ8(offset_ldw);
break;
default:
ret = -EINVAL;
@@ -1470,7 +1503,7 @@ static int gen6_do_reset(struct drm_device *dev)
}
static int wait_for_register(struct drm_i915_private *dev_priv,
- const u32 reg,
+ i915_reg_t reg,
const u32 mask,
const u32 value,
const unsigned long timeout_ms)
diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig
index 2b81a417cf29..35ca4f007839 100644
--- a/drivers/gpu/drm/imx/Kconfig
+++ b/drivers/gpu/drm/imx/Kconfig
@@ -10,15 +10,6 @@ config DRM_IMX
help
enable i.MX graphics support
-config DRM_IMX_FB_HELPER
- tristate "provide legacy framebuffer /dev/fb0"
- select DRM_KMS_CMA_HELPER
- depends on DRM_IMX
- help
- The DRM framework can provide a legacy /dev/fb0 framebuffer
- for your device. This is necessary to get a framebuffer console
- and also for applications using the legacy framebuffer API
-
config DRM_IMX_PARALLEL_DISPLAY
tristate "Support for parallel displays"
select DRM_PANEL
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 7b990b4e96d2..882cf3d4b7a8 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -49,8 +49,10 @@ struct imx_drm_crtc {
struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs;
};
+#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
static int legacyfb_depth = 16;
module_param(legacyfb_depth, int, 0444);
+#endif
int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
{
@@ -60,25 +62,19 @@ EXPORT_SYMBOL_GPL(imx_drm_crtc_id);
static void imx_drm_driver_lastclose(struct drm_device *drm)
{
-#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
struct imx_drm_device *imxdrm = drm->dev_private;
drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
-#endif
}
static int imx_drm_driver_unload(struct drm_device *drm)
{
-#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
struct imx_drm_device *imxdrm = drm->dev_private;
-#endif
drm_kms_helper_poll_fini(drm);
-#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
if (imxdrm->fbhelper)
drm_fbdev_cma_fini(imxdrm->fbhelper);
-#endif
component_unbind_all(drm->dev, drm);
@@ -214,11 +210,9 @@ EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
static void imx_drm_output_poll_changed(struct drm_device *drm)
{
-#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
struct imx_drm_device *imxdrm = drm->dev_private;
drm_fbdev_cma_hotplug_event(imxdrm->fbhelper);
-#endif
}
static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
@@ -307,7 +301,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
* The fb helper takes copies of key hardware information, so the
* crtcs/connectors/encoders must not change after this point.
*/
-#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
+#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
if (legacyfb_depth != 16 && legacyfb_depth != 32) {
dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n");
legacyfb_depth = 16;
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 912151c36d59..205b2801d3b8 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -252,7 +252,7 @@ void mgag200_fbdev_fini(struct mga_device *mdev);
/* mgag200_main.c */
int mgag200_framebuffer_init(struct drm_device *dev,
struct mga_framebuffer *mfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c
index b35b5b2db4ec..d9b04b008feb 100644
--- a/drivers/gpu/drm/mgag200/mgag200_fb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_fb.c
@@ -138,7 +138,7 @@ static struct fb_ops mgag200fb_ops = {
};
static int mgag200fb_create_object(struct mga_fbdev *afbdev,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
struct drm_device *dev = afbdev->helper.dev;
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c
index b1a0f5656175..9147444d5bf2 100644
--- a/drivers/gpu/drm/mgag200/mgag200_main.c
+++ b/drivers/gpu/drm/mgag200/mgag200_main.c
@@ -29,7 +29,7 @@ static const struct drm_framebuffer_funcs mga_fb_funcs = {
int mgag200_framebuffer_init(struct drm_device *dev,
struct mga_framebuffer *gfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
@@ -47,7 +47,7 @@ int mgag200_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
mgag200_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct mga_framebuffer *mga_fb;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 3be7a56b14f1..9a713b7a009d 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -240,9 +240,9 @@ uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, int id, int plane);
struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane);
const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb);
struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
+ const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
- struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd);
+ struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index 121713281417..a474d6cf5d9f 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -138,7 +138,7 @@ const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb)
}
struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
- struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)
+ struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *bos[4] = {0};
struct drm_framebuffer *fb;
@@ -168,7 +168,7 @@ out_unref:
}
struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
+ const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
{
struct msm_drm_private *priv = dev->dev_private;
struct msm_kms *kms = priv->kms;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 64c8d932d5f1..18676b8c1721 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -246,7 +246,7 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
int
nouveau_framebuffer_init(struct drm_device *dev,
struct nouveau_framebuffer *nv_fb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct nouveau_bo *nvbo)
{
struct nouveau_display *disp = nouveau_display(dev);
@@ -272,7 +272,7 @@ nouveau_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
nouveau_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct nouveau_framebuffer *nouveau_fb;
struct drm_gem_object *gem;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 856abe0f070d..5a57d8b472c4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -23,7 +23,7 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
}
int nouveau_framebuffer_init(struct drm_device *, struct nouveau_framebuffer *,
- struct drm_mode_fb_cmd2 *, struct nouveau_bo *);
+ const struct drm_mode_fb_cmd2 *, struct nouveau_bo *);
struct nouveau_page_flip_state {
struct list_head head;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
index 1e2e9e27a03b..ca77ad001978 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
@@ -34,7 +34,6 @@
struct nouveau_fbdev {
struct drm_fb_helper helper;
struct nouveau_framebuffer nouveau_fb;
- struct list_head fbdev_list;
struct drm_device *dev;
unsigned int saved_flags;
struct nvif_object surf2d;
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 5c367aad8a6e..130fca70bfd7 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -172,9 +172,9 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings,
uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
uint32_t max_formats, enum omap_color_mode supported_modes);
struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
- struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd);
+ struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
+ const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p);
int omap_framebuffer_pin(struct drm_framebuffer *fb);
void omap_framebuffer_unpin(struct drm_framebuffer *fb);
@@ -248,7 +248,7 @@ struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder);
static inline int objects_lookup(struct drm_device *dev,
struct drm_file *filp, uint32_t pixel_format,
- struct drm_gem_object **bos, uint32_t *handles)
+ struct drm_gem_object **bos, const uint32_t *handles)
{
int i, n = drm_format_num_planes(pixel_format);
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 636a1f921569..ad202dfc1a49 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -364,7 +364,7 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
#endif
struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
- struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)
+ struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *bos[4];
struct drm_framebuffer *fb;
@@ -386,7 +386,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
}
struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
+ const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
{
struct omap_framebuffer *omap_fb = NULL;
struct drm_framebuffer *fb = NULL;
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 183aea1abebc..cddba079197f 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -521,7 +521,7 @@ static const struct drm_framebuffer_funcs qxl_fb_funcs = {
int
qxl_framebuffer_init(struct drm_device *dev,
struct qxl_framebuffer *qfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
@@ -1003,7 +1003,7 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
static struct drm_framebuffer *
qxl_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct qxl_framebuffer *qxl_fb;
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 01a86948eb8c..6e6b9b1519b8 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -390,7 +390,7 @@ void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state);
int
qxl_framebuffer_init(struct drm_device *dev,
struct qxl_framebuffer *rfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
void qxl_display_read_client_monitors_config(struct qxl_device *qdev);
void qxl_send_monitors_config(struct qxl_device *qdev);
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index c4a552637c93..7136e521e6db 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -40,7 +40,6 @@
struct qxl_fbdev {
struct drm_fb_helper helper;
struct qxl_framebuffer qfb;
- struct list_head fbdev_list;
struct qxl_device *qdev;
spinlock_t delayed_ops_lock;
@@ -283,7 +282,7 @@ int qxl_get_handle_for_primary_fb(struct qxl_device *qdev,
}
static int qxlfb_create_pinned_object(struct qxl_fbdev *qfbdev,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **gobj_p)
{
struct qxl_device *qdev = qfbdev->qdev;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 1eca0acac016..b3bb92368ae0 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1331,7 +1331,7 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = {
int
radeon_framebuffer_init(struct drm_device *dev,
struct radeon_framebuffer *rfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
@@ -1348,7 +1348,7 @@ radeon_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
radeon_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct radeon_framebuffer *radeon_fb;
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 26da2f4d7b4f..adc44bbc81a9 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -44,7 +44,6 @@
struct radeon_fbdev {
struct drm_fb_helper helper;
struct radeon_framebuffer rfb;
- struct list_head fbdev_list;
struct radeon_device *rdev;
};
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index bba112628b47..cddd41b32eda 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -934,7 +934,7 @@ extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green
u16 *blue, int regno);
int radeon_framebuffer_init(struct drm_device *dev,
struct radeon_framebuffer *rfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index ca12e8ca5552..43bce69d8560 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -136,7 +136,7 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev,
static struct drm_framebuffer *
rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct rcar_du_device *rcdu = dev->dev_private;
const struct rcar_du_format_info *format;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 002645bb5bbf..b8ac5911c102 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -72,7 +72,7 @@ static struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
};
static struct rockchip_drm_fb *
-rockchip_fb_alloc(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd,
+rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **obj, unsigned int num_planes)
{
struct rockchip_drm_fb *rockchip_fb;
@@ -102,7 +102,7 @@ rockchip_fb_alloc(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd,
static struct drm_framebuffer *
rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct rockchip_drm_fb *rockchip_fb;
struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];
@@ -173,7 +173,7 @@ static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
struct drm_framebuffer *
rockchip_drm_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
struct rockchip_drm_fb *rockchip_fb;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h
index 09574d48226f..2fe47f1ee98f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h
@@ -17,7 +17,7 @@
struct drm_framebuffer *
rockchip_drm_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
void rockchip_drm_framebuffer_fini(struct drm_framebuffer *fb);
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.c b/drivers/gpu/drm/shmobile/shmob_drm_kms.c
index aaf98ace4a90..388a0fc13564 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_kms.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.c
@@ -104,7 +104,7 @@ const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc)
static struct drm_framebuffer *
shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
const struct shmob_drm_format_info *format;
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index 74d9d621453d..63ebb154b9b5 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -16,18 +16,6 @@ config DRM_TEGRA
if DRM_TEGRA
-config DRM_TEGRA_FBDEV
- bool "Enable legacy fbdev support"
- select DRM_KMS_FB_HELPER
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- default y
- help
- Choose this option if you have a need for the legacy fbdev support.
- Note that this support also provides the Linux console on top of
- the Tegra modesetting driver.
-
config DRM_TEGRA_DEBUG
bool "NVIDIA Tegra DRM debug support"
help
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 159ef515cab1..e0f827790a5e 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -106,7 +106,7 @@ static int tegra_atomic_commit(struct drm_device *drm,
static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
.fb_create = tegra_fb_create,
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
.output_poll_changed = tegra_fb_output_poll_changed,
#endif
.atomic_check = drm_atomic_helper_check,
@@ -260,7 +260,7 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)
static void tegra_drm_lastclose(struct drm_device *drm)
{
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
tegra_fbdev_restore_mode(tegra->fbdev);
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index ec49275ffb24..d88a2d18c1a4 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -30,7 +30,7 @@ struct tegra_fb {
unsigned int num_planes;
};
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_fbdev {
struct drm_fb_helper base;
struct tegra_fb *fb;
@@ -46,7 +46,7 @@ struct tegra_drm {
struct mutex clients_lock;
struct list_head clients;
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_fbdev *fbdev;
#endif
@@ -268,12 +268,12 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
struct tegra_bo_tiling *tiling);
struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
struct drm_file *file,
- struct drm_mode_fb_cmd2 *cmd);
+ const struct drm_mode_fb_cmd2 *cmd);
int tegra_drm_fb_prepare(struct drm_device *drm);
void tegra_drm_fb_free(struct drm_device *drm);
int tegra_drm_fb_init(struct drm_device *drm);
void tegra_drm_fb_exit(struct drm_device *drm);
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
void tegra_fb_output_poll_changed(struct drm_device *drm);
#endif
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 1004075fd088..ede9e94f3312 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -18,7 +18,7 @@ static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb)
return container_of(fb, struct tegra_fb, base);
}
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
{
return container_of(helper, struct tegra_fbdev, base);
@@ -92,7 +92,7 @@ static struct drm_framebuffer_funcs tegra_fb_funcs = {
};
static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct tegra_bo **planes,
unsigned int num_planes)
{
@@ -131,7 +131,7 @@ static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm,
struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
struct drm_file *file,
- struct drm_mode_fb_cmd2 *cmd)
+ const struct drm_mode_fb_cmd2 *cmd)
{
unsigned int hsub, vsub, i;
struct tegra_bo *planes[4];
@@ -181,7 +181,7 @@ unreference:
return ERR_PTR(err);
}
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
static struct fb_ops tegra_fb_ops = {
.owner = THIS_MODULE,
.fb_fillrect = drm_fb_helper_sys_fillrect,
@@ -370,7 +370,7 @@ void tegra_fb_output_poll_changed(struct drm_device *drm)
int tegra_drm_fb_prepare(struct drm_device *drm)
{
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
tegra->fbdev = tegra_fbdev_create(drm);
@@ -383,7 +383,7 @@ int tegra_drm_fb_prepare(struct drm_device *drm)
void tegra_drm_fb_free(struct drm_device *drm)
{
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
tegra_fbdev_free(tegra->fbdev);
@@ -392,7 +392,7 @@ void tegra_drm_fb_free(struct drm_device *drm)
int tegra_drm_fb_init(struct drm_device *drm)
{
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
int err;
@@ -407,7 +407,7 @@ int tegra_drm_fb_init(struct drm_device *drm)
void tegra_drm_fb_exit(struct drm_device *drm)
{
-#ifdef CONFIG_DRM_TEGRA_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
tegra_fbdev_exit(tegra->fbdev);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 876cad58b1f9..4ddb21e7f52f 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -46,7 +46,7 @@ void tilcdc_module_cleanup(struct tilcdc_module *mod)
static struct of_device_id tilcdc_of_match[];
static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev,
- struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
+ struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd)
{
return drm_fb_cma_create(dev, file_priv, mode_cmd);
}
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index 80adbac82bde..4a064efcea58 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -108,7 +108,7 @@ void udl_fbdev_unplug(struct drm_device *dev);
struct drm_framebuffer *
udl_fb_user_fb_create(struct drm_device *dev,
struct drm_file *file,
- struct drm_mode_fb_cmd2 *mode_cmd);
+ const struct drm_mode_fb_cmd2 *mode_cmd);
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
const char *front, char **urb_buf_ptr,
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index 62c7b1dafaa4..200419d4d43c 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -33,7 +33,6 @@ module_param(fb_defio, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
struct udl_fbdev {
struct drm_fb_helper helper;
struct udl_framebuffer ufb;
- struct list_head fbdev_list;
int fb_count;
};
@@ -456,7 +455,7 @@ static const struct drm_framebuffer_funcs udlfb_funcs = {
static int
udl_framebuffer_init(struct drm_device *dev,
struct udl_framebuffer *ufb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct udl_gem_object *obj)
{
int ret;
@@ -624,7 +623,7 @@ void udl_fbdev_unplug(struct drm_device *dev)
struct drm_framebuffer *
udl_fb_user_fb_create(struct drm_device *dev,
struct drm_file *file,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct udl_framebuffer *ufb;
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index 578fe0a9324c..8e6044d7660a 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -215,7 +215,7 @@ static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = {
int
virtio_gpu_framebuffer_init(struct drm_device *dev,
struct virtio_gpu_framebuffer *vgfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
@@ -465,7 +465,7 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index)
static struct drm_framebuffer *
virtio_gpu_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
+ const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj = NULL;
struct virtio_gpu_framebuffer *virtio_gpu_fb;
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 79f0abe69b64..8f486f4c7023 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -328,7 +328,7 @@ void virtio_gpu_dequeue_fence_func(struct work_struct *work);
/* virtio_gpu_display.c */
int virtio_gpu_framebuffer_init(struct drm_device *dev,
struct virtio_gpu_framebuffer *vgfb,
- struct drm_mode_fb_cmd2 *mode_cmd,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev);
void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev);
diff --git a/drivers/gpu/drm/virtio/virtgpu_fb.c b/drivers/gpu/drm/virtio/virtgpu_fb.c
index 6a81e084593b..2242a80866a9 100644
--- a/drivers/gpu/drm/virtio/virtgpu_fb.c
+++ b/drivers/gpu/drm/virtio/virtgpu_fb.c
@@ -32,7 +32,6 @@
struct virtio_gpu_fbdev {
struct drm_fb_helper helper;
struct virtio_gpu_framebuffer vgfb;
- struct list_head fbdev_list;
struct virtio_gpu_device *vgdev;
struct delayed_work work;
};
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 9b4bb9e74d73..27652b08c2e4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -968,7 +968,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd2)
+ const struct drm_mode_fb_cmd2 *mode_cmd2)
{
struct vmw_private *dev_priv = vmw_priv(dev);
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7e327309cf69..c2dd52ea4198 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3405,7 +3405,9 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
return 0;
}
-#include "../gpu/drm/i915/i915_reg.h"
+#define SOUTH_CHICKEN2 0xc2004
+#define PCH_PP_STATUS 0xc7200
+#define PCH_PP_CONTROL 0xc7204
#define MSG_CTL 0x45010
#define NSDE_PWR_STATE 0xd0100
#define IGD_OPERATION_TIMEOUT 10000 /* set timeout 10 seconds */
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 0a271ca1f7c7..a8e01aaca087 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -349,6 +349,8 @@ struct drm_file {
struct list_head event_list;
int event_space;
+ struct mutex event_read_lock;
+
struct drm_prime_file_private prime;
};
@@ -1121,4 +1123,7 @@ static __inline__ bool drm_can_sleep(void)
return true;
}
+/* helper for handling conditionals in various for_each macros */
+#define for_each_if(condition) if (!(condition)) {} else
+
#endif
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 4b74c97d297a..d8576ac55693 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -149,7 +149,7 @@ int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
((connector) = (state)->connectors[__i], \
(connector_state) = (state)->connector_states[__i], 1); \
(__i)++) \
- if (connector)
+ for_each_if (connector)
#define for_each_crtc_in_state(state, crtc, crtc_state, __i) \
for ((__i) = 0; \
@@ -157,7 +157,7 @@ int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
((crtc) = (state)->crtcs[__i], \
(crtc_state) = (state)->crtc_states[__i], 1); \
(__i)++) \
- if (crtc_state)
+ for_each_if (crtc_state)
#define for_each_plane_in_state(state, plane, plane_state, __i) \
for ((__i) = 0; \
@@ -165,7 +165,7 @@ int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
((plane) = (state)->planes[__i], \
(plane_state) = (state)->plane_states[__i], 1); \
(__i)++) \
- if (plane_state)
+ for_each_if (plane_state)
static inline bool
drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state)
{
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 8cba54a2a0a0..a286cce98720 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -62,6 +62,8 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
struct drm_atomic_state *old_state);
void drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state);
+void drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc *crtc,
+ bool atomic);
void drm_atomic_helper_swap_state(struct drm_device *dev,
struct drm_atomic_state *state);
@@ -81,6 +83,12 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set);
int __drm_atomic_helper_set_config(struct drm_mode_set *set,
struct drm_atomic_state *state);
+int drm_atomic_helper_disable_all(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx);
+struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev);
+int drm_atomic_helper_resume(struct drm_device *dev,
+ struct drm_atomic_state *state);
+
int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
struct drm_property *property,
uint64_t val);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3f0c6909dda1..4765df331002 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -85,7 +85,11 @@ static inline uint64_t I642U64(int64_t val)
return (uint64_t)*((uint64_t *)&val);
}
-/* rotation property bits */
+/*
+ * Rotation property bits. DRM_ROTATE_<degrees> rotates the image by the
+ * specified amount in degrees in counter clockwise direction. DRM_REFLECT_X and
+ * DRM_REFLECT_Y reflects the image along the specified axis prior to rotation
+ */
#define DRM_ROTATE_MASK 0x0f
#define DRM_ROTATE_0 0
#define DRM_ROTATE_90 1
@@ -992,7 +996,7 @@ struct drm_mode_set {
struct drm_mode_config_funcs {
struct drm_framebuffer *(*fb_create)(struct drm_device *dev,
struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd);
+ const struct drm_mode_fb_cmd2 *mode_cmd);
void (*output_poll_changed)(struct drm_device *dev);
int (*atomic_check)(struct drm_device *dev,
@@ -1166,7 +1170,7 @@ struct drm_mode_config {
*/
#define drm_for_each_plane_mask(plane, dev, plane_mask) \
list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
- if ((plane_mask) & (1 << drm_plane_index(plane)))
+ for_each_if ((plane_mask) & (1 << drm_plane_index(plane)))
#define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
@@ -1543,7 +1547,7 @@ static inline struct drm_property *drm_property_find(struct drm_device *dev,
/* Plane list iterator for legacy (overlay only) planes. */
#define drm_for_each_legacy_plane(plane, dev) \
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \
- if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+ for_each_if (plane->type == DRM_PLANE_TYPE_OVERLAY)
#define drm_for_each_plane(plane, dev) \
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 3febb4b9fce9..e22ab29d2d00 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -197,7 +197,7 @@ extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
extern void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
- struct drm_mode_fb_cmd2 *mode_cmd);
+ const struct drm_mode_fb_cmd2 *mode_cmd);
static inline void drm_crtc_helper_add(struct drm_crtc *crtc,
const struct drm_crtc_helper_funcs *funcs)
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index bb9d0deca07c..1252108da0ef 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -455,16 +455,52 @@
# define DP_EDP_14 0x03
#define DP_EDP_GENERAL_CAP_1 0x701
+# define DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP (1 << 0)
+# define DP_EDP_BACKLIGHT_PIN_ENABLE_CAP (1 << 1)
+# define DP_EDP_BACKLIGHT_AUX_ENABLE_CAP (1 << 2)
+# define DP_EDP_PANEL_SELF_TEST_PIN_ENABLE_CAP (1 << 3)
+# define DP_EDP_PANEL_SELF_TEST_AUX_ENABLE_CAP (1 << 4)
+# define DP_EDP_FRC_ENABLE_CAP (1 << 5)
+# define DP_EDP_COLOR_ENGINE_CAP (1 << 6)
+# define DP_EDP_SET_POWER_CAP (1 << 7)
#define DP_EDP_BACKLIGHT_ADJUSTMENT_CAP 0x702
+# define DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP (1 << 0)
+# define DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP (1 << 1)
+# define DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT (1 << 2)
+# define DP_EDP_BACKLIGHT_AUX_PWM_PRODUCT_CAP (1 << 3)
+# define DP_EDP_BACKLIGHT_FREQ_PWM_PIN_PASSTHRU_CAP (1 << 4)
+# define DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP (1 << 5)
+# define DP_EDP_DYNAMIC_BACKLIGHT_CAP (1 << 6)
+# define DP_EDP_VBLANK_BACKLIGHT_UPDATE_CAP (1 << 7)
#define DP_EDP_GENERAL_CAP_2 0x703
+# define DP_EDP_OVERDRIVE_ENGINE_ENABLED (1 << 0)
#define DP_EDP_GENERAL_CAP_3 0x704 /* eDP 1.4 */
+# define DP_EDP_X_REGION_CAP_MASK (0xf << 0)
+# define DP_EDP_X_REGION_CAP_SHIFT 0
+# define DP_EDP_Y_REGION_CAP_MASK (0xf << 4)
+# define DP_EDP_Y_REGION_CAP_SHIFT 4
#define DP_EDP_DISPLAY_CONTROL_REGISTER 0x720
+# define DP_EDP_BACKLIGHT_ENABLE (1 << 0)
+# define DP_EDP_BLACK_VIDEO_ENABLE (1 << 1)
+# define DP_EDP_FRC_ENABLE (1 << 2)
+# define DP_EDP_COLOR_ENGINE_ENABLE (1 << 3)
+# define DP_EDP_VBLANK_BACKLIGHT_UPDATE_ENABLE (1 << 7)
#define DP_EDP_BACKLIGHT_MODE_SET_REGISTER 0x721
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_MASK (3 << 0)
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_PWM (0 << 0)
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_PRESET (1 << 0)
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD (2 << 0)
+# define DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT (3 << 0)
+# define DP_EDP_BACKLIGHT_FREQ_PWM_PIN_PASSTHRU_ENABLE (1 << 2)
+# define DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE (1 << 3)
+# define DP_EDP_DYNAMIC_BACKLIGHT_ENABLE (1 << 4)
+# define DP_EDP_REGIONAL_BACKLIGHT_ENABLE (1 << 5)
+# define DP_EDP_UPDATE_REGION_BRIGHTNESS (1 << 6) /* eDP 1.4 */
#define DP_EDP_BACKLIGHT_BRIGHTNESS_MSB 0x722
#define DP_EDP_BACKLIGHT_BRIGHTNESS_LSB 0x723
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index c54cf3d4a03f..be62bd321e75 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -18,7 +18,7 @@ void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma);
void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma);
struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
- struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd);
+ struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
unsigned int plane);
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 15e7f007380f..0b3e11ab8757 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -35,76 +35,129 @@
*/
/**
- * This structure defines the drm_mm memory object, which will be used by the
- * DRM for its buffer objects.
+ * struct drm_gem_object - GEM buffer object
+ *
+ * This structure defines the generic parts for GEM buffer objects, which are
+ * mostly around handling mmap and userspace handles.
+ *
+ * Buffer objects are often abbreviated to BO.
*/
struct drm_gem_object {
- /** Reference count of this object */
+ /**
+ * @refcount:
+ *
+ * Reference count of this object
+ *
+ * Please use drm_gem_object_reference() to acquire and
+ * drm_gem_object_unreference() or drm_gem_object_unreference_unlocked()
+ * to release a reference to a GEM buffer object.
+ */
struct kref refcount;
/**
- * handle_count - gem file_priv handle count of this object
+ * @handle_count:
+ *
+ * This is the GEM file_priv handle count of this object.
*
* Each handle also holds a reference. Note that when the handle_count
* drops to 0 any global names (e.g. the id in the flink namespace) will
* be cleared.
*
* Protected by dev->object_name_lock.
- * */
+ */
unsigned handle_count;
- /** Related drm device */
+ /**
+ * @dev: DRM dev this object belongs to.
+ */
struct drm_device *dev;
- /** File representing the shmem storage */
+ /**
+ * @filp:
+ *
+ * SHMEM file node used as backing storage for swappable buffer objects.
+ * GEM also supports driver private objects with driver-specific backing
+ * storage (contiguous CMA memory, special reserved blocks). In this
+ * case @filp is NULL.
+ */
struct file *filp;
- /* Mapping info for this object */
+ /**
+ * @vma_node:
+ *
+ * Mapping info for this object to support mmap. Drivers are supposed to
+ * allocate the mmap offset using drm_gem_create_mmap_offset(). The
+ * offset itself can be retrieved using drm_vma_node_offset_addr().
+ *
+ * Memory mapping itself is handled by drm_gem_mmap(), which also checks
+ * that userspace is allowed to access the object.
+ */
struct drm_vma_offset_node vma_node;
/**
+ * @size:
+ *
* Size of the object, in bytes. Immutable over the object's
* lifetime.
*/
size_t size;
/**
+ * @name:
+ *
* Global name for this object, starts at 1. 0 means unnamed.
- * Access is covered by the object_name_lock in the related drm_device
+ * Access is covered by dev->object_name_lock. This is used by the GEM_FLINK
+ * and GEM_OPEN ioctls.
*/
int name;
/**
- * Memory domains. These monitor which caches contain read/write data
+ * @read_domains:
+ *
+ * Read memory domains. These monitor which caches contain read/write data
* related to the object. When transitioning from one set of domains
* to another, the driver is called to ensure that caches are suitably
- * flushed and invalidated
+ * flushed and invalidated.
*/
uint32_t read_domains;
+
+ /**
+ * @write_domain: Corresponding unique write memory domain.
+ */
uint32_t write_domain;
/**
+ * @pending_read_domains:
+ *
* While validating an exec operation, the
* new read/write domain values are computed here.
* They will be transferred to the above values
* at the point that any cache flushing occurs
*/
uint32_t pending_read_domains;
+
+ /**
+ * @pending_write_domain: Write domain similar to @pending_read_domains.
+ */
uint32_t pending_write_domain;
/**
- * dma_buf - dma buf associated with this GEM object
+ * @dma_buf:
+ *
+ * dma-buf associated with this GEM object.
*
* Pointer to the dma-buf associated with this gem object (either
* through importing or exporting). We break the resulting reference
* loop when the last gem handle for this object is released.
*
- * Protected by obj->object_name_lock
+ * Protected by obj->object_name_lock.
*/
struct dma_buf *dma_buf;
/**
- * import_attach - dma buf attachment backing this object
+ * @import_attach:
+ *
+ * dma-buf attachment backing this object.
*
* Any foreign dma_buf imported as a gem object has this set to the
* attachment point for the device. This is invariant over the lifetime
@@ -133,12 +186,30 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
struct vm_area_struct *vma);
int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+/**
+ * drm_gem_object_reference - acquire a GEM BO reference
+ * @obj: GEM buffer object
+ *
+ * This acquires additional reference to @obj. It is illegal to call this
+ * without already holding a reference. No locks required.
+ */
static inline void
drm_gem_object_reference(struct drm_gem_object *obj)
{
kref_get(&obj->refcount);
}
+/**
+ * drm_gem_object_unreference - release a GEM BO reference
+ * @obj: GEM buffer object
+ *
+ * This releases a reference to @obj. Callers must hold the dev->struct_mutex
+ * lock when calling this function, even when the driver doesn't use
+ * dev->struct_mutex for anything.
+ *
+ * For drivers not encumbered with legacy locking use
+ * drm_gem_object_unreference_unlocked() instead.
+ */
static inline void
drm_gem_object_unreference(struct drm_gem_object *obj)
{
@@ -149,6 +220,13 @@ drm_gem_object_unreference(struct drm_gem_object *obj)
}
}
+/**
+ * drm_gem_object_unreference_unlocked - release a GEM BO reference
+ * @obj: GEM buffer object
+ *
+ * This releases a reference to @obj. Callers must not hold the
+ * dev->struct_mutex lock when calling this function.
+ */
static inline void
drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
{
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 0de6290df4da..fc65118e5077 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -148,8 +148,7 @@ static inline u64 drm_mm_hole_node_start(struct drm_mm_node *hole_node)
static inline u64 __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
{
- return list_entry(hole_node->node_list.next,
- struct drm_mm_node, node_list)->start;
+ return list_next_entry(hole_node, node_list)->start;
}
/**
@@ -180,6 +179,14 @@ static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
&(mm)->head_node.node_list, \
node_list)
+#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \
+ for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
+ &entry->hole_stack != &(mm)->hole_stack ? \
+ hole_start = drm_mm_hole_node_start(entry), \
+ hole_end = drm_mm_hole_node_end(entry), \
+ 1 : 0; \
+ entry = list_entry((backwards) ? entry->hole_stack.prev : entry->hole_stack.next, struct drm_mm_node, hole_stack))
+
/**
* drm_mm_for_each_hole - iterator to walk over all holes
* @entry: drm_mm_node used internally to track progress
@@ -200,20 +207,7 @@ static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
* going backwards.
*/
#define drm_mm_for_each_hole(entry, mm, hole_start, hole_end) \
- for (entry = list_entry((mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
- &entry->hole_stack != &(mm)->hole_stack ? \
- hole_start = drm_mm_hole_node_start(entry), \
- hole_end = drm_mm_hole_node_end(entry), \
- 1 : 0; \
- entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack))
-
-#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \
- for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
- &entry->hole_stack != &(mm)->hole_stack ? \
- hole_start = drm_mm_hole_node_start(entry), \
- hole_end = drm_mm_hole_node_end(entry), \
- 1 : 0; \
- entry = list_entry((backwards) ? entry->hole_stack.prev : entry->hole_stack.next, struct drm_mm_node, hole_stack))
+ __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, 0)
/*
* Basic range manager support (drm_mm.c)
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 08a8cac9e555..f9115aee43f4 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -222,6 +222,8 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
const struct drm_display_mode *mode);
bool drm_mode_equal(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2);
+bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1,
+ const struct drm_display_mode *mode2);
bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2);
diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
index 94938d89347c..c5576fbcb909 100644
--- a/include/drm/drm_modeset_lock.h
+++ b/include/drm/drm_modeset_lock.h
@@ -138,7 +138,7 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
struct drm_modeset_acquire_ctx *
drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc);
-int drm_modeset_lock_all_crtcs(struct drm_device *dev,
- struct drm_modeset_acquire_ctx *ctx);
+int drm_modeset_lock_all_ctx(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx);
#endif /* DRM_MODESET_LOCK_H_ */
diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h
index 26bb55e9e8b6..83bb156d4356 100644
--- a/include/drm/drm_rect.h
+++ b/include/drm/drm_rect.h
@@ -162,7 +162,8 @@ int drm_rect_calc_hscale_relaxed(struct drm_rect *src,
int drm_rect_calc_vscale_relaxed(struct drm_rect *src,
struct drm_rect *dst,
int min_vscale, int max_vscale);
-void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point);
+void drm_rect_debug_print(const char *prefix,
+ const struct drm_rect *r, bool fixed_point);
void drm_rect_rotate(struct drm_rect *r,
int width, int height,
unsigned int rotation);
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index 30d89e0da2c6..b46fa0ef3005 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -31,47 +31,94 @@
#define MAX_PORTS 5
/**
- * struct i915_audio_component_ops - callbacks defined in gfx driver
- * @owner: the module owner
- * @get_power: get the POWER_DOMAIN_AUDIO power well
- * @put_power: put the POWER_DOMAIN_AUDIO power well
- * @codec_wake_override: Enable/Disable generating the codec wake signal
- * @get_cdclk_freq: get the Core Display Clock in KHz
- * @sync_audio_rate: set n/cts based on the sample rate
+ * struct i915_audio_component_ops - Ops implemented by i915 driver, called by hda driver
*/
struct i915_audio_component_ops {
+ /**
+ * @owner: i915 module
+ */
struct module *owner;
+ /**
+ * @get_power: get the POWER_DOMAIN_AUDIO power well
+ *
+ * Request the power well to be turned on.
+ */
void (*get_power)(struct device *);
+ /**
+ * @put_power: put the POWER_DOMAIN_AUDIO power well
+ *
+ * Allow the power well to be turned off.
+ */
void (*put_power)(struct device *);
+ /**
+ * @codec_wake_override: Enable/disable codec wake signal
+ */
void (*codec_wake_override)(struct device *, bool enable);
+ /**
+ * @get_cdclk_freq: Get the Core Display Clock in kHz
+ */
int (*get_cdclk_freq)(struct device *);
+ /**
+ * @sync_audio_rate: set n/cts based on the sample rate
+ *
+ * Called from audio driver. After audio driver sets the
+ * sample rate, it will call this function to set n/cts
+ */
int (*sync_audio_rate)(struct device *, int port, int rate);
+ /**
+ * @get_eld: fill the audio state and ELD bytes for the given port
+ *
+ * Called from audio driver to get the HDMI/DP audio state of the given
+ * digital port, and also fetch ELD bytes to the given pointer.
+ *
+ * It returns the byte size of the original ELD (not the actually
+ * copied size), zero for an invalid ELD, or a negative error code.
+ *
+ * Note that the returned size may be over @max_bytes. Then it
+ * implies that only a part of ELD has been copied to the buffer.
+ */
+ int (*get_eld)(struct device *, int port, bool *enabled,
+ unsigned char *buf, int max_bytes);
};
+/**
+ * struct i915_audio_component_audio_ops - Ops implemented by hda driver, called by i915 driver
+ */
struct i915_audio_component_audio_ops {
+ /**
+ * @audio_ptr: Pointer to be used in call to pin_eld_notify
+ */
void *audio_ptr;
/**
- * Call from i915 driver, notifying the HDA driver that
- * pin sense and/or ELD information has changed.
- * @audio_ptr: HDA driver object
- * @port: Which port has changed (PORTA / PORTB / PORTC etc)
+ * @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed
+ *
+ * Called when the i915 driver has set up audio pipeline or has just
+ * begun to tear it down. This allows the HDA driver to update its
+ * status accordingly (even when the HDA controller is in power save
+ * mode).
*/
void (*pin_eld_notify)(void *audio_ptr, int port);
};
/**
- * struct i915_audio_component - used for audio video interaction
- * @dev: the device from gfx driver
- * @aud_sample_rate: the array of audio sample rate per port
- * @ops: callback for audio driver calling
- * @audio_ops: Call from i915 driver
+ * struct i915_audio_component - Used for direct communication between i915 and hda drivers
*/
struct i915_audio_component {
+ /**
+ * @dev: i915 device, used as parameter for ops
+ */
struct device *dev;
+ /**
+ * @aud_sample_rate: the array of audio sample rate per port
+ */
int aud_sample_rate[MAX_PORTS];
-
+ /**
+ * @ops: Ops implemented by i915 driver, called by hda driver
+ */
const struct i915_audio_component_ops *ops;
-
+ /**
+ * @audio_ops: Ops implemented by hda driver, called by i915 driver
+ */
const struct i915_audio_component_audio_ops *audio_ops;
};
diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h
index 17c445612e01..f1a113e35f98 100644
--- a/include/drm/i915_pciids.h
+++ b/include/drm/i915_pciids.h
@@ -291,4 +291,40 @@
INTEL_VGA_DEVICE(0x1A84, info), \
INTEL_VGA_DEVICE(0x5A84, info)
+#define INTEL_KBL_GT1_IDS(info) \
+ INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */ \
+ INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */ \
+ INTEL_VGA_DEVICE(0x5917, info), /* DT GT1.5 */ \
+ INTEL_VGA_DEVICE(0x5906, info), /* ULT GT1 */ \
+ INTEL_VGA_DEVICE(0x590E, info), /* ULX GT1 */ \
+ INTEL_VGA_DEVICE(0x5902, info), /* DT GT1 */ \
+ INTEL_VGA_DEVICE(0x590B, info), /* Halo GT1 */ \
+ INTEL_VGA_DEVICE(0x590A, info) /* SRV GT1 */
+
+#define INTEL_KBL_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \
+ INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \
+ INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \
+ INTEL_VGA_DEVICE(0x5912, info), /* DT GT2 */ \
+ INTEL_VGA_DEVICE(0x591B, info), /* Halo GT2 */ \
+ INTEL_VGA_DEVICE(0x591A, info), /* SRV GT2 */ \
+ INTEL_VGA_DEVICE(0x591D, info) /* WKS GT2 */
+
+#define INTEL_KBL_GT3_IDS(info) \
+ INTEL_VGA_DEVICE(0x5926, info), /* ULT GT3 */ \
+ INTEL_VGA_DEVICE(0x592B, info), /* Halo GT3 */ \
+ INTEL_VGA_DEVICE(0x592A, info) /* SRV GT3 */
+
+#define INTEL_KBL_GT4_IDS(info) \
+ INTEL_VGA_DEVICE(0x5932, info), /* DT GT4 */ \
+ INTEL_VGA_DEVICE(0x593B, info), /* Halo GT4 */ \
+ INTEL_VGA_DEVICE(0x593A, info), /* SRV GT4 */ \
+ INTEL_VGA_DEVICE(0x593D, info) /* WKS GT4 */
+
+#define INTEL_KBL_IDS(info) \
+ INTEL_KBL_GT1_IDS(info), \
+ INTEL_KBL_GT2_IDS(info), \
+ INTEL_KBL_GT3_IDS(info), \
+ INTEL_KBL_GT4_IDS(info)
+
#endif /* _I915_PCIIDS_H */
diff --git a/include/linux/platform_data/asoc-s3c.h b/include/linux/platform_data/asoc-s3c.h
index 5e0bc779e6c5..15bf56ee8af7 100644
--- a/include/linux/platform_data/asoc-s3c.h
+++ b/include/linux/platform_data/asoc-s3c.h
@@ -13,6 +13,9 @@
*/
#define S3C64XX_AC97_GPD 0
#define S3C64XX_AC97_GPE 1
+
+#include <linux/dmaengine.h>
+
extern void s3c64xx_ac97_setup_gpio(int);
struct samsung_i2s {
@@ -39,6 +42,11 @@ struct samsung_i2s {
*/
struct s3c_audio_pdata {
int (*cfg_gpio)(struct platform_device *);
+ dma_filter_fn dma_filter;
+ void *dma_playback;
+ void *dma_capture;
+ void *dma_play_sec;
+ void *dma_capture_mic;
union {
struct samsung_i2s i2s;
} type;
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 74bc85473b58..15aa5f07c955 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -417,11 +417,13 @@
#define AC97_RATES_MIC_ADC 4
#define AC97_RATES_SPDIF 5
+#define AC97_NUM_GPIOS 16
/*
*
*/
struct snd_ac97;
+struct snd_ac97_gpio_priv;
struct snd_pcm_chmap;
struct snd_ac97_build_ops {
@@ -529,6 +531,7 @@ struct snd_ac97 {
struct delayed_work power_work;
#endif
struct device dev;
+ struct snd_ac97_gpio_priv *gpio_priv;
struct snd_pcm_chmap *chmaps[2]; /* channel-maps (optional) */
};
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
index fa1d05512c09..c0abcdc11470 100644
--- a/include/sound/compress_driver.h
+++ b/include/sound/compress_driver.h
@@ -152,13 +152,18 @@ struct snd_compr {
unsigned int direction;
struct mutex lock;
int device;
+#ifdef CONFIG_SND_VERBOSE_PROCFS
+ char id[64];
+ struct snd_info_entry *proc_root;
+ struct snd_info_entry *proc_info_entry;
+#endif
};
/* compress device register APIs */
int snd_compress_register(struct snd_compr *device);
int snd_compress_deregister(struct snd_compr *device);
int snd_compress_new(struct snd_card *card, int device,
- int type, struct snd_compr *compr);
+ int type, const char *id, struct snd_compr *compr);
/* dsp driver callback apis
* For playback: driver should call snd_compress_fragment_elapsed() to let the
diff --git a/include/sound/core.h b/include/sound/core.h
index cdfecafff0f4..31079ea5e484 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -99,6 +99,7 @@ struct snd_card {
char driver[16]; /* driver name */
char shortname[32]; /* short name of this soundcard */
char longname[80]; /* name of this soundcard */
+ char irq_descr[32]; /* Interrupt description */
char mixername[80]; /* mixer name */
char components[128]; /* card components delimited with
space */
diff --git a/include/sound/da7218.h b/include/sound/da7218.h
new file mode 100644
index 000000000000..0dbb818ac116
--- /dev/null
+++ b/include/sound/da7218.h
@@ -0,0 +1,109 @@
+/*
+ * da7218.h - DA7218 ASoC Codec Driver Platform Data
+ *
+ * Copyright (c) 2015 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.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; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _DA7218_PDATA_H
+#define _DA7218_PDATA_H
+
+/* Mic Bias */
+enum da7218_micbias_voltage {
+ DA7218_MICBIAS_1_2V = -1,
+ DA7218_MICBIAS_1_6V,
+ DA7218_MICBIAS_1_8V,
+ DA7218_MICBIAS_2_0V,
+ DA7218_MICBIAS_2_2V,
+ DA7218_MICBIAS_2_4V,
+ DA7218_MICBIAS_2_6V,
+ DA7218_MICBIAS_2_8V,
+ DA7218_MICBIAS_3_0V,
+};
+
+enum da7218_mic_amp_in_sel {
+ DA7218_MIC_AMP_IN_SEL_DIFF = 0,
+ DA7218_MIC_AMP_IN_SEL_SE_P,
+ DA7218_MIC_AMP_IN_SEL_SE_N,
+};
+
+/* DMIC */
+enum da7218_dmic_data_sel {
+ DA7218_DMIC_DATA_LRISE_RFALL = 0,
+ DA7218_DMIC_DATA_LFALL_RRISE,
+};
+
+enum da7218_dmic_samplephase {
+ DA7218_DMIC_SAMPLE_ON_CLKEDGE = 0,
+ DA7218_DMIC_SAMPLE_BETWEEN_CLKEDGE,
+};
+
+enum da7218_dmic_clk_rate {
+ DA7218_DMIC_CLK_3_0MHZ = 0,
+ DA7218_DMIC_CLK_1_5MHZ,
+};
+
+/* Headphone Detect */
+enum da7218_hpldet_jack_rate {
+ DA7218_HPLDET_JACK_RATE_5US = 0,
+ DA7218_HPLDET_JACK_RATE_10US,
+ DA7218_HPLDET_JACK_RATE_20US,
+ DA7218_HPLDET_JACK_RATE_40US,
+ DA7218_HPLDET_JACK_RATE_80US,
+ DA7218_HPLDET_JACK_RATE_160US,
+ DA7218_HPLDET_JACK_RATE_320US,
+ DA7218_HPLDET_JACK_RATE_640US,
+};
+
+enum da7218_hpldet_jack_debounce {
+ DA7218_HPLDET_JACK_DEBOUNCE_OFF = 0,
+ DA7218_HPLDET_JACK_DEBOUNCE_2,
+ DA7218_HPLDET_JACK_DEBOUNCE_3,
+ DA7218_HPLDET_JACK_DEBOUNCE_4,
+};
+
+enum da7218_hpldet_jack_thr {
+ DA7218_HPLDET_JACK_THR_84PCT = 0,
+ DA7218_HPLDET_JACK_THR_88PCT,
+ DA7218_HPLDET_JACK_THR_92PCT,
+ DA7218_HPLDET_JACK_THR_96PCT,
+};
+
+struct da7218_hpldet_pdata {
+ enum da7218_hpldet_jack_rate jack_rate;
+ enum da7218_hpldet_jack_debounce jack_debounce;
+ enum da7218_hpldet_jack_thr jack_thr;
+ bool comp_inv;
+ bool hyst;
+ bool discharge;
+};
+
+struct da7218_pdata {
+ /* Mic */
+ enum da7218_micbias_voltage micbias1_lvl;
+ enum da7218_micbias_voltage micbias2_lvl;
+ enum da7218_mic_amp_in_sel mic1_amp_in_sel;
+ enum da7218_mic_amp_in_sel mic2_amp_in_sel;
+
+ /* DMIC */
+ enum da7218_dmic_data_sel dmic1_data_sel;
+ enum da7218_dmic_data_sel dmic2_data_sel;
+ enum da7218_dmic_samplephase dmic1_samplephase;
+ enum da7218_dmic_samplephase dmic2_samplephase;
+ enum da7218_dmic_clk_rate dmic1_clk_rate;
+ enum da7218_dmic_clk_rate dmic2_clk_rate;
+
+ /* HP Diff Supply - DA7217 only */
+ bool hp_diff_single_supply;
+
+ /* HP Detect - DA7218 only */
+ struct da7218_hpldet_pdata *hpldet_pdata;
+};
+
+#endif /* _DA7218_PDATA_H */
diff --git a/include/sound/da7219.h b/include/sound/da7219.h
index 3f39e135312d..02876acdc840 100644
--- a/include/sound/da7219.h
+++ b/include/sound/da7219.h
@@ -14,17 +14,10 @@
#ifndef __DA7219_PDATA_H
#define __DA7219_PDATA_H
-/* LDO */
-enum da7219_ldo_lvl_sel {
- DA7219_LDO_LVL_SEL_1_05V = 0,
- DA7219_LDO_LVL_SEL_1_10V,
- DA7219_LDO_LVL_SEL_1_20V,
- DA7219_LDO_LVL_SEL_1_40V,
-};
-
/* Mic Bias */
enum da7219_micbias_voltage {
- DA7219_MICBIAS_1_8V = 1,
+ DA7219_MICBIAS_1_6V = 0,
+ DA7219_MICBIAS_1_8V,
DA7219_MICBIAS_2_0V,
DA7219_MICBIAS_2_2V,
DA7219_MICBIAS_2_4V,
@@ -41,9 +34,6 @@ enum da7219_mic_amp_in_sel {
struct da7219_aad_pdata;
struct da7219_pdata {
- /* Internal LDO */
- enum da7219_ldo_lvl_sel ldo_lvl_sel;
-
/* Mic */
enum da7219_micbias_voltage micbias_lvl;
enum da7219_mic_amp_in_sel mic_amp_in_sel;
diff --git a/include/sound/designware_i2s.h b/include/sound/designware_i2s.h
index 8966ba7c9629..5681855396c4 100644
--- a/include/sound/designware_i2s.h
+++ b/include/sound/designware_i2s.h
@@ -45,6 +45,12 @@ struct i2s_platform_data {
u32 snd_fmts;
u32 snd_rates;
+ #define DW_I2S_QUIRK_COMP_REG_OFFSET (1 << 0)
+ #define DW_I2S_QUIRK_COMP_PARAM1 (1 << 1)
+ unsigned int quirks;
+ unsigned int i2s_reg_comp1;
+ unsigned int i2s_reg_comp2;
+
void *play_dma_data;
void *capture_dma_data;
bool (*filter)(struct dma_chan *chan, void *slave);
diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h
index 930b41e5acf4..fa341fcb5829 100644
--- a/include/sound/hda_i915.h
+++ b/include/sound/hda_i915.h
@@ -10,6 +10,9 @@
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
int snd_hdac_get_display_clk(struct hdac_bus *bus);
+int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid, int rate);
+int snd_hdac_acomp_get_eld(struct hdac_bus *bus, hda_nid_t nid,
+ bool *audio_enabled, char *buffer, int max_bytes);
int snd_hdac_i915_init(struct hdac_bus *bus);
int snd_hdac_i915_exit(struct hdac_bus *bus);
int snd_hdac_i915_register_notifier(const struct i915_audio_component_audio_ops *);
@@ -26,6 +29,17 @@ static inline int snd_hdac_get_display_clk(struct hdac_bus *bus)
{
return 0;
}
+static inline int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid,
+ int rate)
+{
+ return 0;
+}
+static inline int snd_hdac_acomp_get_eld(struct hdac_bus *bus, hda_nid_t nid,
+ bool *audio_enabled, char *buffer,
+ int max_bytes)
+{
+ return -ENODEV;
+}
static inline int snd_hdac_i915_init(struct hdac_bus *bus)
{
return -ENODEV;
diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h
index 94dc6a9772e0..ff1aecf325e8 100644
--- a/include/sound/hda_register.h
+++ b/include/sound/hda_register.h
@@ -233,6 +233,15 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_MLCTL_SPA (1<<16)
#define AZX_MLCTL_CPA 23
+
+/* registers for DMA Resume Capability Structure */
+#define AZX_DRSM_CAP_ID 0x5
+#define AZX_REG_DRSM_CTL 0x4
+/* Base used to calculate the iterating register offset */
+#define AZX_DRSM_BASE 0x08
+/* Interval used to calculate the iterating register offset */
+#define AZX_DRSM_INTERVAL 0x08
+
/*
* helpers to read the stream position
*/
diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h
index a4cadd9c297a..07fa59237feb 100644
--- a/include/sound/hdaudio_ext.h
+++ b/include/sound/hdaudio_ext.h
@@ -12,6 +12,7 @@
* @spbcap: SPIB capabilities pointer
* @mlcap: MultiLink capabilities pointer
* @gtscap: gts capabilities pointer
+ * @drsmcap: dma resume capabilities pointer
* @hlink_list: link list of HDA links
*/
struct hdac_ext_bus {
@@ -23,6 +24,7 @@ struct hdac_ext_bus {
void __iomem *spbcap;
void __iomem *mlcap;
void __iomem *gtscap;
+ void __iomem *drsmcap;
struct list_head hlink_list;
};
@@ -72,6 +74,9 @@ enum hdac_ext_stream_type {
* @pplc_addr: processing pipe link stream pointer
* @spib_addr: software position in buffers stream pointer
* @fifo_addr: software position Max fifos stream pointer
+ * @dpibr_addr: DMA position in buffer resume pointer
+ * @dpib: DMA position in buffer
+ * @lpib: Linear position in buffer
* @decoupled: stream host and link is decoupled
* @link_locked: link is locked
* @link_prepared: link is prepared
@@ -86,6 +91,10 @@ struct hdac_ext_stream {
void __iomem *spib_addr;
void __iomem *fifo_addr;
+ void __iomem *dpibr_addr;
+
+ u32 dpib;
+ u32 lpib;
bool decoupled:1;
bool link_locked:1;
bool link_prepared;
@@ -116,6 +125,11 @@ int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus,
struct hdac_ext_stream *stream, u32 value);
int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus,
struct hdac_ext_stream *stream);
+void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus,
+ bool enable, int index);
+int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus,
+ struct hdac_ext_stream *stream, u32 value);
+int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *stream, u32 value);
void snd_hdac_ext_link_stream_start(struct hdac_ext_stream *hstream);
void snd_hdac_ext_link_stream_clear(struct hdac_ext_stream *hstream);
@@ -133,6 +147,7 @@ struct hdac_ext_link {
int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link);
+int snd_hdac_ext_bus_link_power_up_all(struct hdac_ext_bus *ebus);
int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus);
void snd_hdac_ext_link_set_stream_id(struct hdac_ext_link *link,
int stream);
@@ -186,9 +201,15 @@ struct hdac_ext_device {
/* codec ops */
struct hdac_ext_codec_ops ops;
+ struct snd_card *card;
+ void *scodec;
void *private_data;
};
+struct hdac_ext_dma_params {
+ u32 format;
+ u8 stream_tag;
+};
#define to_ehdac_device(dev) (container_of((dev), \
struct hdac_ext_device, hdac))
/*
diff --git a/include/sound/i2c.h b/include/sound/i2c.h
index d125ff8c85e8..835254de2039 100644
--- a/include/sound/i2c.h
+++ b/include/sound/i2c.h
@@ -66,7 +66,7 @@ struct snd_i2c_bus {
struct snd_i2c_bit_ops *bit;
void *ops;
} hw_ops; /* lowlevel operations */
- struct snd_i2c_ops *ops; /* midlevel operations */
+ const struct snd_i2c_ops *ops; /* midlevel operations */
unsigned long private_value;
void *private_data;
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index f6cbef78db62..fdabbb4ddba9 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -130,7 +130,7 @@ struct snd_rawmidi {
int ossreg;
#endif
- struct snd_rawmidi_global_ops *ops;
+ const struct snd_rawmidi_global_ops *ops;
struct snd_rawmidi_str streams[2];
diff --git a/include/sound/rt5659.h b/include/sound/rt5659.h
new file mode 100644
index 000000000000..656c4d58948d
--- /dev/null
+++ b/include/sound/rt5659.h
@@ -0,0 +1,49 @@
+/*
+ * linux/sound/rt5659.h -- Platform data for RT5659
+ *
+ * Copyright 2013 Realtek Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_RT5659_H
+#define __LINUX_SND_RT5659_H
+
+enum rt5659_dmic1_data_pin {
+ RT5659_DMIC1_NULL,
+ RT5659_DMIC1_DATA_IN2N,
+ RT5659_DMIC1_DATA_GPIO5,
+ RT5659_DMIC1_DATA_GPIO9,
+ RT5659_DMIC1_DATA_GPIO11,
+};
+
+enum rt5659_dmic2_data_pin {
+ RT5659_DMIC2_NULL,
+ RT5659_DMIC2_DATA_IN2P,
+ RT5659_DMIC2_DATA_GPIO6,
+ RT5659_DMIC2_DATA_GPIO10,
+ RT5659_DMIC2_DATA_GPIO12,
+};
+
+enum rt5659_jd_src {
+ RT5659_JD_NULL,
+ RT5659_JD3,
+};
+
+struct rt5659_platform_data {
+ bool in1_diff;
+ bool in3_diff;
+ bool in4_diff;
+
+ int ldo1_en; /* GPIO for LDO1_EN */
+ int reset; /* GPIO for RESET */
+
+ enum rt5659_dmic1_data_pin dmic1_data_pin;
+ enum rt5659_dmic2_data_pin dmic2_data_pin;
+ enum rt5659_jd_src jd_src;
+};
+
+#endif
+
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 212eaaf172ed..964b7de1a1cc 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -222,6 +222,7 @@ struct snd_soc_dai_driver {
const char *name;
unsigned int id;
unsigned int base;
+ struct snd_soc_dobj dobj;
/* DAI driver callbacks */
int (*probe)(struct snd_soc_dai *dai);
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 95a937eafb79..97069466c38d 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -49,6 +49,9 @@ struct device;
#define SND_SOC_DAPM_SIGGEN(wname) \
{ .id = snd_soc_dapm_siggen, .name = wname, .kcontrol_news = NULL, \
.num_kcontrols = 0, .reg = SND_SOC_NOPM }
+#define SND_SOC_DAPM_SINK(wname) \
+{ .id = snd_soc_dapm_sink, .name = wname, .kcontrol_news = NULL, \
+ .num_kcontrols = 0, .reg = SND_SOC_NOPM }
#define SND_SOC_DAPM_INPUT(wname) \
{ .id = snd_soc_dapm_input, .name = wname, .kcontrol_news = NULL, \
.num_kcontrols = 0, .reg = SND_SOC_NOPM }
@@ -485,6 +488,7 @@ enum snd_soc_dapm_type {
snd_soc_dapm_aif_in, /* audio interface input */
snd_soc_dapm_aif_out, /* audio interface output */
snd_soc_dapm_siggen, /* signal generator */
+ snd_soc_dapm_sink,
snd_soc_dapm_dai_in, /* link to DAI structure */
snd_soc_dapm_dai_out,
snd_soc_dapm_dai_link, /* link between two DAI structures */
diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h
index 086cd7ff6ddc..5b68e3f5aa85 100644
--- a/include/sound/soc-topology.h
+++ b/include/sound/soc-topology.h
@@ -92,8 +92,10 @@ struct snd_soc_tplg_kcontrol_ops {
/* Bytes ext operations, for TLV byte controls */
struct snd_soc_tplg_bytes_ext_ops {
u32 id;
- int (*get)(unsigned int __user *bytes, unsigned int size);
- int (*put)(const unsigned int __user *bytes, unsigned int size);
+ int (*get)(struct snd_kcontrol *kcontrol, unsigned int __user *bytes,
+ unsigned int size);
+ int (*put)(struct snd_kcontrol *kcontrol,
+ const unsigned int __user *bytes, unsigned int size);
};
/*
diff --git a/include/sound/soc.h b/include/sound/soc.h
index fb955e69a78e..7afb72ceac56 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -110,6 +110,14 @@
.put = snd_soc_put_volsw, \
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
max, invert, 0) }
+#define SOC_DOUBLE_STS(xname, reg, shift_left, shift_right, max, invert) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | \
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
+ max, invert, 0) }
#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.info = snd_soc_info_volsw, \
@@ -293,6 +301,9 @@
{.base = xbase, .num_regs = xregs, \
.mask = xmask }) }
+/*
+ * SND_SOC_BYTES_EXT is deprecated, please USE SND_SOC_BYTES_TLV instead
+ */
#define SND_SOC_BYTES_EXT(xname, xcount, xhandler_get, xhandler_put) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_bytes_info_ext, \
@@ -787,6 +798,7 @@ struct snd_soc_component {
unsigned int registered_as_component:1;
struct list_head list;
+ struct list_head list_aux; /* for auxiliary component of the card */
struct snd_soc_dai_driver *dai_drv;
int num_dai;
@@ -830,6 +842,9 @@ struct snd_soc_component {
int (*probe)(struct snd_soc_component *);
void (*remove)(struct snd_soc_component *);
+ /* machine specific init */
+ int (*init)(struct snd_soc_component *component);
+
#ifdef CONFIG_DEBUG_FS
void (*init_debugfs)(struct snd_soc_component *component);
const char *debugfs_prefix;
@@ -1037,6 +1052,9 @@ struct snd_soc_dai_link {
/* pmdown_time is ignored at stop */
unsigned int ignore_pmdown_time:1;
+
+ struct list_head list; /* DAI link list of the soc card */
+ struct snd_soc_dobj dobj; /* For topology */
};
struct snd_soc_codec_conf {
@@ -1101,12 +1119,20 @@ struct snd_soc_card {
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level);
+ int (*add_dai_link)(struct snd_soc_card *,
+ struct snd_soc_dai_link *link);
+ void (*remove_dai_link)(struct snd_soc_card *,
+ struct snd_soc_dai_link *link);
+
long pmdown_time;
/* CPU <--> Codec DAI links */
- struct snd_soc_dai_link *dai_link;
- int num_links;
- struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai_link *dai_link; /* predefined links only */
+ int num_links; /* predefined links only */
+ struct list_head dai_link_list; /* all links */
+ int num_dai_links;
+
+ struct list_head rtd_list;
int num_rtd;
/* optional codec specific configuration */
@@ -1119,8 +1145,7 @@ struct snd_soc_card {
*/
struct snd_soc_aux_dev *aux_dev;
int num_aux_devs;
- struct snd_soc_pcm_runtime *rtd_aux;
- int num_aux_rtd;
+ struct list_head aux_comp_list;
const struct snd_kcontrol_new *controls;
int num_controls;
@@ -1201,6 +1226,9 @@ struct snd_soc_pcm_runtime {
struct dentry *debugfs_dpcm_root;
struct dentry *debugfs_dpcm_state;
#endif
+
+ unsigned int num; /* 0-based and monotonic increasing */
+ struct list_head list; /* rtd list of the soc card */
};
/* mixer control */
@@ -1225,8 +1253,10 @@ struct soc_bytes_ext {
struct snd_soc_dobj dobj;
/* used for TLV byte control */
- int (*get)(unsigned int __user *bytes, unsigned int size);
- int (*put)(const unsigned int __user *bytes, unsigned int size);
+ int (*get)(struct snd_kcontrol *kcontrol, unsigned int __user *bytes,
+ unsigned int size);
+ int (*put)(struct snd_kcontrol *kcontrol, const unsigned int __user *bytes,
+ unsigned int size);
};
/* multi register control */
@@ -1523,6 +1553,7 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
INIT_LIST_HEAD(&card->widgets);
INIT_LIST_HEAD(&card->paths);
INIT_LIST_HEAD(&card->dapm_list);
+ INIT_LIST_HEAD(&card->aux_comp_list);
}
static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
@@ -1644,6 +1675,14 @@ int snd_soc_of_get_dai_link_codecs(struct device *dev,
struct device_node *of_node,
struct snd_soc_dai_link *dai_link);
+int snd_soc_add_dai_link(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_link);
+void snd_soc_remove_dai_link(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_link);
+
+int snd_soc_register_dai(struct snd_soc_component *component,
+ struct snd_soc_dai_driver *dai_drv);
+
#include <sound/soc-dai.h>
#ifdef CONFIG_DEBUG_FS
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 484a9fb20479..67ef73a5d6eb 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1079,6 +1079,12 @@ struct drm_i915_gem_context_destroy {
};
struct drm_i915_reg_read {
+ /*
+ * Register offset.
+ * For 64bit wide registers where the upper 32bits don't immediately
+ * follow the lower 32bits, the offset of the lower 32bits must
+ * be specified
+ */
__u64 offset;
__u64 val; /* Return value */
};
@@ -1125,8 +1131,9 @@ struct drm_i915_gem_context_param {
__u32 ctx_id;
__u32 size;
__u64 param;
-#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
-#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
+#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
+#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
+#define I915_CONTEXT_PARAM_GTT_SIZE 0x3
__u64 value;
};
diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h
index 26539a7e4880..c4cc1e40b35c 100644
--- a/include/uapi/sound/asoc.h
+++ b/include/uapi/sound/asoc.h
@@ -243,7 +243,7 @@ struct snd_soc_tplg_manifest {
__le32 control_elems; /* number of control elements */
__le32 widget_elems; /* number of widget elements */
__le32 graph_elems; /* number of graph elements */
- __le32 dai_elems; /* number of DAI elements */
+ __le32 pcm_elems; /* number of PCM elements */
__le32 dai_link_elems; /* number of DAI link elements */
struct snd_soc_tplg_private priv;
} __attribute__((packed));
diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h
index d9bd9ca0d5b0..9625484a4a2a 100644
--- a/include/uapi/sound/compress_params.h
+++ b/include/uapi/sound/compress_params.h
@@ -73,7 +73,8 @@
#define SND_AUDIOCODEC_IEC61937 ((__u32) 0x0000000B)
#define SND_AUDIOCODEC_G723_1 ((__u32) 0x0000000C)
#define SND_AUDIOCODEC_G729 ((__u32) 0x0000000D)
-#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_G729
+#define SND_AUDIOCODEC_BESPOKE ((__u32) 0x0000000E)
+#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_BESPOKE
/*
* Profile and modes are listed with bit masks. This allows for a
@@ -312,7 +313,7 @@ struct snd_enc_flac {
struct snd_enc_generic {
__u32 bw; /* encoder bandwidth */
- __s32 reserved[15];
+ __s32 reserved[15]; /* Can be used for SND_AUDIOCODEC_BESPOKE */
} __attribute__((packed, aligned(4)));
union snd_codec_options {
diff --git a/kernel/async.c b/kernel/async.c
index 4c3773c0bf63..d2edd6efec56 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -326,3 +326,4 @@ bool current_is_async(void)
return worker && worker->current_func == async_run_entry_fn;
}
+EXPORT_SYMBOL_GPL(current_is_async);
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index b123c42e7dc8..18b8dc45bb8f 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -38,8 +38,10 @@
#include <linux/uio.h>
#include <linux/uaccess.h>
#include <linux/module.h>
+#include <linux/compat.h>
#include <sound/core.h>
#include <sound/initval.h>
+#include <sound/info.h>
#include <sound/compress_params.h>
#include <sound/compress_offload.h>
#include <sound/compress_driver.h>
@@ -847,6 +849,15 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
return retval;
}
+/* support of 32bit userspace on 64bit platforms */
+#ifdef CONFIG_COMPAT
+static long snd_compr_ioctl_compat(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return snd_compr_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
static const struct file_operations snd_compr_file_ops = {
.owner = THIS_MODULE,
.open = snd_compr_open,
@@ -854,6 +865,9 @@ static const struct file_operations snd_compr_file_ops = {
.write = snd_compr_write,
.read = snd_compr_read,
.unlocked_ioctl = snd_compr_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = snd_compr_ioctl_compat,
+#endif
.mmap = snd_compr_mmap,
.poll = snd_compr_poll,
};
@@ -891,11 +905,85 @@ static int snd_compress_dev_disconnect(struct snd_device *device)
return 0;
}
+#ifdef CONFIG_SND_VERBOSE_PROCFS
+static void snd_compress_proc_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct snd_compr *compr = (struct snd_compr *)entry->private_data;
+
+ snd_iprintf(buffer, "card: %d\n", compr->card->number);
+ snd_iprintf(buffer, "device: %d\n", compr->device);
+ snd_iprintf(buffer, "stream: %s\n",
+ compr->direction == SND_COMPRESS_PLAYBACK
+ ? "PLAYBACK" : "CAPTURE");
+ snd_iprintf(buffer, "id: %s\n", compr->id);
+}
+
+static int snd_compress_proc_init(struct snd_compr *compr)
+{
+ struct snd_info_entry *entry;
+ char name[16];
+
+ sprintf(name, "compr%i", compr->device);
+ entry = snd_info_create_card_entry(compr->card, name,
+ compr->card->proc_root);
+ if (!entry)
+ return -ENOMEM;
+ entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ if (snd_info_register(entry) < 0) {
+ snd_info_free_entry(entry);
+ return -ENOMEM;
+ }
+ compr->proc_root = entry;
+
+ entry = snd_info_create_card_entry(compr->card, "info",
+ compr->proc_root);
+ if (entry) {
+ snd_info_set_text_ops(entry, compr,
+ snd_compress_proc_info_read);
+ if (snd_info_register(entry) < 0) {
+ snd_info_free_entry(entry);
+ entry = NULL;
+ }
+ }
+ compr->proc_info_entry = entry;
+
+ return 0;
+}
+
+static void snd_compress_proc_done(struct snd_compr *compr)
+{
+ snd_info_free_entry(compr->proc_info_entry);
+ compr->proc_info_entry = NULL;
+ snd_info_free_entry(compr->proc_root);
+ compr->proc_root = NULL;
+}
+
+static inline void snd_compress_set_id(struct snd_compr *compr, const char *id)
+{
+ strlcpy(compr->id, id, sizeof(compr->id));
+}
+#else
+static inline int snd_compress_proc_init(struct snd_compr *compr)
+{
+ return 0;
+}
+
+static inline void snd_compress_proc_done(struct snd_compr *compr)
+{
+}
+
+static inline void snd_compress_set_id(struct snd_compr *compr, const char *id)
+{
+}
+#endif
+
static int snd_compress_dev_free(struct snd_device *device)
{
struct snd_compr *compr;
compr = device->device_data;
+ snd_compress_proc_done(compr);
put_device(&compr->dev);
return 0;
}
@@ -908,22 +996,29 @@ static int snd_compress_dev_free(struct snd_device *device)
* @compr: compress device pointer
*/
int snd_compress_new(struct snd_card *card, int device,
- int dirn, struct snd_compr *compr)
+ int dirn, const char *id, struct snd_compr *compr)
{
static struct snd_device_ops ops = {
.dev_free = snd_compress_dev_free,
.dev_register = snd_compress_dev_register,
.dev_disconnect = snd_compress_dev_disconnect,
};
+ int ret;
compr->card = card;
compr->device = device;
compr->direction = dirn;
+ snd_compress_set_id(compr, id);
+
snd_device_initialize(&compr->dev, card);
dev_set_name(&compr->dev, "comprC%iD%i", card->number, device);
- return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
+ ret = snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
+ if (ret == 0)
+ snd_compress_proc_init(compr);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_compress_new);
diff --git a/sound/core/init.c b/sound/core/init.c
index 20f37fb3800e..6bda8436d765 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -268,6 +268,9 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
if (err < 0)
goto __error;
+ snprintf(card->irq_descr, sizeof(card->irq_descr), "%s:%s",
+ dev_driver_string(card->dev), dev_name(&card->card_dev));
+
/* the control interface cannot be accessed from the user space until */
/* snd_cards_bitmask and snd_cards are set with snd_card_register */
err = snd_ctl_create(card);
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 7a8c79dd9734..2ff9c12d664a 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -24,6 +24,7 @@
#include <linux/time.h>
#include <linux/string.h>
#include <linux/module.h>
+#include <linux/compat.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/control.h>
@@ -397,7 +398,12 @@ int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned l
#ifdef CONFIG_COMPAT
/* all compatible */
-#define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl
+static long snd_mixer_oss_ioctl_compat(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return snd_mixer_oss_ioctl1(file->private_data, cmd,
+ (unsigned long)compat_ptr(arg));
+}
#else
#define snd_mixer_oss_ioctl_compat NULL
#endif
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 58550cc93f28..0e73d03b30e3 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -33,6 +33,7 @@
#include <linux/module.h>
#include <linux/math64.h>
#include <linux/string.h>
+#include <linux/compat.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/pcm.h>
@@ -850,7 +851,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
if (mutex_lock_interruptible(&runtime->oss.params_lock))
return -EINTR;
- sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
+ sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL);
params = kmalloc(sizeof(*params), GFP_KERNEL);
sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
if (!sw_params || !params || !sparams) {
@@ -988,7 +989,6 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
goto failure;
}
- memset(sw_params, 0, sizeof(*sw_params));
if (runtime->oss.trigger) {
sw_params->start_threshold = 1;
} else {
@@ -2648,7 +2648,11 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
#ifdef CONFIG_COMPAT
/* all compatible */
-#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl
+static long snd_pcm_oss_ioctl_compat(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return snd_pcm_oss_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
+}
#else
#define snd_pcm_oss_ioctl_compat NULL
#endif
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a8b27cdc2844..fadd3eb8e8bb 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -875,7 +875,7 @@ struct action_ops {
* Note: the stream state might be changed also on failure
* Note2: call with calling stream lock + link lock
*/
-static int snd_pcm_action_group(struct action_ops *ops,
+static int snd_pcm_action_group(const struct action_ops *ops,
struct snd_pcm_substream *substream,
int state, int do_lock)
{
@@ -932,7 +932,7 @@ static int snd_pcm_action_group(struct action_ops *ops,
/*
* Note: call with stream lock
*/
-static int snd_pcm_action_single(struct action_ops *ops,
+static int snd_pcm_action_single(const struct action_ops *ops,
struct snd_pcm_substream *substream,
int state)
{
@@ -952,7 +952,7 @@ static int snd_pcm_action_single(struct action_ops *ops,
/*
* Note: call with stream lock
*/
-static int snd_pcm_action(struct action_ops *ops,
+static int snd_pcm_action(const struct action_ops *ops,
struct snd_pcm_substream *substream,
int state)
{
@@ -984,7 +984,7 @@ static int snd_pcm_action(struct action_ops *ops,
/*
* Note: don't use any locks before
*/
-static int snd_pcm_action_lock_irq(struct action_ops *ops,
+static int snd_pcm_action_lock_irq(const struct action_ops *ops,
struct snd_pcm_substream *substream,
int state)
{
@@ -998,7 +998,7 @@ static int snd_pcm_action_lock_irq(struct action_ops *ops,
/*
*/
-static int snd_pcm_action_nonatomic(struct action_ops *ops,
+static int snd_pcm_action_nonatomic(const struct action_ops *ops,
struct snd_pcm_substream *substream,
int state)
{
@@ -1056,7 +1056,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTART);
}
-static struct action_ops snd_pcm_action_start = {
+static const struct action_ops snd_pcm_action_start = {
.pre_action = snd_pcm_pre_start,
.do_action = snd_pcm_do_start,
.undo_action = snd_pcm_undo_start,
@@ -1107,7 +1107,7 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
wake_up(&runtime->tsleep);
}
-static struct action_ops snd_pcm_action_stop = {
+static const struct action_ops snd_pcm_action_stop = {
.pre_action = snd_pcm_pre_stop,
.do_action = snd_pcm_do_stop,
.post_action = snd_pcm_post_stop
@@ -1224,7 +1224,7 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
}
}
-static struct action_ops snd_pcm_action_pause = {
+static const struct action_ops snd_pcm_action_pause = {
.pre_action = snd_pcm_pre_pause,
.do_action = snd_pcm_do_pause,
.undo_action = snd_pcm_undo_pause,
@@ -1273,7 +1273,7 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
wake_up(&runtime->tsleep);
}
-static struct action_ops snd_pcm_action_suspend = {
+static const struct action_ops snd_pcm_action_suspend = {
.pre_action = snd_pcm_pre_suspend,
.do_action = snd_pcm_do_suspend,
.post_action = snd_pcm_post_suspend
@@ -1375,7 +1375,7 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME);
}
-static struct action_ops snd_pcm_action_resume = {
+static const struct action_ops snd_pcm_action_resume = {
.pre_action = snd_pcm_pre_resume,
.do_action = snd_pcm_do_resume,
.undo_action = snd_pcm_undo_resume,
@@ -1478,7 +1478,7 @@ static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state)
snd_pcm_playback_silence(substream, ULONG_MAX);
}
-static struct action_ops snd_pcm_action_reset = {
+static const struct action_ops snd_pcm_action_reset = {
.pre_action = snd_pcm_pre_reset,
.do_action = snd_pcm_do_reset,
.post_action = snd_pcm_post_reset
@@ -1522,7 +1522,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
}
-static struct action_ops snd_pcm_action_prepare = {
+static const struct action_ops snd_pcm_action_prepare = {
.pre_action = snd_pcm_pre_prepare,
.do_action = snd_pcm_do_prepare,
.post_action = snd_pcm_post_prepare
@@ -1618,7 +1618,7 @@ static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int sta
{
}
-static struct action_ops snd_pcm_action_drain_init = {
+static const struct action_ops snd_pcm_action_drain_init = {
.pre_action = snd_pcm_pre_drain_init,
.do_action = snd_pcm_do_drain_init,
.post_action = snd_pcm_post_drain_init
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 7354b8bed860..8db156b207f1 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/compat.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/initval.h>
@@ -189,7 +190,11 @@ odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
#ifdef CONFIG_COMPAT
-#define odev_ioctl_compat odev_ioctl
+static long odev_ioctl_compat(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return odev_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
+}
#else
#define odev_ioctl_compat NULL
#endif
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index b64f20deba90..13cfa815732d 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1962,7 +1962,7 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
* No restrictions so for a user client we can clear
* the whole fifo
*/
- if (client->type == USER_CLIENT)
+ if (client->type == USER_CLIENT && client->data.user.fifo)
snd_seq_fifo_clear(client->data.user.fifo);
}
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 7dfd0f429410..0bec02e89d51 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -142,8 +142,10 @@ static struct snd_seq_queue *queue_new(int owner, int locked)
static void queue_delete(struct snd_seq_queue *q)
{
/* stop and release the timer */
+ mutex_lock(&q->timer_mutex);
snd_seq_timer_stop(q->timer);
snd_seq_timer_close(q);
+ mutex_unlock(&q->timer_mutex);
/* wait until access free */
snd_use_lock_sync(&q->use_lock);
/* release resources... */
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 56e0f4cd3f82..3da2d48610b3 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -468,7 +468,7 @@ static int snd_virmidi_dev_unregister(struct snd_rawmidi *rmidi)
/*
*
*/
-static struct snd_rawmidi_global_ops snd_virmidi_global_ops = {
+static const struct snd_rawmidi_global_ops snd_virmidi_global_ops = {
.dev_register = snd_virmidi_dev_register,
.dev_unregister = snd_virmidi_dev_unregister,
};
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 31f40f03e5b7..cb25aded5349 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -73,7 +73,7 @@ struct snd_timer_user {
struct timespec tstamp; /* trigger tstamp */
wait_queue_head_t qchange_sleep;
struct fasync_struct *fasync;
- struct mutex tread_sem;
+ struct mutex ioctl_lock;
};
/* list of timers */
@@ -215,11 +215,13 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
slave->slave_id == master->slave_id) {
list_move_tail(&slave->open_list, &master->slave_list_head);
spin_lock_irq(&slave_active_lock);
+ spin_lock(&master->timer->lock);
slave->master = master;
slave->timer = master->timer;
if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
list_add_tail(&slave->active_list,
&master->slave_active_head);
+ spin_unlock(&master->timer->lock);
spin_unlock_irq(&slave_active_lock);
}
}
@@ -299,8 +301,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
return 0;
}
-static int _snd_timer_stop(struct snd_timer_instance *timeri,
- int keep_flag, int event);
+static int _snd_timer_stop(struct snd_timer_instance *timeri, int event);
/*
* close a timer instance
@@ -342,19 +343,22 @@ int snd_timer_close(struct snd_timer_instance *timeri)
spin_unlock_irq(&timer->lock);
mutex_lock(&register_mutex);
list_del(&timeri->open_list);
- if (timer && list_empty(&timer->open_list_head) &&
+ if (list_empty(&timer->open_list_head) &&
timer->hw.close)
timer->hw.close(timer);
/* remove slave links */
+ spin_lock_irq(&slave_active_lock);
+ spin_lock(&timer->lock);
list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
open_list) {
- spin_lock_irq(&slave_active_lock);
- _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
list_move_tail(&slave->open_list, &snd_timer_slave_list);
slave->master = NULL;
slave->timer = NULL;
- spin_unlock_irq(&slave_active_lock);
+ list_del_init(&slave->ack_list);
+ list_del_init(&slave->active_list);
}
+ spin_unlock(&timer->lock);
+ spin_unlock_irq(&slave_active_lock);
mutex_unlock(&register_mutex);
}
out:
@@ -441,9 +445,12 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri)
spin_lock_irqsave(&slave_active_lock, flags);
timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
- if (timeri->master)
+ if (timeri->master && timeri->timer) {
+ spin_lock(&timeri->timer->lock);
list_add_tail(&timeri->active_list,
&timeri->master->slave_active_head);
+ spin_unlock(&timeri->timer->lock);
+ }
spin_unlock_irqrestore(&slave_active_lock, flags);
return 1; /* delayed start */
}
@@ -476,8 +483,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
return result;
}
-static int _snd_timer_stop(struct snd_timer_instance * timeri,
- int keep_flag, int event)
+static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
{
struct snd_timer *timer;
unsigned long flags;
@@ -486,11 +492,11 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
return -ENXIO;
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
- if (!keep_flag) {
- spin_lock_irqsave(&slave_active_lock, flags);
- timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
- spin_unlock_irqrestore(&slave_active_lock, flags);
- }
+ spin_lock_irqsave(&slave_active_lock, flags);
+ timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+ list_del_init(&timeri->ack_list);
+ list_del_init(&timeri->active_list);
+ spin_unlock_irqrestore(&slave_active_lock, flags);
goto __end;
}
timer = timeri->timer;
@@ -511,9 +517,7 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
}
}
}
- if (!keep_flag)
- timeri->flags &=
- ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
+ timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
spin_unlock_irqrestore(&timer->lock, flags);
__end:
if (event != SNDRV_TIMER_EVENT_RESOLUTION)
@@ -532,7 +536,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
unsigned long flags;
int err;
- err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP);
+ err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP);
if (err < 0)
return err;
timer = timeri->timer;
@@ -576,7 +580,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
*/
int snd_timer_pause(struct snd_timer_instance * timeri)
{
- return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE);
+ return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE);
}
/*
@@ -694,7 +698,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
} else {
ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
if (--timer->running)
- list_del(&ti->active_list);
+ list_del_init(&ti->active_list);
}
if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
(ti->flags & SNDRV_TIMER_IFLG_FAST))
@@ -1253,7 +1257,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
return -ENOMEM;
spin_lock_init(&tu->qlock);
init_waitqueue_head(&tu->qchange_sleep);
- mutex_init(&tu->tread_sem);
+ mutex_init(&tu->ioctl_lock);
tu->ticks = 1;
tu->queue_size = 128;
tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
@@ -1273,8 +1277,10 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)
if (file->private_data) {
tu = file->private_data;
file->private_data = NULL;
+ mutex_lock(&tu->ioctl_lock);
if (tu->timeri)
snd_timer_close(tu->timeri);
+ mutex_unlock(&tu->ioctl_lock);
kfree(tu->queue);
kfree(tu->tqueue);
kfree(tu);
@@ -1512,7 +1518,6 @@ static int snd_timer_user_tselect(struct file *file,
int err = 0;
tu = file->private_data;
- mutex_lock(&tu->tread_sem);
if (tu->timeri) {
snd_timer_close(tu->timeri);
tu->timeri = NULL;
@@ -1556,7 +1561,6 @@ static int snd_timer_user_tselect(struct file *file,
}
__err:
- mutex_unlock(&tu->tread_sem);
return err;
}
@@ -1769,7 +1773,7 @@ enum {
SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
};
-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct snd_timer_user *tu;
@@ -1786,17 +1790,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
{
int xarg;
- mutex_lock(&tu->tread_sem);
- if (tu->timeri) { /* too late */
- mutex_unlock(&tu->tread_sem);
+ if (tu->timeri) /* too late */
return -EBUSY;
- }
- if (get_user(xarg, p)) {
- mutex_unlock(&tu->tread_sem);
+ if (get_user(xarg, p))
return -EFAULT;
- }
tu->tread = xarg ? 1 : 0;
- mutex_unlock(&tu->tread_sem);
return 0;
}
case SNDRV_TIMER_IOCTL_GINFO:
@@ -1829,6 +1827,18 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
return -ENOTTY;
}
+static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct snd_timer_user *tu = file->private_data;
+ long ret;
+
+ mutex_lock(&tu->ioctl_lock);
+ ret = __snd_timer_user_ioctl(file, cmd, arg);
+ mutex_unlock(&tu->ioctl_lock);
+ return ret;
+}
+
static int snd_timer_user_fasync(int fd, struct file * file, int on)
{
struct snd_timer_user *tu;
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 016e451ed506..75b74850c005 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -351,7 +351,7 @@ static void dummy_systimer_free(struct snd_pcm_substream *substream)
kfree(substream->runtime->private_data);
}
-static struct dummy_timer_ops dummy_systimer_ops = {
+static const struct dummy_timer_ops dummy_systimer_ops = {
.create = dummy_systimer_create,
.free = dummy_systimer_free,
.prepare = dummy_systimer_prepare,
@@ -475,7 +475,7 @@ static void dummy_hrtimer_free(struct snd_pcm_substream *substream)
kfree(dpcm);
}
-static struct dummy_timer_ops dummy_hrtimer_ops = {
+static const struct dummy_timer_ops dummy_hrtimer_ops = {
.create = dummy_hrtimer_create,
.free = dummy_hrtimer_free,
.prepare = dummy_hrtimer_prepare,
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index e92a6d949847..2a779c2f63ab 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -39,6 +39,7 @@ config SND_OXFW
* Mackie(Loud) d.2 pro/d.4 pro
* Mackie(Loud) U.420/U.420d
* TASCAM FireOne
+ * Stanton Controllers & Systems 1 Deck/Mixer
To compile this driver as a module, choose M here: the module
will be called snd-oxfw.
@@ -53,17 +54,6 @@ config SND_ISIGHT
To compile this driver as a module, choose M here: the module
will be called snd-isight.
-config SND_SCS1X
- tristate "Stanton Control System 1 MIDI"
- select SND_FIREWIRE_LIB
- help
- Say Y here to include support for the MIDI ports of the Stanton
- SCS.1d/SCS.1m DJ controllers. (SCS.1m audio is still handled
- by FFADO.)
-
- To compile this driver as a module, choose M here: the module
- will be called snd-scs1x.
-
config SND_FIREWORKS
tristate "Echo Fireworks board module support"
select SND_FIREWIRE_LIB
diff --git a/sound/firewire/Makefile b/sound/firewire/Makefile
index f5fb62551c60..003c09029786 100644
--- a/sound/firewire/Makefile
+++ b/sound/firewire/Makefile
@@ -1,13 +1,11 @@
snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \
fcp.o cmp.o amdtp-stream.o amdtp-am824.o
snd-isight-objs := isight.o
-snd-scs1x-objs := scs1x.o
obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o
obj-$(CONFIG_SND_DICE) += dice/
obj-$(CONFIG_SND_OXFW) += oxfw/
obj-$(CONFIG_SND_ISIGHT) += snd-isight.o
-obj-$(CONFIG_SND_SCS1X) += snd-scs1x.o
obj-$(CONFIG_SND_FIREWORKS) += fireworks/
obj-$(CONFIG_SND_BEBOB) += bebob/
obj-$(CONFIG_SND_FIREWIRE_DIGI00X) += digi00x/
diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c
index aee746187665..a4ff4e0bc0af 100644
--- a/sound/firewire/dice/dice-transaction.c
+++ b/sound/firewire/dice/dice-transaction.c
@@ -9,7 +9,7 @@
#include "dice.h"
-#define NOTIFICATION_TIMEOUT_MS 100
+#define NOTIFICATION_TIMEOUT_MS (2 * MSEC_PER_SEC)
static u64 get_subaddr(struct snd_dice *dice, enum snd_dice_addr_type type,
u64 offset)
@@ -65,16 +65,15 @@ static unsigned int get_clock_info(struct snd_dice *dice, __be32 *info)
static int set_clock_info(struct snd_dice *dice,
unsigned int rate, unsigned int source)
{
- unsigned int retries = 3;
unsigned int i;
__be32 info;
u32 mask;
u32 clock;
int err;
-retry:
+
err = get_clock_info(dice, &info);
if (err < 0)
- goto end;
+ return err;
clock = be32_to_cpu(info);
if (source != UINT_MAX) {
@@ -87,10 +86,8 @@ retry:
if (snd_dice_rates[i] == rate)
break;
}
- if (i == ARRAY_SIZE(snd_dice_rates)) {
- err = -EINVAL;
- goto end;
- }
+ if (i == ARRAY_SIZE(snd_dice_rates))
+ return -EINVAL;
mask = CLOCK_RATE_MASK;
clock &= ~mask;
@@ -104,25 +101,13 @@ retry:
err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
&info, 4);
if (err < 0)
- goto end;
+ return err;
- /* Timeout means it's invalid request, probably bus reset occurred. */
if (wait_for_completion_timeout(&dice->clock_accepted,
- msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) {
- if (retries-- == 0) {
- err = -ETIMEDOUT;
- goto end;
- }
+ msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0)
+ return -ETIMEDOUT;
- err = snd_dice_transaction_reinit(dice);
- if (err < 0)
- goto end;
-
- msleep(500); /* arbitrary */
- goto retry;
- }
-end:
- return err;
+ return 0;
}
int snd_dice_transaction_get_clock_source(struct snd_dice *dice,
@@ -331,39 +316,60 @@ int snd_dice_transaction_reinit(struct snd_dice *dice)
return register_notification_address(dice, false);
}
-int snd_dice_transaction_init(struct snd_dice *dice)
+static int get_subaddrs(struct snd_dice *dice)
{
- struct fw_address_handler *handler = &dice->notification_handler;
+ static const int min_values[10] = {
+ 10, 0x64 / 4,
+ 10, 0x18 / 4,
+ 10, 0x18 / 4,
+ 0, 0,
+ 0, 0,
+ };
__be32 *pointers;
+ __be32 version;
+ u32 data;
+ unsigned int i;
int err;
- /* Use the same way which dice_interface_check() does. */
- pointers = kmalloc(sizeof(__be32) * 10, GFP_KERNEL);
+ pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32),
+ GFP_KERNEL);
if (pointers == NULL)
return -ENOMEM;
- /* Get offsets for sub-addresses */
+ /*
+ * Check that the sub address spaces exist and are located inside the
+ * private address space. The minimum values are chosen so that all
+ * minimally required registers are included.
+ */
err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
- DICE_PRIVATE_SPACE,
- pointers, sizeof(__be32) * 10, 0);
+ DICE_PRIVATE_SPACE, pointers,
+ sizeof(__be32) * ARRAY_SIZE(min_values), 0);
if (err < 0)
goto end;
- /* Allocation callback in address space over host controller */
- handler->length = 4;
- handler->address_callback = dice_notification;
- handler->callback_data = dice;
- err = fw_core_add_address_handler(handler, &fw_high_memory_region);
- if (err < 0) {
- handler->callback_data = NULL;
- goto end;
+ for (i = 0; i < ARRAY_SIZE(min_values); ++i) {
+ data = be32_to_cpu(pointers[i]);
+ if (data < min_values[i] || data >= 0x40000) {
+ err = -ENODEV;
+ goto end;
+ }
}
- /* Register the address space */
- err = register_notification_address(dice, true);
- if (err < 0) {
- fw_core_remove_address_handler(handler);
- handler->callback_data = NULL;
+ /*
+ * Check that the implemented DICE driver specification major version
+ * number matches.
+ */
+ err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
+ DICE_PRIVATE_SPACE +
+ be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
+ &version, sizeof(version), 0);
+ if (err < 0)
+ goto end;
+
+ if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
+ dev_err(&dice->unit->device,
+ "unknown DICE version: 0x%08x\n", be32_to_cpu(version));
+ err = -ENODEV;
goto end;
}
@@ -380,3 +386,32 @@ end:
kfree(pointers);
return err;
}
+
+int snd_dice_transaction_init(struct snd_dice *dice)
+{
+ struct fw_address_handler *handler = &dice->notification_handler;
+ int err;
+
+ err = get_subaddrs(dice);
+ if (err < 0)
+ return err;
+
+ /* Allocation callback in address space over host controller */
+ handler->length = 4;
+ handler->address_callback = dice_notification;
+ handler->callback_data = dice;
+ err = fw_core_add_address_handler(handler, &fw_high_memory_region);
+ if (err < 0) {
+ handler->callback_data = NULL;
+ return err;
+ }
+
+ /* Register the address space */
+ err = register_notification_address(dice, true);
+ if (err < 0) {
+ fw_core_remove_address_handler(handler);
+ handler->callback_data = NULL;
+ }
+
+ return err;
+}
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c
index 0cda05c72f50..b91b3739c810 100644
--- a/sound/firewire/dice/dice.c
+++ b/sound/firewire/dice/dice.c
@@ -18,27 +18,14 @@ MODULE_LICENSE("GPL v2");
#define WEISS_CATEGORY_ID 0x00
#define LOUD_CATEGORY_ID 0x10
-static int dice_interface_check(struct fw_unit *unit)
+#define PROBE_DELAY_MS (2 * MSEC_PER_SEC)
+
+static int check_dice_category(struct fw_unit *unit)
{
- static const int min_values[10] = {
- 10, 0x64 / 4,
- 10, 0x18 / 4,
- 10, 0x18 / 4,
- 0, 0,
- 0, 0,
- };
struct fw_device *device = fw_parent_device(unit);
struct fw_csr_iterator it;
- int key, val, vendor = -1, model = -1, err;
- unsigned int category, i;
- __be32 *pointers;
- u32 value;
- __be32 version;
-
- pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32),
- GFP_KERNEL);
- if (pointers == NULL)
- return -ENOMEM;
+ int key, val, vendor = -1, model = -1;
+ unsigned int category;
/*
* Check that GUID and unit directory are constructed according to DICE
@@ -64,51 +51,10 @@ static int dice_interface_check(struct fw_unit *unit)
else
category = DICE_CATEGORY_ID;
if (device->config_rom[3] != ((vendor << 8) | category) ||
- device->config_rom[4] >> 22 != model) {
- err = -ENODEV;
- goto end;
- }
-
- /*
- * Check that the sub address spaces exist and are located inside the
- * private address space. The minimum values are chosen so that all
- * minimally required registers are included.
- */
- err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST,
- DICE_PRIVATE_SPACE, pointers,
- sizeof(__be32) * ARRAY_SIZE(min_values), 0);
- if (err < 0) {
- err = -ENODEV;
- goto end;
- }
- for (i = 0; i < ARRAY_SIZE(min_values); ++i) {
- value = be32_to_cpu(pointers[i]);
- if (value < min_values[i] || value >= 0x40000) {
- err = -ENODEV;
- goto end;
- }
- }
+ device->config_rom[4] >> 22 != model)
+ return -ENODEV;
- /*
- * Check that the implemented DICE driver specification major version
- * number matches.
- */
- err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
- DICE_PRIVATE_SPACE +
- be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
- &version, 4, 0);
- if (err < 0) {
- err = -ENODEV;
- goto end;
- }
- if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
- dev_err(&unit->device,
- "unknown DICE version: 0x%08x\n", be32_to_cpu(version));
- err = -ENODEV;
- goto end;
- }
-end:
- return err;
+ return 0;
}
static int highest_supported_mode_rate(struct snd_dice *dice,
@@ -231,6 +177,16 @@ static void dice_card_strings(struct snd_dice *dice)
strcpy(card->mixername, "DICE");
}
+static void dice_free(struct snd_dice *dice)
+{
+ snd_dice_stream_destroy_duplex(dice);
+ snd_dice_transaction_destroy(dice);
+ fw_unit_put(dice->unit);
+
+ mutex_destroy(&dice->mutex);
+ kfree(dice);
+}
+
/*
* This module releases the FireWire unit data after all ALSA character devices
* are released by applications. This is for releasing stream data or finishing
@@ -239,39 +195,21 @@ static void dice_card_strings(struct snd_dice *dice)
*/
static void dice_card_free(struct snd_card *card)
{
- struct snd_dice *dice = card->private_data;
-
- snd_dice_stream_destroy_duplex(dice);
- snd_dice_transaction_destroy(dice);
- fw_unit_put(dice->unit);
-
- mutex_destroy(&dice->mutex);
+ dice_free(card->private_data);
}
-static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
+static void do_registration(struct work_struct *work)
{
- struct snd_card *card;
- struct snd_dice *dice;
+ struct snd_dice *dice = container_of(work, struct snd_dice, dwork.work);
int err;
- err = dice_interface_check(unit);
- if (err < 0)
- goto end;
+ if (dice->registered)
+ return;
- err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE,
- sizeof(*dice), &card);
+ err = snd_card_new(&dice->unit->device, -1, NULL, THIS_MODULE, 0,
+ &dice->card);
if (err < 0)
- goto end;
-
- dice = card->private_data;
- dice->card = card;
- dice->unit = fw_unit_get(unit);
- card->private_free = dice_card_free;
-
- spin_lock_init(&dice->lock);
- mutex_init(&dice->mutex);
- init_completion(&dice->clock_accepted);
- init_waitqueue_head(&dice->hwdep_wait);
+ return;
err = snd_dice_transaction_init(dice);
if (err < 0)
@@ -283,56 +221,131 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
dice_card_strings(dice);
+ snd_dice_create_proc(dice);
+
err = snd_dice_create_pcm(dice);
if (err < 0)
goto error;
- err = snd_dice_create_hwdep(dice);
+ err = snd_dice_create_midi(dice);
if (err < 0)
goto error;
- snd_dice_create_proc(dice);
-
- err = snd_dice_create_midi(dice);
+ err = snd_dice_create_hwdep(dice);
if (err < 0)
goto error;
- err = snd_dice_stream_init_duplex(dice);
+ err = snd_card_register(dice->card);
if (err < 0)
goto error;
- err = snd_card_register(card);
+ /*
+ * After registered, dice instance can be released corresponding to
+ * releasing the sound card instance.
+ */
+ dice->card->private_free = dice_card_free;
+ dice->card->private_data = dice;
+ dice->registered = true;
+
+ return;
+error:
+ snd_dice_transaction_destroy(dice);
+ snd_card_free(dice->card);
+ dev_info(&dice->unit->device,
+ "Sound card registration failed: %d\n", err);
+}
+
+static void schedule_registration(struct snd_dice *dice)
+{
+ struct fw_card *fw_card = fw_parent_device(dice->unit)->card;
+ u64 now, delay;
+
+ now = get_jiffies_64();
+ delay = fw_card->reset_jiffies + msecs_to_jiffies(PROBE_DELAY_MS);
+
+ if (time_after64(delay, now))
+ delay -= now;
+ else
+ delay = 0;
+
+ mod_delayed_work(system_wq, &dice->dwork, delay);
+}
+
+static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
+{
+ struct snd_dice *dice;
+ int err;
+
+ err = check_dice_category(unit);
+ if (err < 0)
+ return -ENODEV;
+
+ /* Allocate this independent of sound card instance. */
+ dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL);
+ if (dice == NULL)
+ return -ENOMEM;
+
+ dice->unit = fw_unit_get(unit);
+ dev_set_drvdata(&unit->device, dice);
+
+ spin_lock_init(&dice->lock);
+ mutex_init(&dice->mutex);
+ init_completion(&dice->clock_accepted);
+ init_waitqueue_head(&dice->hwdep_wait);
+
+ err = snd_dice_stream_init_duplex(dice);
if (err < 0) {
- snd_dice_stream_destroy_duplex(dice);
- goto error;
+ dice_free(dice);
+ return err;
}
- dev_set_drvdata(&unit->device, dice);
-end:
- return err;
-error:
- snd_card_free(card);
- return err;
+ /* Allocate and register this sound card later. */
+ INIT_DEFERRABLE_WORK(&dice->dwork, do_registration);
+ schedule_registration(dice);
+
+ return 0;
}
static void dice_remove(struct fw_unit *unit)
{
struct snd_dice *dice = dev_get_drvdata(&unit->device);
- /* No need to wait for releasing card object in this context. */
- snd_card_free_when_closed(dice->card);
+ /*
+ * Confirm to stop the work for registration before the sound card is
+ * going to be released. The work is not scheduled again because bus
+ * reset handler is not called anymore.
+ */
+ cancel_delayed_work_sync(&dice->dwork);
+
+ if (dice->registered) {
+ /* No need to wait for releasing card object in this context. */
+ snd_card_free_when_closed(dice->card);
+ } else {
+ /* Don't forget this case. */
+ dice_free(dice);
+ }
}
static void dice_bus_reset(struct fw_unit *unit)
{
struct snd_dice *dice = dev_get_drvdata(&unit->device);
+ /* Postpone a workqueue for deferred registration. */
+ if (!dice->registered)
+ schedule_registration(dice);
+
/* The handler address register becomes initialized. */
snd_dice_transaction_reinit(dice);
- mutex_lock(&dice->mutex);
- snd_dice_stream_update_duplex(dice);
- mutex_unlock(&dice->mutex);
+ /*
+ * After registration, userspace can start packet streaming, then this
+ * code block works fine.
+ */
+ if (dice->registered) {
+ mutex_lock(&dice->mutex);
+ snd_dice_stream_update_duplex(dice);
+ mutex_unlock(&dice->mutex);
+ }
}
#define DICE_INTERFACE 0x000001
diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h
index 101550ac1a24..3d5ebebe61ea 100644
--- a/sound/firewire/dice/dice.h
+++ b/sound/firewire/dice/dice.h
@@ -45,6 +45,9 @@ struct snd_dice {
spinlock_t lock;
struct mutex mutex;
+ bool registered;
+ struct delayed_work dwork;
+
/* Offsets for sub-addresses */
unsigned int global_offset;
unsigned int rx_offset;
diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h
index c7cb7deafe48..96c4e0c6a9bd 100644
--- a/sound/firewire/fireworks/fireworks.h
+++ b/sound/firewire/fireworks/fireworks.h
@@ -86,8 +86,8 @@ struct snd_efw {
struct amdtp_stream rx_stream;
struct cmp_connection out_conn;
struct cmp_connection in_conn;
- atomic_t capture_substreams;
- atomic_t playback_substreams;
+ unsigned int capture_substreams;
+ unsigned int playback_substreams;
/* hardware metering parameters */
unsigned int phys_out;
diff --git a/sound/firewire/fireworks/fireworks_midi.c b/sound/firewire/fireworks/fireworks_midi.c
index fba01bbba456..3e8c4cf9fe1e 100644
--- a/sound/firewire/fireworks/fireworks_midi.c
+++ b/sound/firewire/fireworks/fireworks_midi.c
@@ -17,8 +17,10 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream)
if (err < 0)
goto end;
- atomic_inc(&efw->capture_substreams);
+ mutex_lock(&efw->mutex);
+ efw->capture_substreams++;
err = snd_efw_stream_start_duplex(efw, 0);
+ mutex_unlock(&efw->mutex);
if (err < 0)
snd_efw_stream_lock_release(efw);
@@ -35,8 +37,10 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream)
if (err < 0)
goto end;
- atomic_inc(&efw->playback_substreams);
+ mutex_lock(&efw->mutex);
+ efw->playback_substreams++;
err = snd_efw_stream_start_duplex(efw, 0);
+ mutex_unlock(&efw->mutex);
if (err < 0)
snd_efw_stream_lock_release(efw);
end:
@@ -47,8 +51,10 @@ static int midi_capture_close(struct snd_rawmidi_substream *substream)
{
struct snd_efw *efw = substream->rmidi->private_data;
- atomic_dec(&efw->capture_substreams);
+ mutex_lock(&efw->mutex);
+ efw->capture_substreams--;
snd_efw_stream_stop_duplex(efw);
+ mutex_unlock(&efw->mutex);
snd_efw_stream_lock_release(efw);
return 0;
@@ -58,8 +64,10 @@ static int midi_playback_close(struct snd_rawmidi_substream *substream)
{
struct snd_efw *efw = substream->rmidi->private_data;
- atomic_dec(&efw->playback_substreams);
+ mutex_lock(&efw->mutex);
+ efw->playback_substreams--;
snd_efw_stream_stop_duplex(efw);
+ mutex_unlock(&efw->mutex);
snd_efw_stream_lock_release(efw);
return 0;
diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c
index d27135bac513..f4fbf75ed198 100644
--- a/sound/firewire/fireworks/fireworks_pcm.c
+++ b/sound/firewire/fireworks/fireworks_pcm.c
@@ -251,8 +251,11 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
if (err < 0)
return err;
- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
- atomic_inc(&efw->capture_substreams);
+ if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+ mutex_lock(&efw->mutex);
+ efw->capture_substreams++;
+ mutex_unlock(&efw->mutex);
+ }
amdtp_am824_set_pcm_format(&efw->tx_stream, params_format(hw_params));
@@ -269,8 +272,11 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
if (err < 0)
return err;
- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
- atomic_inc(&efw->playback_substreams);
+ if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+ mutex_lock(&efw->mutex);
+ efw->playback_substreams++;
+ mutex_unlock(&efw->mutex);
+ }
amdtp_am824_set_pcm_format(&efw->rx_stream, params_format(hw_params));
@@ -281,8 +287,11 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
{
struct snd_efw *efw = substream->private_data;
- if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- atomic_dec(&efw->capture_substreams);
+ if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) {
+ mutex_lock(&efw->mutex);
+ efw->capture_substreams--;
+ mutex_unlock(&efw->mutex);
+ }
snd_efw_stream_stop_duplex(efw);
@@ -292,8 +301,11 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
{
struct snd_efw *efw = substream->private_data;
- if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- atomic_dec(&efw->playback_substreams);
+ if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) {
+ mutex_lock(&efw->mutex);
+ efw->playback_substreams--;
+ mutex_unlock(&efw->mutex);
+ }
snd_efw_stream_stop_duplex(efw);
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c
index 759f6e3ed44a..968a40a1beb2 100644
--- a/sound/firewire/fireworks/fireworks_stream.c
+++ b/sound/firewire/fireworks/fireworks_stream.c
@@ -209,16 +209,13 @@ end:
int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate)
{
struct amdtp_stream *master, *slave;
- atomic_t *slave_substreams;
+ unsigned int slave_substreams;
enum cip_flags sync_mode;
unsigned int curr_rate;
int err = 0;
- mutex_lock(&efw->mutex);
-
/* Need no substreams */
- if ((atomic_read(&efw->playback_substreams) == 0) &&
- (atomic_read(&efw->capture_substreams) == 0))
+ if (efw->playback_substreams == 0 && efw->capture_substreams == 0)
goto end;
err = get_sync_mode(efw, &sync_mode);
@@ -227,11 +224,11 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate)
if (sync_mode == CIP_SYNC_TO_DEVICE) {
master = &efw->tx_stream;
slave = &efw->rx_stream;
- slave_substreams = &efw->playback_substreams;
+ slave_substreams = efw->playback_substreams;
} else {
master = &efw->rx_stream;
slave = &efw->tx_stream;
- slave_substreams = &efw->capture_substreams;
+ slave_substreams = efw->capture_substreams;
}
/*
@@ -277,7 +274,7 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate)
}
/* start slave if needed */
- if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) {
+ if (slave_substreams > 0 && !amdtp_stream_running(slave)) {
err = start_stream(efw, slave, rate);
if (err < 0) {
dev_err(&efw->unit->device,
@@ -286,37 +283,32 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate)
}
}
end:
- mutex_unlock(&efw->mutex);
return err;
}
void snd_efw_stream_stop_duplex(struct snd_efw *efw)
{
struct amdtp_stream *master, *slave;
- atomic_t *master_substreams, *slave_substreams;
+ unsigned int master_substreams, slave_substreams;
if (efw->master == &efw->rx_stream) {
slave = &efw->tx_stream;
master = &efw->rx_stream;
- slave_substreams = &efw->capture_substreams;
- master_substreams = &efw->playback_substreams;
+ slave_substreams = efw->capture_substreams;
+ master_substreams = efw->playback_substreams;
} else {
slave = &efw->rx_stream;
master = &efw->tx_stream;
- slave_substreams = &efw->playback_substreams;
- master_substreams = &efw->capture_substreams;
+ slave_substreams = efw->playback_substreams;
+ master_substreams = efw->capture_substreams;
}
- mutex_lock(&efw->mutex);
-
- if (atomic_read(slave_substreams) == 0) {
+ if (slave_substreams == 0) {
stop_stream(efw, slave);
- if (atomic_read(master_substreams) == 0)
+ if (master_substreams == 0)
stop_stream(efw, master);
}
-
- mutex_unlock(&efw->mutex);
}
void snd_efw_stream_update_duplex(struct snd_efw *efw)
diff --git a/sound/firewire/oxfw/Makefile b/sound/firewire/oxfw/Makefile
index 06ff50f4e6c0..b474da7c6a1f 100644
--- a/sound/firewire/oxfw/Makefile
+++ b/sound/firewire/oxfw/Makefile
@@ -1,3 +1,3 @@
-snd-oxfw-objs := oxfw-command.o oxfw-stream.o oxfw-control.o oxfw-pcm.o \
- oxfw-proc.o oxfw-midi.o oxfw-hwdep.o oxfw.o
+snd-oxfw-objs := oxfw-command.o oxfw-stream.o oxfw-pcm.o oxfw-proc.o \
+ oxfw-midi.o oxfw-hwdep.o oxfw-spkr.o oxfw-scs1x.o oxfw.o
obj-$(CONFIG_SND_OXFW) += snd-oxfw.o
diff --git a/sound/firewire/oxfw/oxfw-scs1x.c b/sound/firewire/oxfw/oxfw-scs1x.c
new file mode 100644
index 000000000000..bb53eb35721b
--- /dev/null
+++ b/sound/firewire/oxfw/oxfw-scs1x.c
@@ -0,0 +1,406 @@
+/*
+ * oxfw-scs1x.c - a part of driver for OXFW970/971 based devices
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Copyright (c) 2015 Takashi Sakamoto <o-takashi@sakamocchi.jp>
+ *
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include "oxfw.h"
+
+#define HSS1394_ADDRESS 0xc007dedadadaULL
+#define HSS1394_MAX_PACKET_SIZE 64
+#define HSS1394_TAG_USER_DATA 0x00
+#define HSS1394_TAG_CHANGE_ADDRESS 0xf1
+
+struct fw_scs1x {
+ struct fw_address_handler hss_handler;
+ u8 input_escape_count;
+ struct snd_rawmidi_substream *input;
+
+ /* For MIDI playback. */
+ struct snd_rawmidi_substream *output;
+ bool output_idle;
+ u8 output_status;
+ u8 output_bytes;
+ bool output_escaped;
+ bool output_escape_high_nibble;
+ struct tasklet_struct tasklet;
+ wait_queue_head_t idle_wait;
+ u8 buffer[HSS1394_MAX_PACKET_SIZE];
+ bool transaction_running;
+ struct fw_transaction transaction;
+ struct fw_device *fw_dev;
+};
+
+static const u8 sysex_escape_prefix[] = {
+ 0xf0, /* SysEx begin */
+ 0x00, 0x01, 0x60, /* Stanton DJ */
+ 0x48, 0x53, 0x53, /* "HSS" */
+};
+
+static void midi_input_escaped_byte(struct snd_rawmidi_substream *stream,
+ u8 byte)
+{
+ u8 nibbles[2];
+
+ nibbles[0] = byte >> 4;
+ nibbles[1] = byte & 0x0f;
+ snd_rawmidi_receive(stream, nibbles, 2);
+}
+
+static void midi_input_byte(struct fw_scs1x *scs,
+ struct snd_rawmidi_substream *stream, u8 byte)
+{
+ const u8 eox = 0xf7;
+
+ if (scs->input_escape_count > 0) {
+ midi_input_escaped_byte(stream, byte);
+ scs->input_escape_count--;
+ if (scs->input_escape_count == 0)
+ snd_rawmidi_receive(stream, &eox, sizeof(eox));
+ } else if (byte == 0xf9) {
+ snd_rawmidi_receive(stream, sysex_escape_prefix,
+ ARRAY_SIZE(sysex_escape_prefix));
+ midi_input_escaped_byte(stream, 0x00);
+ midi_input_escaped_byte(stream, 0xf9);
+ scs->input_escape_count = 3;
+ } else {
+ snd_rawmidi_receive(stream, &byte, 1);
+ }
+}
+
+static void midi_input_packet(struct fw_scs1x *scs,
+ struct snd_rawmidi_substream *stream,
+ const u8 *data, unsigned int bytes)
+{
+ unsigned int i;
+ const u8 eox = 0xf7;
+
+ if (data[0] == HSS1394_TAG_USER_DATA) {
+ for (i = 1; i < bytes; ++i)
+ midi_input_byte(scs, stream, data[i]);
+ } else {
+ snd_rawmidi_receive(stream, sysex_escape_prefix,
+ ARRAY_SIZE(sysex_escape_prefix));
+ for (i = 0; i < bytes; ++i)
+ midi_input_escaped_byte(stream, data[i]);
+ snd_rawmidi_receive(stream, &eox, sizeof(eox));
+ }
+}
+
+static void handle_hss(struct fw_card *card, struct fw_request *request,
+ int tcode, int destination, int source, int generation,
+ unsigned long long offset, void *data, size_t length,
+ void *callback_data)
+{
+ struct fw_scs1x *scs = callback_data;
+ struct snd_rawmidi_substream *stream;
+ int rcode;
+
+ if (offset != scs->hss_handler.offset) {
+ rcode = RCODE_ADDRESS_ERROR;
+ goto end;
+ }
+ if (tcode != TCODE_WRITE_QUADLET_REQUEST &&
+ tcode != TCODE_WRITE_BLOCK_REQUEST) {
+ rcode = RCODE_TYPE_ERROR;
+ goto end;
+ }
+
+ if (length >= 1) {
+ stream = ACCESS_ONCE(scs->input);
+ if (stream)
+ midi_input_packet(scs, stream, data, length);
+ }
+
+ rcode = RCODE_COMPLETE;
+end:
+ fw_send_response(card, request, rcode);
+}
+
+static void scs_write_callback(struct fw_card *card, int rcode,
+ void *data, size_t length, void *callback_data)
+{
+ struct fw_scs1x *scs = callback_data;
+
+ if (rcode == RCODE_GENERATION)
+ ; /* TODO: retry this packet */
+
+ scs->transaction_running = false;
+ tasklet_schedule(&scs->tasklet);
+}
+
+static bool is_valid_running_status(u8 status)
+{
+ return status >= 0x80 && status <= 0xef;
+}
+
+static bool is_one_byte_cmd(u8 status)
+{
+ return status == 0xf6 ||
+ status >= 0xf8;
+}
+
+static bool is_two_bytes_cmd(u8 status)
+{
+ return (status >= 0xc0 && status <= 0xdf) ||
+ status == 0xf1 ||
+ status == 0xf3;
+}
+
+static bool is_three_bytes_cmd(u8 status)
+{
+ return (status >= 0x80 && status <= 0xbf) ||
+ (status >= 0xe0 && status <= 0xef) ||
+ status == 0xf2;
+}
+
+static bool is_invalid_cmd(u8 status)
+{
+ return status == 0xf4 ||
+ status == 0xf5 ||
+ status == 0xf9 ||
+ status == 0xfd;
+}
+
+static void scs_output_tasklet(unsigned long data)
+{
+ struct fw_scs1x *scs = (struct fw_scs1x *)data;
+ struct snd_rawmidi_substream *stream;
+ unsigned int i;
+ u8 byte;
+ int generation;
+
+ if (scs->transaction_running)
+ return;
+
+ stream = ACCESS_ONCE(scs->output);
+ if (!stream) {
+ scs->output_idle = true;
+ wake_up(&scs->idle_wait);
+ return;
+ }
+
+ i = scs->output_bytes;
+ for (;;) {
+ if (snd_rawmidi_transmit(stream, &byte, 1) != 1) {
+ scs->output_bytes = i;
+ scs->output_idle = true;
+ wake_up(&scs->idle_wait);
+ return;
+ }
+ /*
+ * Convert from real MIDI to what I think the device expects (no
+ * running status, one command per packet, unescaped SysExs).
+ */
+ if (scs->output_escaped && byte < 0x80) {
+ if (scs->output_escape_high_nibble) {
+ if (i < HSS1394_MAX_PACKET_SIZE) {
+ scs->buffer[i] = byte << 4;
+ scs->output_escape_high_nibble = false;
+ }
+ } else {
+ scs->buffer[i++] |= byte & 0x0f;
+ scs->output_escape_high_nibble = true;
+ }
+ } else if (byte < 0x80) {
+ if (i == 1) {
+ if (!is_valid_running_status(
+ scs->output_status))
+ continue;
+ scs->buffer[0] = HSS1394_TAG_USER_DATA;
+ scs->buffer[i++] = scs->output_status;
+ }
+ scs->buffer[i++] = byte;
+ if ((i == 3 && is_two_bytes_cmd(scs->output_status)) ||
+ (i == 4 && is_three_bytes_cmd(scs->output_status)))
+ break;
+ if (i == 1 + ARRAY_SIZE(sysex_escape_prefix) &&
+ !memcmp(scs->buffer + 1, sysex_escape_prefix,
+ ARRAY_SIZE(sysex_escape_prefix))) {
+ scs->output_escaped = true;
+ scs->output_escape_high_nibble = true;
+ i = 0;
+ }
+ if (i >= HSS1394_MAX_PACKET_SIZE)
+ i = 1;
+ } else if (byte == 0xf7) {
+ if (scs->output_escaped) {
+ if (i >= 1 && scs->output_escape_high_nibble &&
+ scs->buffer[0] !=
+ HSS1394_TAG_CHANGE_ADDRESS)
+ break;
+ } else {
+ if (i > 1 && scs->output_status == 0xf0) {
+ scs->buffer[i++] = 0xf7;
+ break;
+ }
+ }
+ i = 1;
+ scs->output_escaped = false;
+ } else if (!is_invalid_cmd(byte) && byte < 0xf8) {
+ i = 1;
+ scs->buffer[0] = HSS1394_TAG_USER_DATA;
+ scs->buffer[i++] = byte;
+ scs->output_status = byte;
+ scs->output_escaped = false;
+ if (is_one_byte_cmd(byte))
+ break;
+ }
+ }
+ scs->output_bytes = 1;
+ scs->output_escaped = false;
+
+ scs->transaction_running = true;
+ generation = scs->fw_dev->generation;
+ smp_rmb(); /* node_id vs. generation */
+ fw_send_request(scs->fw_dev->card, &scs->transaction,
+ TCODE_WRITE_BLOCK_REQUEST, scs->fw_dev->node_id,
+ generation, scs->fw_dev->max_speed, HSS1394_ADDRESS,
+ scs->buffer, i, scs_write_callback, scs);
+}
+
+static int midi_capture_open(struct snd_rawmidi_substream *stream)
+{
+ return 0;
+}
+
+static int midi_capture_close(struct snd_rawmidi_substream *stream)
+{
+ return 0;
+}
+
+static void midi_capture_trigger(struct snd_rawmidi_substream *stream, int up)
+{
+ struct fw_scs1x *scs = stream->rmidi->private_data;
+
+ if (up) {
+ scs->input_escape_count = 0;
+ ACCESS_ONCE(scs->input) = stream;
+ } else {
+ ACCESS_ONCE(scs->input) = NULL;
+ }
+}
+
+static struct snd_rawmidi_ops midi_capture_ops = {
+ .open = midi_capture_open,
+ .close = midi_capture_close,
+ .trigger = midi_capture_trigger,
+};
+
+static int midi_playback_open(struct snd_rawmidi_substream *stream)
+{
+ return 0;
+}
+
+static int midi_playback_close(struct snd_rawmidi_substream *stream)
+{
+ return 0;
+}
+
+static void midi_playback_trigger(struct snd_rawmidi_substream *stream, int up)
+{
+ struct fw_scs1x *scs = stream->rmidi->private_data;
+
+ if (up) {
+ scs->output_status = 0;
+ scs->output_bytes = 1;
+ scs->output_escaped = false;
+ scs->output_idle = false;
+
+ ACCESS_ONCE(scs->output) = stream;
+ tasklet_schedule(&scs->tasklet);
+ } else {
+ ACCESS_ONCE(scs->output) = NULL;
+ }
+}
+static void midi_playback_drain(struct snd_rawmidi_substream *stream)
+{
+ struct fw_scs1x *scs = stream->rmidi->private_data;
+
+ 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;
+ __be64 data;
+
+ data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
+ scs->hss_handler.offset);
+ return snd_fw_transaction(oxfw->unit, TCODE_WRITE_BLOCK_REQUEST,
+ HSS1394_ADDRESS, &data, sizeof(data), 0);
+}
+
+static void remove_scs1x(struct snd_rawmidi *rmidi)
+{
+ struct fw_scs1x *scs = rmidi->private_data;
+
+ fw_core_remove_address_handler(&scs->hss_handler);
+}
+
+void snd_oxfw_scs1x_update(struct snd_oxfw *oxfw)
+{
+ register_address(oxfw);
+}
+
+int snd_oxfw_scs1x_add(struct snd_oxfw *oxfw)
+{
+ struct snd_rawmidi *rmidi;
+ struct fw_scs1x *scs;
+ int err;
+
+ scs = kzalloc(sizeof(struct fw_scs1x), GFP_KERNEL);
+ if (scs == NULL)
+ return -ENOMEM;
+ scs->fw_dev = fw_parent_device(oxfw->unit);
+ oxfw->spec = scs;
+
+ /* Allocate own handler for imcoming asynchronous transaction. */
+ scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE;
+ scs->hss_handler.address_callback = handle_hss;
+ scs->hss_handler.callback_data = scs;
+ err = fw_core_add_address_handler(&scs->hss_handler,
+ &fw_high_memory_region);
+ if (err < 0)
+ return err;
+
+ err = register_address(oxfw);
+ if (err < 0)
+ goto err_allocated;
+
+ /* Use unique name for backward compatibility to scs1x module. */
+ err = snd_rawmidi_new(oxfw->card, "SCS.1x", 0, 1, 1, &rmidi);
+ if (err < 0)
+ goto err_allocated;
+ rmidi->private_data = scs;
+ rmidi->private_free = remove_scs1x;
+
+ snprintf(rmidi->name, sizeof(rmidi->name),
+ "%s MIDI", oxfw->card->shortname);
+
+ rmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT |
+ SNDRV_RAWMIDI_INFO_OUTPUT |
+ SNDRV_RAWMIDI_INFO_DUPLEX;
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+ &midi_capture_ops);
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+ &midi_playback_ops);
+
+ tasklet_init(&scs->tasklet, scs_output_tasklet, (unsigned long)scs);
+ init_waitqueue_head(&scs->idle_wait);
+ scs->output_idle = true;
+
+ return 0;
+err_allocated:
+ fw_core_remove_address_handler(&scs->hss_handler);
+ return err;
+}
diff --git a/sound/firewire/oxfw/oxfw-control.c b/sound/firewire/oxfw/oxfw-spkr.c
index 02a1cb90f20d..cb905af0660d 100644
--- a/sound/firewire/oxfw/oxfw-control.c
+++ b/sound/firewire/oxfw/oxfw-spkr.c
@@ -1,5 +1,5 @@
/*
- * oxfw_stream.c - a part of driver for OXFW970/971 based devices
+ * oxfw-spkr.c - a part of driver for OXFW970/971 based devices
*
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
* Licensed under the terms of the GNU General Public License, version 2.
@@ -7,6 +7,17 @@
#include "oxfw.h"
+struct fw_spkr {
+ bool mute;
+ s16 volume[6];
+ s16 volume_min;
+ s16 volume_max;
+
+ unsigned int mixer_channels;
+ u8 mute_fb_id;
+ u8 volume_fb_id;
+};
+
enum control_action { CTL_READ, CTL_WRITE };
enum control_attribute {
CTL_MIN = 0x02,
@@ -14,8 +25,8 @@ enum control_attribute {
CTL_CURRENT = 0x10,
};
-static int oxfw_mute_command(struct snd_oxfw *oxfw, bool *value,
- enum control_action action)
+static int avc_audio_feature_mute(struct fw_unit *unit, u8 fb_id, bool *value,
+ enum control_action action)
{
u8 *buf;
u8 response_ok;
@@ -35,7 +46,7 @@ static int oxfw_mute_command(struct snd_oxfw *oxfw, bool *value,
buf[1] = 0x08; /* audio unit 0 */
buf[2] = 0xb8; /* FUNCTION BLOCK */
buf[3] = 0x81; /* function block type: feature */
- buf[4] = oxfw->device_info->mute_fb_id; /* function block ID */
+ buf[4] = fb_id; /* function block ID */
buf[5] = 0x10; /* control attribute: current */
buf[6] = 0x02; /* selector length */
buf[7] = 0x00; /* audio channel number */
@@ -46,16 +57,16 @@ static int oxfw_mute_command(struct snd_oxfw *oxfw, bool *value,
else
buf[10] = *value ? 0x70 : 0x60;
- err = fcp_avc_transaction(oxfw->unit, buf, 11, buf, 11, 0x3fe);
+ err = fcp_avc_transaction(unit, buf, 11, buf, 11, 0x3fe);
if (err < 0)
goto error;
if (err < 11) {
- dev_err(&oxfw->unit->device, "short FCP response\n");
+ dev_err(&unit->device, "short FCP response\n");
err = -EIO;
goto error;
}
if (buf[0] != response_ok) {
- dev_err(&oxfw->unit->device, "mute command failed\n");
+ dev_err(&unit->device, "mute command failed\n");
err = -EIO;
goto error;
}
@@ -70,10 +81,10 @@ error:
return err;
}
-static int oxfw_volume_command(struct snd_oxfw *oxfw, s16 *value,
- unsigned int channel,
- enum control_attribute attribute,
- enum control_action action)
+static int avc_audio_feature_volume(struct fw_unit *unit, u8 fb_id, s16 *value,
+ unsigned int channel,
+ enum control_attribute attribute,
+ enum control_action action)
{
u8 *buf;
u8 response_ok;
@@ -93,7 +104,7 @@ static int oxfw_volume_command(struct snd_oxfw *oxfw, s16 *value,
buf[1] = 0x08; /* audio unit 0 */
buf[2] = 0xb8; /* FUNCTION BLOCK */
buf[3] = 0x81; /* function block type: feature */
- buf[4] = oxfw->device_info->volume_fb_id; /* function block ID */
+ buf[4] = fb_id; /* function block ID */
buf[5] = attribute; /* control attribute */
buf[6] = 0x02; /* selector length */
buf[7] = channel; /* audio channel number */
@@ -107,16 +118,16 @@ static int oxfw_volume_command(struct snd_oxfw *oxfw, s16 *value,
buf[11] = *value;
}
- err = fcp_avc_transaction(oxfw->unit, buf, 12, buf, 12, 0x3fe);
+ err = fcp_avc_transaction(unit, buf, 12, buf, 12, 0x3fe);
if (err < 0)
goto error;
if (err < 12) {
- dev_err(&oxfw->unit->device, "short FCP response\n");
+ dev_err(&unit->device, "short FCP response\n");
err = -EIO;
goto error;
}
if (buf[0] != response_ok) {
- dev_err(&oxfw->unit->device, "volume command failed\n");
+ dev_err(&unit->device, "volume command failed\n");
err = -EIO;
goto error;
}
@@ -131,75 +142,81 @@ error:
return err;
}
-static int oxfw_mute_get(struct snd_kcontrol *control,
+static int spkr_mute_get(struct snd_kcontrol *control,
struct snd_ctl_elem_value *value)
{
struct snd_oxfw *oxfw = control->private_data;
+ struct fw_spkr *spkr = oxfw->spec;
- value->value.integer.value[0] = !oxfw->mute;
+ value->value.integer.value[0] = !spkr->mute;
return 0;
}
-static int oxfw_mute_put(struct snd_kcontrol *control,
+static int spkr_mute_put(struct snd_kcontrol *control,
struct snd_ctl_elem_value *value)
{
struct snd_oxfw *oxfw = control->private_data;
+ struct fw_spkr *spkr = oxfw->spec;
bool mute;
int err;
mute = !value->value.integer.value[0];
- if (mute == oxfw->mute)
+ if (mute == spkr->mute)
return 0;
- err = oxfw_mute_command(oxfw, &mute, CTL_WRITE);
+ err = avc_audio_feature_mute(oxfw->unit, spkr->mute_fb_id, &mute,
+ CTL_WRITE);
if (err < 0)
return err;
- oxfw->mute = mute;
+ spkr->mute = mute;
return 1;
}
-static int oxfw_volume_info(struct snd_kcontrol *control,
+static int spkr_volume_info(struct snd_kcontrol *control,
struct snd_ctl_elem_info *info)
{
struct snd_oxfw *oxfw = control->private_data;
+ struct fw_spkr *spkr = oxfw->spec;
info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- info->count = oxfw->device_info->mixer_channels;
- info->value.integer.min = oxfw->volume_min;
- info->value.integer.max = oxfw->volume_max;
+ info->count = spkr->mixer_channels;
+ info->value.integer.min = spkr->volume_min;
+ info->value.integer.max = spkr->volume_max;
return 0;
}
static const u8 channel_map[6] = { 0, 1, 4, 5, 2, 3 };
-static int oxfw_volume_get(struct snd_kcontrol *control,
+static int spkr_volume_get(struct snd_kcontrol *control,
struct snd_ctl_elem_value *value)
{
struct snd_oxfw *oxfw = control->private_data;
+ struct fw_spkr *spkr = oxfw->spec;
unsigned int i;
- for (i = 0; i < oxfw->device_info->mixer_channels; ++i)
- value->value.integer.value[channel_map[i]] = oxfw->volume[i];
+ for (i = 0; i < spkr->mixer_channels; ++i)
+ value->value.integer.value[channel_map[i]] = spkr->volume[i];
return 0;
}
-static int oxfw_volume_put(struct snd_kcontrol *control,
+static int spkr_volume_put(struct snd_kcontrol *control,
struct snd_ctl_elem_value *value)
{
struct snd_oxfw *oxfw = control->private_data;
+ struct fw_spkr *spkr = oxfw->spec;
unsigned int i, changed_channels;
bool equal_values = true;
s16 volume;
int err;
- for (i = 0; i < oxfw->device_info->mixer_channels; ++i) {
- if (value->value.integer.value[i] < oxfw->volume_min ||
- value->value.integer.value[i] > oxfw->volume_max)
+ for (i = 0; i < spkr->mixer_channels; ++i) {
+ if (value->value.integer.value[i] < spkr->volume_min ||
+ value->value.integer.value[i] > spkr->volume_max)
return -EINVAL;
if (value->value.integer.value[i] !=
value->value.integer.value[0])
@@ -207,67 +224,86 @@ static int oxfw_volume_put(struct snd_kcontrol *control,
}
changed_channels = 0;
- for (i = 0; i < oxfw->device_info->mixer_channels; ++i)
+ for (i = 0; i < spkr->mixer_channels; ++i)
if (value->value.integer.value[channel_map[i]] !=
- oxfw->volume[i])
+ spkr->volume[i])
changed_channels |= 1 << (i + 1);
if (equal_values && changed_channels != 0)
changed_channels = 1 << 0;
- for (i = 0; i <= oxfw->device_info->mixer_channels; ++i) {
+ for (i = 0; i <= spkr->mixer_channels; ++i) {
volume = value->value.integer.value[channel_map[i ? i - 1 : 0]];
if (changed_channels & (1 << i)) {
- err = oxfw_volume_command(oxfw, &volume, i,
- CTL_CURRENT, CTL_WRITE);
+ err = avc_audio_feature_volume(oxfw->unit,
+ spkr->volume_fb_id, &volume,
+ i, CTL_CURRENT, CTL_WRITE);
if (err < 0)
return err;
}
if (i > 0)
- oxfw->volume[i - 1] = volume;
+ spkr->volume[i - 1] = volume;
}
return changed_channels != 0;
}
-int snd_oxfw_create_mixer(struct snd_oxfw *oxfw)
+int snd_oxfw_add_spkr(struct snd_oxfw *oxfw, bool is_lacie)
{
static const struct snd_kcontrol_new controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.info = snd_ctl_boolean_mono_info,
- .get = oxfw_mute_get,
- .put = oxfw_mute_put,
+ .get = spkr_mute_get,
+ .put = spkr_mute_put,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
- .info = oxfw_volume_info,
- .get = oxfw_volume_get,
- .put = oxfw_volume_put,
+ .info = spkr_volume_info,
+ .get = spkr_volume_get,
+ .put = spkr_volume_put,
},
};
+ struct fw_spkr *spkr;
unsigned int i, first_ch;
int err;
- err = oxfw_volume_command(oxfw, &oxfw->volume_min,
- 0, CTL_MIN, CTL_READ);
+ spkr = kzalloc(sizeof(struct fw_spkr), GFP_KERNEL);
+ if (spkr == NULL)
+ return -ENOMEM;
+ oxfw->spec = spkr;
+
+ if (is_lacie) {
+ spkr->mixer_channels = 1;
+ spkr->mute_fb_id = 0x01;
+ spkr->volume_fb_id = 0x01;
+ } else {
+ spkr->mixer_channels = 6;
+ spkr->mute_fb_id = 0x01;
+ spkr->volume_fb_id = 0x02;
+ }
+
+ err = avc_audio_feature_volume(oxfw->unit, spkr->volume_fb_id,
+ &spkr->volume_min, 0, CTL_MIN, CTL_READ);
if (err < 0)
return err;
- err = oxfw_volume_command(oxfw, &oxfw->volume_max,
- 0, CTL_MAX, CTL_READ);
+ err = avc_audio_feature_volume(oxfw->unit, spkr->volume_fb_id,
+ &spkr->volume_max, 0, CTL_MAX, CTL_READ);
if (err < 0)
return err;
- err = oxfw_mute_command(oxfw, &oxfw->mute, CTL_READ);
+ err = avc_audio_feature_mute(oxfw->unit, spkr->mute_fb_id, &spkr->mute,
+ CTL_READ);
if (err < 0)
return err;
- first_ch = oxfw->device_info->mixer_channels == 1 ? 0 : 1;
- for (i = 0; i < oxfw->device_info->mixer_channels; ++i) {
- err = oxfw_volume_command(oxfw, &oxfw->volume[i],
- first_ch + i, CTL_CURRENT, CTL_READ);
+ first_ch = spkr->mixer_channels == 1 ? 0 : 1;
+ for (i = 0; i < spkr->mixer_channels; ++i) {
+ err = avc_audio_feature_volume(oxfw->unit, spkr->volume_fb_id,
+ &spkr->volume[i], first_ch + i,
+ CTL_CURRENT, CTL_READ);
if (err < 0)
return err;
}
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index 588b93f20c2e..abedc2207261 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -19,6 +19,7 @@
#define VENDOR_BEHRINGER 0x001564
#define VENDOR_LACIE 0x00d04b
#define VENDOR_TASCAM 0x00022e
+#define OUI_STANTON 0x001260
#define MODEL_SATELLITE 0x00200f
@@ -29,6 +30,13 @@ MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("snd-firewire-speakers");
+MODULE_ALIAS("snd-scs1x");
+
+struct compat_info {
+ const char *driver_name;
+ const char *vendor_name;
+ const char *model_name;
+};
static bool detect_loud_models(struct fw_unit *unit)
{
@@ -59,6 +67,7 @@ static bool detect_loud_models(struct fw_unit *unit)
static int name_card(struct snd_oxfw *oxfw)
{
struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
+ const struct compat_info *info;
char vendor[24];
char model[32];
const char *d, *v, *m;
@@ -84,10 +93,12 @@ static int name_card(struct snd_oxfw *oxfw)
be32_to_cpus(&firmware);
/* to apply card definitions */
- if (oxfw->device_info) {
- d = oxfw->device_info->driver_name;
- v = oxfw->device_info->vendor_name;
- m = oxfw->device_info->model_name;
+ if (oxfw->entry->vendor_id == VENDOR_GRIFFIN ||
+ oxfw->entry->vendor_id == VENDOR_LACIE) {
+ info = (const struct compat_info *)oxfw->entry->driver_data;
+ d = info->driver_name;
+ v = info->vendor_name;
+ m = info->model_name;
} else {
d = "OXFW";
v = vendor;
@@ -129,16 +140,51 @@ static void oxfw_card_free(struct snd_card *card)
kfree(oxfw->rx_stream_formats[i]);
}
+ kfree(oxfw->spec);
mutex_destroy(&oxfw->mutex);
}
-static void detect_quirks(struct snd_oxfw *oxfw)
+static int detect_quirks(struct snd_oxfw *oxfw)
{
struct fw_device *fw_dev = fw_parent_device(oxfw->unit);
struct fw_csr_iterator it;
int key, val;
int vendor, model;
+ /*
+ * Add ALSA control elements for two models to keep compatibility to
+ * old firewire-speaker module.
+ */
+ if (oxfw->entry->vendor_id == VENDOR_GRIFFIN)
+ return snd_oxfw_add_spkr(oxfw, false);
+ if (oxfw->entry->vendor_id == VENDOR_LACIE)
+ return snd_oxfw_add_spkr(oxfw, true);
+
+ /*
+ * Stanton models supports asynchronous transactions for unique MIDI
+ * messages.
+ */
+ if (oxfw->entry->vendor_id == OUI_STANTON) {
+ /* No physical MIDI ports. */
+ oxfw->midi_input_ports = 0;
+ oxfw->midi_output_ports = 0;
+
+ /* Output stream exists but no data channels are useful. */
+ oxfw->has_output = false;
+
+ return snd_oxfw_scs1x_add(oxfw);
+ }
+
+ /*
+ * TASCAM FireOne has physical control and requires a pair of additional
+ * MIDI ports.
+ */
+ if (oxfw->entry->vendor_id == VENDOR_TASCAM) {
+ oxfw->midi_input_ports++;
+ oxfw->midi_output_ports++;
+ return 0;
+ }
+
/* Seek from Root Directory of Config ROM. */
vendor = model = 0;
fw_csr_iterator_init(&it, fw_dev->config_rom + 5);
@@ -156,24 +202,17 @@ static void detect_quirks(struct snd_oxfw *oxfw)
if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE)
oxfw->wrong_dbs = true;
- /*
- * TASCAM FireOne has physical control and requires a pair of additional
- * MIDI ports.
- */
- if (vendor == VENDOR_TASCAM) {
- oxfw->midi_input_ports++;
- oxfw->midi_output_ports++;
- }
+ return 0;
}
static int oxfw_probe(struct fw_unit *unit,
- const struct ieee1394_device_id *id)
+ const struct ieee1394_device_id *entry)
{
struct snd_card *card;
struct snd_oxfw *oxfw;
int err;
- if ((id->vendor_id == VENDOR_LOUD) && !detect_loud_models(unit))
+ if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit))
return -ENODEV;
err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE,
@@ -186,7 +225,7 @@ static int oxfw_probe(struct fw_unit *unit,
oxfw->card = card;
mutex_init(&oxfw->mutex);
oxfw->unit = fw_unit_get(unit);
- oxfw->device_info = (const struct device_info *)id->driver_data;
+ oxfw->entry = entry;
spin_lock_init(&oxfw->lock);
init_waitqueue_head(&oxfw->hwdep_wait);
@@ -194,21 +233,17 @@ static int oxfw_probe(struct fw_unit *unit,
if (err < 0)
goto error;
- detect_quirks(oxfw);
-
err = name_card(oxfw);
if (err < 0)
goto error;
- err = snd_oxfw_create_pcm(oxfw);
+ err = detect_quirks(oxfw);
if (err < 0)
goto error;
- if (oxfw->device_info) {
- err = snd_oxfw_create_mixer(oxfw);
- if (err < 0)
- goto error;
- }
+ err = snd_oxfw_create_pcm(oxfw);
+ if (err < 0)
+ goto error;
snd_oxfw_proc_init(oxfw);
@@ -257,6 +292,9 @@ static void oxfw_bus_reset(struct fw_unit *unit)
snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream);
mutex_unlock(&oxfw->mutex);
+
+ if (oxfw->entry->vendor_id == OUI_STANTON)
+ snd_oxfw_scs1x_update(oxfw);
}
static void oxfw_remove(struct fw_unit *unit)
@@ -267,22 +305,16 @@ static void oxfw_remove(struct fw_unit *unit)
snd_card_free_when_closed(oxfw->card);
}
-static const struct device_info griffin_firewave = {
+static const struct compat_info griffin_firewave = {
.driver_name = "FireWave",
.vendor_name = "Griffin",
.model_name = "FireWave",
- .mixer_channels = 6,
- .mute_fb_id = 0x01,
- .volume_fb_id = 0x02,
};
-static const struct device_info lacie_speakers = {
+static const struct compat_info lacie_speakers = {
.driver_name = "FWSpeakers",
.vendor_name = "LaCie",
.model_name = "FireWire Speakers",
- .mixer_channels = 1,
- .mute_fb_id = 0x01,
- .volume_fb_id = 0x01,
};
static const struct ieee1394_device_id oxfw_id_table[] = {
@@ -340,6 +372,20 @@ static const struct ieee1394_device_id oxfw_id_table[] = {
.vendor_id = VENDOR_TASCAM,
.model_id = 0x800007,
},
+ /* Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m) */
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_MODEL_ID,
+ .vendor_id = OUI_STANTON,
+ .model_id = 0x001000,
+ },
+ /* Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d) */
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+ IEEE1394_MATCH_MODEL_ID,
+ .vendor_id = OUI_STANTON,
+ .model_id = 0x002000,
+ },
{ }
};
MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table);
diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h
index 8392c424ad1d..9beecc214767 100644
--- a/sound/firewire/oxfw/oxfw.h
+++ b/sound/firewire/oxfw/oxfw.h
@@ -31,15 +31,6 @@
#include "../amdtp-am824.h"
#include "../cmp.h"
-struct device_info {
- const char *driver_name;
- const char *vendor_name;
- const char *model_name;
- unsigned int mixer_channels;
- u8 mute_fb_id;
- u8 volume_fb_id;
-};
-
/* This is an arbitrary number for convinience. */
#define SND_OXFW_STREAM_FORMAT_ENTRIES 10
struct snd_oxfw {
@@ -64,14 +55,12 @@ struct snd_oxfw {
unsigned int midi_input_ports;
unsigned int midi_output_ports;
- bool mute;
- s16 volume[6];
- s16 volume_min;
- s16 volume_max;
-
int dev_lock_count;
bool dev_lock_changed;
wait_queue_head_t hwdep_wait;
+
+ const struct ieee1394_device_id *entry;
+ void *spec;
};
/*
@@ -138,10 +127,12 @@ void snd_oxfw_stream_lock_release(struct snd_oxfw *oxfw);
int snd_oxfw_create_pcm(struct snd_oxfw *oxfw);
-int snd_oxfw_create_mixer(struct snd_oxfw *oxfw);
-
void snd_oxfw_proc_init(struct snd_oxfw *oxfw);
int snd_oxfw_create_midi(struct snd_oxfw *oxfw);
int snd_oxfw_create_hwdep(struct snd_oxfw *oxfw);
+
+int snd_oxfw_add_spkr(struct snd_oxfw *oxfw, bool is_lacie);
+int snd_oxfw_scs1x_add(struct snd_oxfw *oxfw);
+void snd_oxfw_scs1x_update(struct snd_oxfw *oxfw);
diff --git a/sound/firewire/scs1x.c b/sound/firewire/scs1x.c
deleted file mode 100644
index 2dba848a781f..000000000000
--- a/sound/firewire/scs1x.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Stanton Control System 1 MIDI driver
- *
- * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
- * Licensed under the terms of the GNU General Public License, version 2.
- */
-
-#include <linux/device.h>
-#include <linux/firewire.h>
-#include <linux/firewire-constants.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/mod_devicetable.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/rawmidi.h>
-#include "lib.h"
-
-#define OUI_STANTON 0x001260
-#define MODEL_SCS_1M 0x001000
-#define MODEL_SCS_1D 0x002000
-
-#define HSS1394_ADDRESS 0xc007dedadadaULL
-#define HSS1394_MAX_PACKET_SIZE 64
-
-#define HSS1394_TAG_USER_DATA 0x00
-#define HSS1394_TAG_CHANGE_ADDRESS 0xf1
-
-struct scs {
- struct snd_card *card;
- struct fw_unit *unit;
- struct fw_address_handler hss_handler;
- struct fw_transaction transaction;
- bool transaction_running;
- bool output_idle;
- u8 output_status;
- u8 output_bytes;
- bool output_escaped;
- bool output_escape_high_nibble;
- u8 input_escape_count;
- struct snd_rawmidi_substream *output;
- struct snd_rawmidi_substream *input;
- struct tasklet_struct tasklet;
- wait_queue_head_t idle_wait;
- u8 *buffer;
-};
-
-static const u8 sysex_escape_prefix[] = {
- 0xf0, /* SysEx begin */
- 0x00, 0x01, 0x60, /* Stanton DJ */
- 0x48, 0x53, 0x53, /* "HSS" */
-};
-
-static int scs_output_open(struct snd_rawmidi_substream *stream)
-{
- struct scs *scs = stream->rmidi->private_data;
-
- scs->output_status = 0;
- scs->output_bytes = 1;
- scs->output_escaped = false;
-
- return 0;
-}
-
-static int scs_output_close(struct snd_rawmidi_substream *stream)
-{
- return 0;
-}
-
-static void scs_output_trigger(struct snd_rawmidi_substream *stream, int up)
-{
- struct scs *scs = stream->rmidi->private_data;
-
- ACCESS_ONCE(scs->output) = up ? stream : NULL;
- if (up) {
- scs->output_idle = false;
- tasklet_schedule(&scs->tasklet);
- }
-}
-
-static void scs_write_callback(struct fw_card *card, int rcode,
- void *data, size_t length, void *callback_data)
-{
- struct scs *scs = callback_data;
-
- if (rcode == RCODE_GENERATION) {
- /* TODO: retry this packet */
- }
-
- scs->transaction_running = false;
- tasklet_schedule(&scs->tasklet);
-}
-
-static bool is_valid_running_status(u8 status)
-{
- return status >= 0x80 && status <= 0xef;
-}
-
-static bool is_one_byte_cmd(u8 status)
-{
- return status == 0xf6 ||
- status >= 0xf8;
-}
-
-static bool is_two_bytes_cmd(u8 status)
-{
- return (status >= 0xc0 && status <= 0xdf) ||
- status == 0xf1 ||
- status == 0xf3;
-}
-
-static bool is_three_bytes_cmd(u8 status)
-{
- return (status >= 0x80 && status <= 0xbf) ||
- (status >= 0xe0 && status <= 0xef) ||
- status == 0xf2;
-}
-
-static bool is_invalid_cmd(u8 status)
-{
- return status == 0xf4 ||
- status == 0xf5 ||
- status == 0xf9 ||
- status == 0xfd;
-}
-
-static void scs_output_tasklet(unsigned long data)
-{
- struct scs *scs = (void *)data;
- struct snd_rawmidi_substream *stream;
- unsigned int i;
- u8 byte;
- struct fw_device *dev;
- int generation;
-
- if (scs->transaction_running)
- return;
-
- stream = ACCESS_ONCE(scs->output);
- if (!stream) {
- scs->output_idle = true;
- wake_up(&scs->idle_wait);
- return;
- }
-
- i = scs->output_bytes;
- for (;;) {
- if (snd_rawmidi_transmit(stream, &byte, 1) != 1) {
- scs->output_bytes = i;
- scs->output_idle = true;
- wake_up(&scs->idle_wait);
- return;
- }
- /*
- * Convert from real MIDI to what I think the device expects (no
- * running status, one command per packet, unescaped SysExs).
- */
- if (scs->output_escaped && byte < 0x80) {
- if (scs->output_escape_high_nibble) {
- if (i < HSS1394_MAX_PACKET_SIZE) {
- scs->buffer[i] = byte << 4;
- scs->output_escape_high_nibble = false;
- }
- } else {
- scs->buffer[i++] |= byte & 0x0f;
- scs->output_escape_high_nibble = true;
- }
- } else if (byte < 0x80) {
- if (i == 1) {
- if (!is_valid_running_status(scs->output_status))
- continue;
- scs->buffer[0] = HSS1394_TAG_USER_DATA;
- scs->buffer[i++] = scs->output_status;
- }
- scs->buffer[i++] = byte;
- if ((i == 3 && is_two_bytes_cmd(scs->output_status)) ||
- (i == 4 && is_three_bytes_cmd(scs->output_status)))
- break;
- if (i == 1 + ARRAY_SIZE(sysex_escape_prefix) &&
- !memcmp(scs->buffer + 1, sysex_escape_prefix,
- ARRAY_SIZE(sysex_escape_prefix))) {
- scs->output_escaped = true;
- scs->output_escape_high_nibble = true;
- i = 0;
- }
- if (i >= HSS1394_MAX_PACKET_SIZE)
- i = 1;
- } else if (byte == 0xf7) {
- if (scs->output_escaped) {
- if (i >= 1 && scs->output_escape_high_nibble &&
- scs->buffer[0] != HSS1394_TAG_CHANGE_ADDRESS)
- break;
- } else {
- if (i > 1 && scs->output_status == 0xf0) {
- scs->buffer[i++] = 0xf7;
- break;
- }
- }
- i = 1;
- scs->output_escaped = false;
- } else if (!is_invalid_cmd(byte) &&
- byte < 0xf8) {
- i = 1;
- scs->buffer[0] = HSS1394_TAG_USER_DATA;
- scs->buffer[i++] = byte;
- scs->output_status = byte;
- scs->output_escaped = false;
- if (is_one_byte_cmd(byte))
- break;
- }
- }
- scs->output_bytes = 1;
- scs->output_escaped = false;
-
- scs->transaction_running = true;
- dev = fw_parent_device(scs->unit);
- generation = dev->generation;
- smp_rmb(); /* node_id vs. generation */
- fw_send_request(dev->card, &scs->transaction, TCODE_WRITE_BLOCK_REQUEST,
- dev->node_id, generation, dev->max_speed,
- HSS1394_ADDRESS, scs->buffer, i,
- scs_write_callback, scs);
-}
-
-static void scs_output_drain(struct snd_rawmidi_substream *stream)
-{
- struct scs *scs = stream->rmidi->private_data;
-
- wait_event(scs->idle_wait, scs->output_idle);
-}
-
-static struct snd_rawmidi_ops output_ops = {
- .open = scs_output_open,
- .close = scs_output_close,
- .trigger = scs_output_trigger,
- .drain = scs_output_drain,
-};
-
-static int scs_input_open(struct snd_rawmidi_substream *stream)
-{
- struct scs *scs = stream->rmidi->private_data;
-
- scs->input_escape_count = 0;
-
- return 0;
-}
-
-static int scs_input_close(struct snd_rawmidi_substream *stream)
-{
- return 0;
-}
-
-static void scs_input_trigger(struct snd_rawmidi_substream *stream, int up)
-{
- struct scs *scs = stream->rmidi->private_data;
-
- ACCESS_ONCE(scs->input) = up ? stream : NULL;
-}
-
-static void scs_input_escaped_byte(struct snd_rawmidi_substream *stream,
- u8 byte)
-{
- u8 nibbles[2];
-
- nibbles[0] = byte >> 4;
- nibbles[1] = byte & 0x0f;
- snd_rawmidi_receive(stream, nibbles, 2);
-}
-
-static void scs_input_midi_byte(struct scs *scs,
- struct snd_rawmidi_substream *stream,
- u8 byte)
-{
- if (scs->input_escape_count > 0) {
- scs_input_escaped_byte(stream, byte);
- scs->input_escape_count--;
- if (scs->input_escape_count == 0)
- snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1);
- } else if (byte == 0xf9) {
- snd_rawmidi_receive(stream, sysex_escape_prefix,
- ARRAY_SIZE(sysex_escape_prefix));
- scs_input_escaped_byte(stream, 0x00);
- scs_input_escaped_byte(stream, 0xf9);
- scs->input_escape_count = 3;
- } else {
- snd_rawmidi_receive(stream, &byte, 1);
- }
-}
-
-static void scs_input_packet(struct scs *scs,
- struct snd_rawmidi_substream *stream,
- const u8 *data, unsigned int bytes)
-{
- unsigned int i;
-
- if (data[0] == HSS1394_TAG_USER_DATA) {
- for (i = 1; i < bytes; ++i)
- scs_input_midi_byte(scs, stream, data[i]);
- } else {
- snd_rawmidi_receive(stream, sysex_escape_prefix,
- ARRAY_SIZE(sysex_escape_prefix));
- for (i = 0; i < bytes; ++i)
- scs_input_escaped_byte(stream, data[i]);
- snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1);
- }
-}
-
-static struct snd_rawmidi_ops input_ops = {
- .open = scs_input_open,
- .close = scs_input_close,
- .trigger = scs_input_trigger,
-};
-
-static int scs_create_midi(struct scs *scs)
-{
- struct snd_rawmidi *rmidi;
- int err;
-
- err = snd_rawmidi_new(scs->card, "SCS.1x", 0, 1, 1, &rmidi);
- if (err < 0)
- return err;
- snprintf(rmidi->name, sizeof(rmidi->name),
- "%s MIDI", scs->card->shortname);
- rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
- SNDRV_RAWMIDI_INFO_INPUT |
- SNDRV_RAWMIDI_INFO_DUPLEX;
- rmidi->private_data = scs;
- snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &output_ops);
- snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &input_ops);
-
- return 0;
-}
-
-static void handle_hss(struct fw_card *card, struct fw_request *request,
- int tcode, int destination, int source, int generation,
- unsigned long long offset, void *data, size_t length,
- void *callback_data)
-{
- struct scs *scs = callback_data;
- struct snd_rawmidi_substream *stream;
-
- if (offset != scs->hss_handler.offset) {
- fw_send_response(card, request, RCODE_ADDRESS_ERROR);
- return;
- }
- if (tcode != TCODE_WRITE_QUADLET_REQUEST &&
- tcode != TCODE_WRITE_BLOCK_REQUEST) {
- fw_send_response(card, request, RCODE_TYPE_ERROR);
- return;
- }
-
- if (length >= 1) {
- stream = ACCESS_ONCE(scs->input);
- if (stream)
- scs_input_packet(scs, stream, data, length);
- }
-
- fw_send_response(card, request, RCODE_COMPLETE);
-}
-
-static int scs_init_hss_address(struct scs *scs)
-{
- __be64 data;
- int err;
-
- data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
- scs->hss_handler.offset);
- err = snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
- HSS1394_ADDRESS, &data, 8, 0);
- if (err < 0)
- dev_err(&scs->unit->device, "HSS1394 communication failed\n");
-
- return err;
-}
-
-static void scs_card_free(struct snd_card *card)
-{
- struct scs *scs = card->private_data;
-
- fw_core_remove_address_handler(&scs->hss_handler);
- kfree(scs->buffer);
-}
-
-static int scs_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
-{
- struct fw_device *fw_dev = fw_parent_device(unit);
- struct snd_card *card;
- struct scs *scs;
- int err;
-
- err = snd_card_new(&unit->device, -16, NULL, THIS_MODULE,
- sizeof(*scs), &card);
- if (err < 0)
- return err;
-
- scs = card->private_data;
- scs->card = card;
- scs->unit = unit;
- tasklet_init(&scs->tasklet, scs_output_tasklet, (unsigned long)scs);
- init_waitqueue_head(&scs->idle_wait);
- scs->output_idle = true;
-
- scs->buffer = kmalloc(HSS1394_MAX_PACKET_SIZE, GFP_KERNEL);
- if (!scs->buffer) {
- err = -ENOMEM;
- goto err_card;
- }
-
- scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE;
- scs->hss_handler.address_callback = handle_hss;
- scs->hss_handler.callback_data = scs;
- err = fw_core_add_address_handler(&scs->hss_handler,
- &fw_high_memory_region);
- if (err < 0)
- goto err_buffer;
-
- card->private_free = scs_card_free;
-
- strcpy(card->driver, "SCS.1x");
- strcpy(card->shortname, "SCS.1x");
- fw_csr_string(unit->directory, CSR_MODEL,
- card->shortname, sizeof(card->shortname));
- snprintf(card->longname, sizeof(card->longname),
- "Stanton DJ %s (GUID %08x%08x) at %s, S%d",
- card->shortname, fw_dev->config_rom[3], fw_dev->config_rom[4],
- dev_name(&unit->device), 100 << fw_dev->max_speed);
- strcpy(card->mixername, card->shortname);
-
- err = scs_init_hss_address(scs);
- if (err < 0)
- goto err_card;
-
- err = scs_create_midi(scs);
- if (err < 0)
- goto err_card;
-
- err = snd_card_register(card);
- if (err < 0)
- goto err_card;
-
- dev_set_drvdata(&unit->device, scs);
-
- return 0;
-
-err_buffer:
- kfree(scs->buffer);
-err_card:
- snd_card_free(card);
- return err;
-}
-
-static void scs_update(struct fw_unit *unit)
-{
- struct scs *scs = dev_get_drvdata(&unit->device);
- int generation;
- __be64 data;
-
- data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
- scs->hss_handler.offset);
- generation = fw_parent_device(unit)->generation;
- smp_rmb(); /* node_id vs. generation */
- snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
- HSS1394_ADDRESS, &data, 8,
- FW_FIXED_GENERATION | generation);
-}
-
-static void scs_remove(struct fw_unit *unit)
-{
- struct scs *scs = dev_get_drvdata(&unit->device);
-
- snd_card_disconnect(scs->card);
-
- ACCESS_ONCE(scs->output) = NULL;
- ACCESS_ONCE(scs->input) = NULL;
-
- wait_event(scs->idle_wait, scs->output_idle);
-
- tasklet_kill(&scs->tasklet);
-
- snd_card_free_when_closed(scs->card);
-}
-
-static const struct ieee1394_device_id scs_id_table[] = {
- {
- .match_flags = IEEE1394_MATCH_VENDOR_ID |
- IEEE1394_MATCH_MODEL_ID,
- .vendor_id = OUI_STANTON,
- .model_id = MODEL_SCS_1M,
- },
- {
- .match_flags = IEEE1394_MATCH_VENDOR_ID |
- IEEE1394_MATCH_MODEL_ID,
- .vendor_id = OUI_STANTON,
- .model_id = MODEL_SCS_1D,
- },
- {}
-};
-MODULE_DEVICE_TABLE(ieee1394, scs_id_table);
-
-MODULE_DESCRIPTION("SCS.1x MIDI driver");
-MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
-MODULE_LICENSE("GPL v2");
-
-static struct fw_driver scs_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = KBUILD_MODNAME,
- .bus = &fw_bus_type,
- },
- .probe = scs_probe,
- .update = scs_update,
- .remove = scs_remove,
- .id_table = scs_id_table,
-};
-
-static int __init alsa_scs1x_init(void)
-{
- return driver_register(&scs_driver.driver);
-}
-
-static void __exit alsa_scs1x_exit(void)
-{
- driver_unregister(&scs_driver.driver);
-}
-
-module_init(alsa_scs1x_init);
-module_exit(alsa_scs1x_exit);
diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c
index 63215b17247c..548cc1e4114b 100644
--- a/sound/hda/ext/hdac_ext_controller.c
+++ b/sound/hda/ext/hdac_ext_controller.c
@@ -77,6 +77,12 @@ int snd_hdac_ext_bus_parse_capabilities(struct hdac_ext_bus *ebus)
ebus->spbcap = bus->remap_addr + offset;
break;
+ case AZX_DRSM_CAP_ID:
+ /* DMA resume capability found, handler function */
+ dev_dbg(bus->dev, "Found DRSM capability\n");
+ ebus->drsmcap = bus->remap_addr + offset;
+ break;
+
default:
dev_dbg(bus->dev, "Unknown capability %d\n", cur_cap);
break;
@@ -240,7 +246,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable)
int mask = (1 << AZX_MLCTL_CPA);
udelay(3);
- timeout = 50;
+ timeout = 150;
do {
val = readl(link->ml_addr + AZX_REG_ML_LCTL);
@@ -282,6 +288,27 @@ int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link)
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down);
/**
+ * snd_hdac_ext_bus_link_power_up_all -power up all hda link
+ * @ebus: HD-audio extended bus
+ */
+int snd_hdac_ext_bus_link_power_up_all(struct hdac_ext_bus *ebus)
+{
+ struct hdac_ext_link *hlink = NULL;
+ int ret;
+
+ list_for_each_entry(hlink, &ebus->hlink_list, list) {
+ snd_hdac_updatel(hlink->ml_addr,
+ AZX_REG_ML_LCTL, 0, AZX_MLCTL_SPA);
+ ret = check_hdac_link_power_active(hlink, true);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up_all);
+
+/**
* snd_hdac_ext_bus_link_power_down_all -power down all hda link
* @ebus: HD-audio extended bus
*/
diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c
index cb89ec7c8147..023cc4cad5c1 100644
--- a/sound/hda/ext/hdac_ext_stream.c
+++ b/sound/hda/ext/hdac_ext_stream.c
@@ -59,6 +59,10 @@ void snd_hdac_ext_stream_init(struct hdac_ext_bus *ebus,
AZX_SPB_MAXFIFO;
}
+ if (ebus->drsmcap)
+ stream->dpibr_addr = ebus->drsmcap + AZX_DRSM_BASE +
+ AZX_DRSM_INTERVAL * idx;
+
stream->decoupled = false;
snd_hdac_stream_init(bus, &stream->hstream, idx, direction, tag);
}
@@ -107,6 +111,7 @@ void snd_hdac_stream_free_all(struct hdac_ext_bus *ebus)
while (!list_empty(&bus->stream_list)) {
s = list_first_entry(&bus->stream_list, struct hdac_stream, list);
stream = stream_to_hdac_ext_stream(s);
+ snd_hdac_ext_stream_decouple(ebus, stream, false);
list_del(&s->list);
kfree(stream);
}
@@ -497,3 +502,70 @@ void snd_hdac_ext_stop_streams(struct hdac_ext_bus *ebus)
}
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stop_streams);
+
+/**
+ * snd_hdac_ext_stream_drsm_enable - enable DMA resume for a stream
+ * @ebus: HD-audio ext core bus
+ * @enable: flag to enable/disable DRSM
+ * @index: stream index for which DRSM need to be enabled
+ */
+void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus,
+ bool enable, int index)
+{
+ u32 mask = 0;
+ u32 register_mask = 0;
+ struct hdac_bus *bus = &ebus->bus;
+
+ if (!ebus->drsmcap) {
+ dev_err(bus->dev, "Address of DRSM capability is NULL");
+ return;
+ }
+
+ mask |= (1 << index);
+
+ register_mask = readl(ebus->drsmcap + AZX_REG_SPB_SPBFCCTL);
+
+ mask |= register_mask;
+
+ if (enable)
+ snd_hdac_updatel(ebus->drsmcap, AZX_REG_DRSM_CTL, 0, mask);
+ else
+ snd_hdac_updatel(ebus->drsmcap, AZX_REG_DRSM_CTL, mask, 0);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_drsm_enable);
+
+/**
+ * snd_hdac_ext_stream_set_dpibr - sets the dpibr value of a stream
+ * @ebus: HD-audio ext core bus
+ * @stream: hdac_ext_stream
+ * @value: dpib value to set
+ */
+int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus,
+ struct hdac_ext_stream *stream, u32 value)
+{
+ struct hdac_bus *bus = &ebus->bus;
+
+ if (!ebus->drsmcap) {
+ dev_err(bus->dev, "Address of DRSM capability is NULL");
+ return -EINVAL;
+ }
+
+ writel(value, stream->dpibr_addr);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_dpibr);
+
+/**
+ * snd_hdac_ext_stream_set_lpib - sets the lpib value of a stream
+ * @ebus: HD-audio ext core bus
+ * @stream: hdac_ext_stream
+ * @value: lpib value to set
+ */
+int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *stream, u32 value)
+{
+ snd_hdac_stream_writel(&stream->hstream, SD_LPIB, value);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_lpib);
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c
index 8fef1b8d1fd8..c50177fb469f 100644
--- a/sound/hda/hdac_i915.c
+++ b/sound/hda/hdac_i915.c
@@ -118,6 +118,72 @@ int snd_hdac_get_display_clk(struct hdac_bus *bus)
}
EXPORT_SYMBOL_GPL(snd_hdac_get_display_clk);
+/* There is a fixed mapping between audio pin node and display port
+ * on current Intel platforms:
+ * Pin Widget 5 - PORT B (port = 1 in i915 driver)
+ * Pin Widget 6 - PORT C (port = 2 in i915 driver)
+ * Pin Widget 7 - PORT D (port = 3 in i915 driver)
+ */
+static int pin2port(hda_nid_t pin_nid)
+{
+ return pin_nid - 4;
+}
+
+/**
+ * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate
+ * @bus: HDA core bus
+ * @nid: the pin widget NID
+ * @rate: the sample rate to set
+ *
+ * This function is supposed to be used only by a HD-audio controller
+ * driver that needs the interaction with i915 graphics.
+ *
+ * This function sets N/CTS value based on the given sample rate.
+ * Returns zero for success, or a negative error code.
+ */
+int snd_hdac_sync_audio_rate(struct hdac_bus *bus, hda_nid_t nid, int rate)
+{
+ struct i915_audio_component *acomp = bus->audio_component;
+
+ if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate)
+ return -ENODEV;
+ return acomp->ops->sync_audio_rate(acomp->dev, pin2port(nid), rate);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
+
+/**
+ * snd_hdac_acomp_get_eld - Get the audio state and ELD via component
+ * @bus: HDA core bus
+ * @nid: the pin widget NID
+ * @audio_enabled: the pointer to store the current audio state
+ * @buffer: the buffer pointer to store ELD bytes
+ * @max_bytes: the max bytes to be stored on @buffer
+ *
+ * This function is supposed to be used only by a HD-audio controller
+ * driver that needs the interaction with i915 graphics.
+ *
+ * This function queries the current state of the audio on the given
+ * digital port and fetches the ELD bytes onto the given buffer.
+ * It returns the number of bytes for the total ELD data, zero for
+ * invalid ELD, or a negative error code.
+ *
+ * The return size is the total bytes required for the whole ELD bytes,
+ * thus it may be over @max_bytes. If it's over @max_bytes, it implies
+ * that only a part of ELD bytes have been fetched.
+ */
+int snd_hdac_acomp_get_eld(struct hdac_bus *bus, hda_nid_t nid,
+ bool *audio_enabled, char *buffer, int max_bytes)
+{
+ struct i915_audio_component *acomp = bus->audio_component;
+
+ if (!acomp || !acomp->ops || !acomp->ops->get_eld)
+ return -ENODEV;
+
+ return acomp->ops->get_eld(acomp->dev, pin2port(nid), audio_enabled,
+ buffer, max_bytes);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld);
+
static int hdac_component_master_bind(struct device *dev)
{
struct i915_audio_component *acomp = hdac_acomp;
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index 4677037f0c8e..ef2a9afe9e19 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -39,7 +39,7 @@ static int snd_i2c_bit_readbytes(struct snd_i2c_device *device,
static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus,
unsigned short addr);
-static struct snd_i2c_ops snd_i2c_bit_ops = {
+static const struct snd_i2c_ops snd_i2c_bit_ops = {
.sendbytes = snd_i2c_bit_sendbytes,
.readbytes = snd_i2c_bit_readbytes,
.probeaddr = snd_i2c_bit_probeaddr,
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 48568fdf847f..4033fe58f0cf 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -240,7 +240,7 @@ config MSND_FIFOSIZE
menuconfig SOUND_OSS
tristate "OSS sound modules"
- depends on ISA_DMA_API && VIRT_TO_BUS
+ depends on ISA_DMA_API && (VIRT_TO_BUS || ARCH_RPC || ARCH_NETWINDER)
depends on !GENERIC_ISA_DMA_SUPPORT_BROKEN
help
OSS is the Open Sound System suite of sound card drivers. They make
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 1028fc8bdff5..2ce0022dbc46 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1219,7 +1219,7 @@ static struct ac97_pcm atiixp_pcm_defs[] = {
},
};
-static struct atiixp_dma_ops snd_atiixp_playback_dma_ops = {
+static const struct atiixp_dma_ops snd_atiixp_playback_dma_ops = {
.type = ATI_DMA_PLAYBACK,
.llp_offset = ATI_REG_OUT_DMA_LINKPTR,
.dt_cur = ATI_REG_OUT_DMA_DT_CUR,
@@ -1228,7 +1228,7 @@ static struct atiixp_dma_ops snd_atiixp_playback_dma_ops = {
.flush_dma = atiixp_out_flush_dma,
};
-static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
+static const struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
.type = ATI_DMA_CAPTURE,
.llp_offset = ATI_REG_IN_DMA_LINKPTR,
.dt_cur = ATI_REG_IN_DMA_DT_CUR,
@@ -1237,7 +1237,7 @@ static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
.flush_dma = atiixp_in_flush_dma,
};
-static struct atiixp_dma_ops snd_atiixp_spdif_dma_ops = {
+static const struct atiixp_dma_ops snd_atiixp_spdif_dma_ops = {
.type = ATI_DMA_SPDIF,
.llp_offset = ATI_REG_SPDF_DMA_LINKPTR,
.dt_cur = ATI_REG_SPDF_DMA_DT_CUR,
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 27ed678a46df..c534552963e7 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -970,7 +970,7 @@ static struct snd_pcm_ops snd_atiixp_capture_ops = {
.pointer = snd_atiixp_pcm_pointer,
};
-static struct atiixp_dma_ops snd_atiixp_playback_dma_ops = {
+static const struct atiixp_dma_ops snd_atiixp_playback_dma_ops = {
.type = ATI_DMA_PLAYBACK,
.llp_offset = ATI_REG_MODEM_OUT_DMA1_LINKPTR,
.dt_cur = ATI_REG_MODEM_OUT_DMA1_DT_CUR,
@@ -979,7 +979,7 @@ static struct atiixp_dma_ops snd_atiixp_playback_dma_ops = {
.flush_dma = atiixp_out_flush_dma,
};
-static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
+static const struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
.type = ATI_DMA_CAPTURE,
.llp_offset = ATI_REG_MODEM_IN_DMA_LINKPTR,
.dt_cur = ATI_REG_MODEM_IN_DMA_DT_CUR,
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 07a4acc99541..5e2ef0bb7057 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -2294,8 +2294,6 @@ snd_azf3328_free(struct snd_azf3328 *chip)
snd_azf3328_timer_stop(chip->timer);
snd_azf3328_gameport_free(chip);
- if (chip->irq >= 0)
- synchronize_irq(chip->irq);
__end_hw:
if (chip->irq >= 0)
free_irq(chip->irq, chip);
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
index 9c2dc911d8d7..27fa57da8dc4 100644
--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -402,7 +402,7 @@ static struct snd_pcm_ops snd_cs5535audio_capture_ops = {
.pointer = snd_cs5535audio_pcm_pointer,
};
-static struct cs5535audio_dma_ops snd_cs5535audio_playback_dma_ops = {
+static const struct cs5535audio_dma_ops snd_cs5535audio_playback_dma_ops = {
.type = CS5535AUDIO_DMA_PLAYBACK,
.enable_dma = cs5535audio_playback_enable_dma,
.disable_dma = cs5535audio_playback_disable_dma,
@@ -412,7 +412,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_playback_dma_ops = {
.read_dma_pntr = cs5535audio_playback_read_dma_pntr,
};
-static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = {
+static const struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = {
.type = CS5535AUDIO_DMA_CAPTURE,
.enable_dma = cs5535audio_capture_enable_dma,
.disable_dma = cs5535audio_capture_disable_dma,
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 759295aa8366..bade9b907b92 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -163,6 +163,7 @@ MODULE_PARM_DESC(radio_nr, "Radio device numbers");
* @cap_ctrl: capture control
*/
struct fm801 {
+ struct device *dev;
int irq;
unsigned long port;
@@ -190,7 +191,6 @@ struct fm801 {
struct snd_ac97 *ac97;
struct snd_ac97 *ac97_sec;
- struct pci_dev *pci;
struct snd_card *card;
struct snd_pcm *pcm;
struct snd_rawmidi *rmidi;
@@ -212,6 +212,20 @@ struct fm801 {
#endif
};
+/*
+ * IO accessors
+ */
+
+static inline void fm801_iowrite16(struct fm801 *chip, unsigned short offset, u16 value)
+{
+ outw(value, chip->port + offset);
+}
+
+static inline u16 fm801_ioread16(struct fm801 *chip, unsigned short offset)
+{
+ return inw(chip->port + offset);
+}
+
static const struct pci_device_id snd_fm801_ids[] = {
{ 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */
{ 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */
@@ -256,11 +270,11 @@ static int snd_fm801_update_bits(struct fm801 *chip, unsigned short reg,
unsigned short old, new;
spin_lock_irqsave(&chip->reg_lock, flags);
- old = inw(chip->port + reg);
+ old = fm801_ioread16(chip, reg);
new = (old & ~mask) | value;
change = old != new;
if (change)
- outw(new, chip->port + reg);
+ fm801_iowrite16(chip, reg, new);
spin_unlock_irqrestore(&chip->reg_lock, flags);
return change;
}
@@ -578,8 +592,9 @@ static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id)
}
if (chip->rmidi && (status & FM801_IRQ_MPU))
snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
- if (status & FM801_IRQ_VOLUME)
- ;/* TODO */
+ if (status & FM801_IRQ_VOLUME) {
+ /* TODO */
+ }
return IRQ_HANDLED;
}
@@ -700,6 +715,7 @@ static struct snd_pcm_ops snd_fm801_capture_ops = {
static int snd_fm801_pcm(struct fm801 *chip, int device)
{
+ struct pci_dev *pdev = to_pci_dev(chip->dev);
struct snd_pcm *pcm;
int err;
@@ -715,7 +731,7 @@ static int snd_fm801_pcm(struct fm801 *chip, int device)
chip->pcm = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci),
+ snd_dma_pci_data(pdev),
chip->multichannel ? 128*1024 : 64*1024, 128*1024);
return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
@@ -851,10 +867,11 @@ static int snd_fm801_get_single(struct snd_kcontrol *kcontrol,
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
int invert = (kcontrol->private_value >> 24) & 0xff;
+ long *value = ucontrol->value.integer.value;
- ucontrol->value.integer.value[0] = (inw(chip->port + reg) >> shift) & mask;
+ value[0] = (fm801_ioread16(chip, reg) >> shift) & mask;
if (invert)
- ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
+ value[0] = mask - value[0];
return 0;
}
@@ -907,14 +924,15 @@ static int snd_fm801_get_double(struct snd_kcontrol *kcontrol,
int shift_right = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff;
int invert = (kcontrol->private_value >> 24) & 0xff;
+ long *value = ucontrol->value.integer.value;
spin_lock_irq(&chip->reg_lock);
- ucontrol->value.integer.value[0] = (inw(chip->port + reg) >> shift_left) & mask;
- ucontrol->value.integer.value[1] = (inw(chip->port + reg) >> shift_right) & mask;
+ value[0] = (fm801_ioread16(chip, reg) >> shift_left) & mask;
+ value[1] = (fm801_ioread16(chip, reg) >> shift_right) & mask;
spin_unlock_irq(&chip->reg_lock);
if (invert) {
- ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
- ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
+ value[0] = mask - value[0];
+ value[1] = mask - value[1];
}
return 0;
}
@@ -1080,26 +1098,20 @@ static int wait_for_codec(struct fm801 *chip, unsigned int codec_id,
return -EIO;
}
-static int snd_fm801_chip_init(struct fm801 *chip, int resume)
+static int reset_codec(struct fm801 *chip)
{
- unsigned short cmdw;
-
- if (chip->tea575x_tuner & TUNER_ONLY)
- goto __ac97_ok;
-
/* codec cold reset + AC'97 warm reset */
fm801_writew(chip, CODEC_CTRL, (1 << 5) | (1 << 6));
fm801_readw(chip, CODEC_CTRL); /* flush posting data */
udelay(100);
fm801_writew(chip, CODEC_CTRL, 0);
- if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0)
- if (!resume) {
- dev_info(chip->card->dev,
- "Primary AC'97 codec not found, assume SF64-PCR (tuner-only)\n");
- chip->tea575x_tuner = 3 | TUNER_ONLY;
- goto __ac97_ok;
- }
+ return wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750));
+}
+
+static void snd_fm801_chip_multichannel_init(struct fm801 *chip)
+{
+ unsigned short cmdw;
if (chip->multichannel) {
if (chip->secondary_addr) {
@@ -1126,8 +1138,11 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
/* cause timeout problems */
wait_for_codec(chip, 0, AC97_VENDOR_ID1, msecs_to_jiffies(750));
}
+}
- __ac97_ok:
+static void snd_fm801_chip_init(struct fm801 *chip)
+{
+ unsigned short cmdw;
/* init volume */
fm801_writew(chip, PCM_VOL, 0x0808);
@@ -1148,11 +1163,8 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
/* interrupt clear */
fm801_writew(chip, IRQ_STATUS,
FM801_IRQ_PLAYBACK | FM801_IRQ_CAPTURE | FM801_IRQ_MPU);
-
- return 0;
}
-
static int snd_fm801_free(struct fm801 *chip)
{
unsigned short cmdw;
@@ -1165,6 +1177,8 @@ static int snd_fm801_free(struct fm801 *chip)
cmdw |= 0x00c3;
fm801_writew(chip, IRQ_MASK, cmdw);
+ devm_free_irq(chip->dev, chip->irq, chip);
+
__end_hw:
#ifdef CONFIG_SND_FM801_TEA575X_BOOL
if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
@@ -1201,13 +1215,29 @@ static int snd_fm801_create(struct snd_card *card,
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
chip->card = card;
- chip->pci = pci;
+ chip->dev = &pci->dev;
chip->irq = -1;
chip->tea575x_tuner = tea575x_tuner;
if ((err = pci_request_regions(pci, "FM801")) < 0)
return err;
chip->port = pci_resource_start(pci, 0);
- if ((tea575x_tuner & TUNER_ONLY) == 0) {
+
+ if (pci->revision >= 0xb1) /* FM801-AU */
+ chip->multichannel = 1;
+
+ if (!(chip->tea575x_tuner & TUNER_ONLY)) {
+ if (reset_codec(chip) < 0) {
+ dev_info(chip->card->dev,
+ "Primary AC'97 codec not found, assume SF64-PCR (tuner-only)\n");
+ chip->tea575x_tuner = 3 | TUNER_ONLY;
+ } else {
+ snd_fm801_chip_multichannel_init(chip);
+ }
+ }
+
+ snd_fm801_chip_init(chip);
+
+ if ((chip->tea575x_tuner & TUNER_ONLY) == 0) {
if (devm_request_irq(&pci->dev, pci->irq, snd_fm801_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
@@ -1218,13 +1248,6 @@ static int snd_fm801_create(struct snd_card *card,
pci_set_master(pci);
}
- if (pci->revision >= 0xb1) /* FM801-AU */
- chip->multichannel = 1;
-
- snd_fm801_chip_init(chip, 0);
- /* init might set tuner access method */
- tea575x_tuner = chip->tea575x_tuner;
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_fm801_free(chip);
return err;
@@ -1241,14 +1264,16 @@ static int snd_fm801_create(struct snd_card *card,
chip->tea.private_data = chip;
chip->tea.ops = &snd_fm801_tea_ops;
sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));
- if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 &&
- (tea575x_tuner & TUNER_TYPE_MASK) < 4) {
+ if ((chip->tea575x_tuner & TUNER_TYPE_MASK) > 0 &&
+ (chip->tea575x_tuner & TUNER_TYPE_MASK) < 4) {
if (snd_tea575x_init(&chip->tea, THIS_MODULE)) {
dev_err(card->dev, "TEA575x radio not found\n");
snd_fm801_free(chip);
return -ENODEV;
}
- } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) {
+ } else if ((chip->tea575x_tuner & TUNER_TYPE_MASK) == 0) {
+ unsigned int tuner_only = chip->tea575x_tuner & TUNER_ONLY;
+
/* autodetect tuner connection */
for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) {
chip->tea575x_tuner = tea575x_tuner;
@@ -1263,6 +1288,8 @@ static int snd_fm801_create(struct snd_card *card,
dev_err(card->dev, "TEA575x radio not found\n");
chip->tea575x_tuner = TUNER_DISABLED;
}
+
+ chip->tea575x_tuner |= tuner_only;
}
if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name,
@@ -1366,12 +1393,18 @@ static int snd_fm801_suspend(struct device *dev)
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- snd_pcm_suspend_all(chip->pcm);
- snd_ac97_suspend(chip->ac97);
- snd_ac97_suspend(chip->ac97_sec);
+
for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
- chip->saved_regs[i] = inw(chip->port + saved_regs[i]);
- /* FIXME: tea575x suspend */
+ chip->saved_regs[i] = fm801_ioread16(chip, saved_regs[i]);
+
+ if (chip->tea575x_tuner & TUNER_ONLY) {
+ /* FIXME: tea575x suspend */
+ } else {
+ snd_pcm_suspend_all(chip->pcm);
+ snd_ac97_suspend(chip->ac97);
+ snd_ac97_suspend(chip->ac97_sec);
+ }
+
return 0;
}
@@ -1381,11 +1414,23 @@ static int snd_fm801_resume(struct device *dev)
struct fm801 *chip = card->private_data;
int i;
- snd_fm801_chip_init(chip, 1);
- snd_ac97_resume(chip->ac97);
- snd_ac97_resume(chip->ac97_sec);
+ if (chip->tea575x_tuner & TUNER_ONLY) {
+ snd_fm801_chip_init(chip);
+ } else {
+ reset_codec(chip);
+ snd_fm801_chip_multichannel_init(chip);
+ snd_fm801_chip_init(chip);
+ snd_ac97_resume(chip->ac97);
+ snd_ac97_resume(chip->ac97_sec);
+ }
+
for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
- outw(chip->saved_regs[i], chip->port + saved_regs[i]);
+ fm801_iowrite16(chip, saved_regs[i], chip->saved_regs[i]);
+
+#ifdef CONFIG_SND_FM801_TEA575X_BOOL
+ if (!(chip->tea575x_tuner & TUNER_DISABLED))
+ snd_tea575x_set_freq(&chip->tea);
+#endif
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 22dbfa563919..37cf9cee9835 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -956,7 +956,7 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
status = azx_readb(chip, RIRBSTS);
if (status & RIRB_INT_MASK) {
if (status & RIRB_INT_RESPONSE) {
- if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY)
+ if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
udelay(80);
snd_hdac_bus_update_rirb(bus);
}
@@ -1050,16 +1050,10 @@ int azx_bus_init(struct azx *chip, const char *model,
if (chip->get_position[0] != azx_get_pos_lpib ||
chip->get_position[1] != azx_get_pos_lpib)
bus->core.use_posbuf = true;
- if (chip->bdl_pos_adj)
- bus->core.bdl_pos_adj = chip->bdl_pos_adj[chip->dev_index];
+ bus->core.bdl_pos_adj = chip->bdl_pos_adj;
if (chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)
bus->core.corbrp_self_clear = true;
- if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) {
- dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
- bus->needs_damn_long_delay = 1;
- }
-
if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY)
bus->core.align_bdle_4k = true;
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index 7b635d68cfe1..ec63bbf1ec6d 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -32,21 +32,25 @@
#define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */
#define AZX_DCAPS_SNOOP_MASK (3 << 10) /* snoop type mask */
#define AZX_DCAPS_SNOOP_OFF (1 << 12) /* snoop default off */
-#define AZX_DCAPS_RIRB_DELAY (1 << 13) /* Long delay in read loop */
-#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14) /* Put a delay before read */
+/* 13 unused */
+/* 14 unused */
#define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */
#define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */
-#define AZX_DCAPS_POSFIX_VIA (1 << 17) /* Use VIACOMBO as default */
+/* 17 unused */
#define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */
#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */
#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */
#define AZX_DCAPS_NO_ALIGN_BUFSIZE (1 << 21) /* no buffer size alignment */
/* 22 unused */
#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
-#define AZX_DCAPS_REVERSE_ASSIGN (1 << 24) /* Assign devices in reverse order */
+/* 24 unused */
#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
#define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */
+#ifdef CONFIG_SND_HDA_I915
#define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */
+#else
+#define AZX_DCAPS_I915_POWERWELL 0 /* NOP */
+#endif
#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */
#define AZX_DCAPS_NO_MSI64 (1 << 29) /* Stick to 32-bit MSIs */
#define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30) /* capture and playback use separate stream tag */
@@ -143,7 +147,7 @@ struct azx {
#endif
/* flags */
- const int *bdl_pos_adj;
+ int bdl_pos_adj;
int poll_count;
unsigned int running:1;
unsigned int single_cmd:1;
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 563984dd2562..bc2e08257c2e 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -253,6 +253,7 @@ int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
int mnl;
int i;
+ memset(e, 0, sizeof(*e));
e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
if (e->eld_ver != ELD_VER_CEA_861D &&
e->eld_ver != ELD_VER_PARTIAL) {
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index c6e8a651cea1..30c8efe0f80a 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -279,22 +279,6 @@ static struct nid_path *get_nid_path(struct hda_codec *codec,
}
/**
- * snd_hda_get_nid_path - get the path between the given NIDs
- * @codec: the HDA codec
- * @from_nid: the NID where the path start from
- * @to_nid: the NID where the path ends at
- *
- * Return the found nid_path object or NULL for error.
- * Passing 0 to either @from_nid or @to_nid behaves as a wildcard.
- */
-struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
- hda_nid_t from_nid, hda_nid_t to_nid)
-{
- return get_nid_path(codec, from_nid, to_nid, 0);
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_nid_path);
-
-/**
* snd_hda_get_path_idx - get the index number corresponding to the path
* instance
* @codec: the HDA codec
@@ -451,7 +435,7 @@ static bool __parse_nid_path(struct hda_codec *codec,
return true;
}
-/**
+/*
* snd_hda_parse_nid_path - parse the widget path from the given nid to
* the target nid
* @codec: the HDA codec
@@ -470,7 +454,7 @@ static bool __parse_nid_path(struct hda_codec *codec,
* with the negative of given value are excluded, only other paths are chosen.
* when @anchor_nid is zero, no special handling about path selection.
*/
-bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
+static bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
hda_nid_t to_nid, int anchor_nid,
struct nid_path *path)
{
@@ -481,7 +465,6 @@ bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
}
return false;
}
-EXPORT_SYMBOL_GPL(snd_hda_parse_nid_path);
/**
* snd_hda_add_new_path - parse the path between the given NIDs and
@@ -771,9 +754,6 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps;
unsigned int mask, val;
- if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
- return;
-
caps = query_amp_caps(codec, nid, dir);
val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
@@ -784,12 +764,22 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
update_amp(codec, nid, dir, idx, mask, val);
}
+static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
+ int dir, int idx, int idx_to_check,
+ bool enable)
+{
+ /* check whether the given amp is still used by others */
+ if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
+ return;
+ activate_amp(codec, nid, dir, idx, idx_to_check, enable);
+}
+
static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
int i, bool enable)
{
hda_nid_t nid = path->path[i];
init_amp(codec, nid, HDA_OUTPUT, 0);
- activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
+ check_and_activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
}
static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
@@ -817,9 +807,16 @@ static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
* when aa-mixer is available, we need to enable the path as well
*/
for (n = 0; n < nums; n++) {
- if (n != idx && (!add_aamix || conn[n] != spec->mixer_merge_nid))
- continue;
- activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
+ if (n != idx) {
+ if (conn[n] != spec->mixer_merge_nid)
+ continue;
+ /* when aamix is disabled, force to off */
+ if (!add_aamix) {
+ activate_amp(codec, nid, HDA_INPUT, n, n, false);
+ continue;
+ }
+ }
+ check_and_activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
}
}
@@ -1580,6 +1577,12 @@ static bool map_singles(struct hda_codec *codec, int outs,
return found;
}
+static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
+{
+ return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
+ spec->aamix_out_paths[2];
+}
+
/* create a new path including aamix if available, and return its index */
static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
{
@@ -2422,25 +2425,51 @@ static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
}
}
+/* re-initialize the output paths; only called from loopback_mixing_put() */
+static void update_output_paths(struct hda_codec *codec, int num_outs,
+ const int *paths)
+{
+ struct hda_gen_spec *spec = codec->spec;
+ struct nid_path *path;
+ int i;
+
+ for (i = 0; i < num_outs; i++) {
+ path = snd_hda_get_path_from_idx(codec, paths[i]);
+ if (path)
+ snd_hda_activate_path(codec, path, path->active,
+ spec->aamix_mode);
+ }
+}
+
static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct hda_gen_spec *spec = codec->spec;
+ const struct auto_pin_cfg *cfg = &spec->autocfg;
unsigned int val = ucontrol->value.enumerated.item[0];
if (val == spec->aamix_mode)
return 0;
spec->aamix_mode = val;
- update_aamix_paths(codec, val, spec->out_paths[0],
- spec->aamix_out_paths[0],
- spec->autocfg.line_out_type);
- update_aamix_paths(codec, val, spec->hp_paths[0],
- spec->aamix_out_paths[1],
- AUTO_PIN_HP_OUT);
- update_aamix_paths(codec, val, spec->speaker_paths[0],
- spec->aamix_out_paths[2],
- AUTO_PIN_SPEAKER_OUT);
+ if (has_aamix_out_paths(spec)) {
+ update_aamix_paths(codec, val, spec->out_paths[0],
+ spec->aamix_out_paths[0],
+ cfg->line_out_type);
+ update_aamix_paths(codec, val, spec->hp_paths[0],
+ spec->aamix_out_paths[1],
+ AUTO_PIN_HP_OUT);
+ update_aamix_paths(codec, val, spec->speaker_paths[0],
+ spec->aamix_out_paths[2],
+ AUTO_PIN_SPEAKER_OUT);
+ } else {
+ update_output_paths(codec, cfg->line_outs, spec->out_paths);
+ if (cfg->line_out_type != AUTO_PIN_HP_OUT)
+ update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
+ if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
+ update_output_paths(codec, cfg->speaker_outs,
+ spec->speaker_paths);
+ }
return 1;
}
@@ -2458,12 +2487,13 @@ static int create_loopback_mixing_ctl(struct hda_codec *codec)
if (!spec->mixer_nid)
return 0;
- if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
- spec->aamix_out_paths[2]))
- return 0;
if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
return -ENOMEM;
spec->have_aamix_ctl = 1;
+ /* if no explicit aamix path is present (e.g. for Realtek codecs),
+ * enable aamix as default -- just for compatibility
+ */
+ spec->aamix_mode = !has_aamix_out_paths(spec);
return 0;
}
@@ -5664,6 +5694,8 @@ static void init_aamix_paths(struct hda_codec *codec)
if (!spec->have_aamix_ctl)
return;
+ if (!has_aamix_out_paths(spec))
+ return;
update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
spec->aamix_out_paths[0],
spec->autocfg.line_out_type);
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 56e4139b9032..f66fc7e25e07 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -306,13 +306,8 @@ int snd_hda_gen_spec_init(struct hda_gen_spec *spec);
int snd_hda_gen_init(struct hda_codec *codec);
void snd_hda_gen_free(struct hda_codec *codec);
-struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
- hda_nid_t from_nid, hda_nid_t to_nid);
int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path);
struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx);
-bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
- hda_nid_t to_nid, int anchor_nid,
- struct nid_path *path);
struct nid_path *
snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
hda_nid_t to_nid, int anchor_nid);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 3b3658297070..c0bef11afa7e 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -284,13 +284,19 @@ enum {
(AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE)
/* quirks for Intel PCH */
-#define AZX_DCAPS_INTEL_PCH_NOPM \
+#define AZX_DCAPS_INTEL_PCH_BASE \
(AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\
- AZX_DCAPS_REVERSE_ASSIGN | AZX_DCAPS_SNOOP_TYPE(SCH))
+ AZX_DCAPS_SNOOP_TYPE(SCH))
+
+/* PCH up to IVB; no runtime PM */
+#define AZX_DCAPS_INTEL_PCH_NOPM \
+ (AZX_DCAPS_INTEL_PCH_BASE)
+/* PCH for HSW/BDW; with runtime PM */
#define AZX_DCAPS_INTEL_PCH \
- (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME)
+ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME)
+/* HSW HDMI */
#define AZX_DCAPS_INTEL_HASWELL \
(/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\
AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\
@@ -332,7 +338,7 @@ enum {
/* quirks for Nvidia */
#define AZX_DCAPS_PRESET_NVIDIA \
- (AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI | /*AZX_DCAPS_ALIGN_BUFSIZE |*/ \
+ (AZX_DCAPS_NO_MSI | /*AZX_DCAPS_ALIGN_BUFSIZE |*/ \
AZX_DCAPS_NO_64BIT | AZX_DCAPS_CORBRP_SELF_CLEAR |\
AZX_DCAPS_SNOOP_TYPE(NVIDIA))
@@ -649,7 +655,7 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
if (wallclk < (azx_dev->core.period_wallclk * 5) / 4 &&
pos % azx_dev->core.period_bytes > azx_dev->core.period_bytes / 2)
/* NG - it's below the first next period boundary */
- return chip->bdl_pos_adj[chip->dev_index] ? 0 : -1;
+ return chip->bdl_pos_adj ? 0 : -1;
azx_dev->core.start_wallclk += wallclk;
return 1; /* OK, it's fine */
}
@@ -719,7 +725,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
if (request_irq(chip->pci->irq, azx_interrupt,
chip->msi ? 0 : IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ chip->card->irq_descr, chip)) {
dev_err(chip->card->dev,
"unable to grab IRQ %d, disabling device\n",
chip->pci->irq);
@@ -1376,7 +1382,7 @@ static int check_position_fix(struct azx *chip, int fix)
}
/* Check VIA/ATI HD Audio Controller exist */
- if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) {
+ if (chip->driver_type == AZX_DRIVER_VIA) {
dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n");
return POS_FIX_VIACOMBO;
}
@@ -1539,6 +1545,26 @@ static void azx_probe_work(struct work_struct *work)
azx_probe_continue(&hda->chip);
}
+static int default_bdl_pos_adj(struct azx *chip)
+{
+ /* some exceptions: Atoms seem problematic with value 1 */
+ if (chip->pci->vendor == PCI_VENDOR_ID_INTEL) {
+ switch (chip->pci->device) {
+ case 0x0f04: /* Baytrail */
+ case 0x2284: /* Braswell */
+ return 32;
+ }
+ }
+
+ switch (chip->driver_type) {
+ case AZX_DRIVER_ICH:
+ case AZX_DRIVER_PCH:
+ return 1;
+ default:
+ return 32;
+ }
+}
+
/*
* constructor
*/
@@ -1592,18 +1618,10 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
chip->single_cmd = single_cmd;
azx_check_snoop_available(chip);
- if (bdl_pos_adj[dev] < 0) {
- switch (chip->driver_type) {
- case AZX_DRIVER_ICH:
- case AZX_DRIVER_PCH:
- bdl_pos_adj[dev] = 1;
- break;
- default:
- bdl_pos_adj[dev] = 32;
- break;
- }
- }
- chip->bdl_pos_adj = bdl_pos_adj;
+ if (bdl_pos_adj[dev] < 0)
+ chip->bdl_pos_adj = default_bdl_pos_adj(chip);
+ else
+ chip->bdl_pos_adj = bdl_pos_adj[dev];
err = azx_bus_init(chip, model[dev], &pci_hda_io_ops);
if (err < 0) {
@@ -1612,6 +1630,11 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
return err;
}
+ if (chip->driver_type == AZX_DRIVER_NVIDIA) {
+ dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
+ chip->bus.needs_damn_long_delay = 1;
+ }
+
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
dev_err(card->dev, "Error creating device [card]!\n");
@@ -2005,8 +2028,8 @@ static int azx_probe(struct pci_dev *pci,
#endif /* CONFIG_SND_HDA_PATCH_LOADER */
#ifndef CONFIG_SND_HDA_I915
- if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
- dev_err(card->dev, "Haswell must build in CONFIG_SND_HDA_I915\n");
+ if (CONTROLLER_IN_GPU(pci))
+ dev_err(card->dev, "Haswell/Broadwell HDMI/DP must build in CONFIG_SND_HDA_I915\n");
#endif
if (schedule_probe)
@@ -2203,10 +2226,10 @@ static const struct pci_device_id azx_ids[] = {
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
/* Poulsbo */
{ PCI_DEVICE(0x8086, 0x811b),
- .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
+ .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE },
/* Oaktrail */
{ PCI_DEVICE(0x8086, 0x080a),
- .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
+ .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE },
/* BayTrail */
{ PCI_DEVICE(0x8086, 0x0f04),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BAYTRAIL },
@@ -2318,8 +2341,7 @@ static const struct pci_device_id azx_ids[] = {
{ PCI_DEVICE(0x1002, 0xaae8),
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
/* VIA VT8251/VT8237A */
- { PCI_DEVICE(0x1106, 0x3288),
- .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA },
+ { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
/* VIA GFX VT7122/VX900 */
{ PCI_DEVICE(0x1106, 0x9170), .driver_data = AZX_DRIVER_GENERIC },
/* VIA GFX VT6122/VX11 */
@@ -2353,14 +2375,12 @@ static const struct pci_device_id azx_ids[] = {
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
- AZX_DCAPS_NO_64BIT |
- AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
+ AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB },
#else
/* this entry seems still valid -- i.e. without emu20kx chip */
{ PCI_DEVICE(0x1102, 0x0009),
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
- AZX_DCAPS_NO_64BIT |
- AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
+ AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB },
#endif
/* CM8888 */
{ PCI_DEVICE(0x13f6, 0x5011),
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index 58c0aad37284..17fd81736d3d 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -464,6 +464,8 @@ static int hda_tegra_create(struct snd_card *card,
if (err < 0)
return err;
+ chip->bus.needs_damn_long_delay = 1;
+
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
dev_err(card->dev, "Error creating device\n");
@@ -481,8 +483,7 @@ MODULE_DEVICE_TABLE(of, hda_tegra_match);
static int hda_tegra_probe(struct platform_device *pdev)
{
- const unsigned int driver_flags = AZX_DCAPS_RIRB_DELAY |
- AZX_DCAPS_CORBRP_SELF_CLEAR;
+ const unsigned int driver_flags = AZX_DCAPS_CORBRP_SELF_CLEAR;
struct snd_card *card;
struct azx *chip;
struct hda_tegra *hda;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index ef198903c0c3..6122b8ca872f 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -901,6 +901,9 @@ static int patch_conexant_auto(struct hda_codec *codec)
snd_hda_pick_fixup(codec, cxt5051_fixup_models,
cxt5051_fixups, cxt_fixups);
break;
+ case 0x14f150f2:
+ codec->power_save_node = 1;
+ /* Fall through */
default:
codec->pin_amp_workaround = 1;
snd_hda_pick_fixup(codec, cxt5066_fixup_models,
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 4b6fb668c91c..426a29a1c19b 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -51,8 +51,10 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
#define is_broadwell(codec) ((codec)->core.vendor_id == 0x80862808)
#define is_skylake(codec) ((codec)->core.vendor_id == 0x80862809)
#define is_broxton(codec) ((codec)->core.vendor_id == 0x8086280a)
+#define is_kabylake(codec) ((codec)->core.vendor_id == 0x8086280b)
#define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \
- || is_skylake(codec) || is_broxton(codec))
+ || is_skylake(codec) || is_broxton(codec) \
+ || is_kabylake(codec))
#define is_valleyview(codec) ((codec)->core.vendor_id == 0x80862882)
#define is_cherryview(codec) ((codec)->core.vendor_id == 0x80862883)
@@ -83,6 +85,7 @@ struct hdmi_spec_per_pin {
struct mutex lock;
struct delayed_work work;
struct snd_kcontrol *eld_ctl;
+ struct snd_jack *acomp_jack; /* jack via audio component */
int repoll_count;
bool setup; /* the stream has been set up by prepare callback */
int channels; /* current number of channels */
@@ -150,8 +153,15 @@ struct hdmi_spec {
/* i915/powerwell (Haswell+/Valleyview+) specific */
struct i915_audio_component_audio_ops i915_audio_ops;
+ bool i915_bound; /* was i915 bound in this driver? */
};
+#ifdef CONFIG_SND_HDA_I915
+#define codec_has_acomp(codec) \
+ ((codec)->bus->core.audio_component != NULL)
+#else
+#define codec_has_acomp(codec) false
+#endif
struct hdmi_audio_infoframe {
u8 type; /* 0x84 */
@@ -1530,7 +1540,59 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
return 0;
}
-static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
+/* update per_pin ELD from the given new ELD;
+ * setup info frame and notification accordingly
+ */
+static void update_eld(struct hda_codec *codec,
+ struct hdmi_spec_per_pin *per_pin,
+ struct hdmi_eld *eld)
+{
+ struct hdmi_eld *pin_eld = &per_pin->sink_eld;
+ bool old_eld_valid = pin_eld->eld_valid;
+ bool eld_changed;
+
+ if (eld->eld_valid)
+ snd_hdmi_show_eld(codec, &eld->info);
+
+ eld_changed = (pin_eld->eld_valid != eld->eld_valid);
+ if (eld->eld_valid && pin_eld->eld_valid)
+ if (pin_eld->eld_size != eld->eld_size ||
+ memcmp(pin_eld->eld_buffer, eld->eld_buffer,
+ eld->eld_size) != 0)
+ eld_changed = true;
+
+ pin_eld->eld_valid = eld->eld_valid;
+ pin_eld->eld_size = eld->eld_size;
+ if (eld->eld_valid)
+ memcpy(pin_eld->eld_buffer, eld->eld_buffer, eld->eld_size);
+ pin_eld->info = eld->info;
+
+ /*
+ * Re-setup pin and infoframe. This is needed e.g. when
+ * - sink is first plugged-in
+ * - transcoder can change during stream playback on Haswell
+ * and this can make HW reset converter selection on a pin.
+ */
+ if (eld->eld_valid && !old_eld_valid && per_pin->setup) {
+ if (is_haswell_plus(codec) || is_valleyview_plus(codec)) {
+ intel_verify_pin_cvt_connect(codec, per_pin);
+ intel_not_share_assigned_cvt(codec, per_pin->pin_nid,
+ per_pin->mux_idx);
+ }
+
+ hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
+ }
+
+ if (eld_changed)
+ snd_ctl_notify(codec->card,
+ SNDRV_CTL_EVENT_MASK_VALUE |
+ SNDRV_CTL_EVENT_MASK_INFO,
+ &per_pin->eld_ctl->id);
+}
+
+/* update ELD and jack state via HD-audio verbs */
+static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
+ int repoll)
{
struct hda_jack_tbl *jack;
struct hda_codec *codec = per_pin->codec;
@@ -1547,9 +1609,8 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
* the unsolicited response to avoid custom WARs.
*/
int present;
- bool update_eld = false;
- bool eld_changed = false;
bool ret;
+ bool do_repoll = false;
snd_hda_power_up_pm(codec);
present = snd_hda_pin_sense(codec, pin_nid);
@@ -1570,66 +1631,19 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
&eld->eld_size) < 0)
eld->eld_valid = false;
else {
- memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld));
if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer,
eld->eld_size) < 0)
eld->eld_valid = false;
}
-
- if (eld->eld_valid) {
- snd_hdmi_show_eld(codec, &eld->info);
- update_eld = true;
- }
- else if (repoll) {
- schedule_delayed_work(&per_pin->work,
- msecs_to_jiffies(300));
- goto unlock;
- }
+ if (!eld->eld_valid && repoll)
+ do_repoll = true;
}
- if (pin_eld->eld_valid != eld->eld_valid)
- eld_changed = true;
-
- if (pin_eld->eld_valid && !eld->eld_valid)
- update_eld = true;
-
- if (update_eld) {
- bool old_eld_valid = pin_eld->eld_valid;
- pin_eld->eld_valid = eld->eld_valid;
- if (pin_eld->eld_size != eld->eld_size ||
- memcmp(pin_eld->eld_buffer, eld->eld_buffer,
- eld->eld_size) != 0) {
- memcpy(pin_eld->eld_buffer, eld->eld_buffer,
- eld->eld_size);
- eld_changed = true;
- }
- pin_eld->eld_size = eld->eld_size;
- pin_eld->info = eld->info;
-
- /*
- * Re-setup pin and infoframe. This is needed e.g. when
- * - sink is first plugged-in (infoframe is not set up if !monitor_present)
- * - transcoder can change during stream playback on Haswell
- * and this can make HW reset converter selection on a pin.
- */
- if (eld->eld_valid && !old_eld_valid && per_pin->setup) {
- if (is_haswell_plus(codec) ||
- is_valleyview_plus(codec)) {
- intel_verify_pin_cvt_connect(codec, per_pin);
- intel_not_share_assigned_cvt(codec, pin_nid,
- per_pin->mux_idx);
- }
-
- hdmi_setup_audio_infoframe(codec, per_pin,
- per_pin->non_pcm);
- }
- }
+ if (do_repoll)
+ schedule_delayed_work(&per_pin->work, msecs_to_jiffies(300));
+ else
+ update_eld(codec, per_pin, eld);
- if (eld_changed)
- snd_ctl_notify(codec->card,
- SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
- &per_pin->eld_ctl->id);
- unlock:
ret = !repoll || !pin_eld->monitor_present || pin_eld->eld_valid;
jack = snd_hda_jack_tbl_get(codec, pin_nid);
@@ -1641,6 +1655,54 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
return ret;
}
+/* update ELD and jack state via audio component */
+static void sync_eld_via_acomp(struct hda_codec *codec,
+ struct hdmi_spec_per_pin *per_pin)
+{
+ struct hdmi_spec *spec = codec->spec;
+ struct hdmi_eld *eld = &spec->temp_eld;
+ int size;
+
+ mutex_lock(&per_pin->lock);
+ size = snd_hdac_acomp_get_eld(&codec->bus->core, per_pin->pin_nid,
+ &eld->monitor_present, eld->eld_buffer,
+ ELD_MAX_SIZE);
+ if (size < 0)
+ goto unlock;
+ if (size > 0) {
+ size = min(size, ELD_MAX_SIZE);
+ if (snd_hdmi_parse_eld(codec, &eld->info,
+ eld->eld_buffer, size) < 0)
+ size = -EINVAL;
+ }
+
+ if (size > 0) {
+ eld->eld_valid = true;
+ eld->eld_size = size;
+ } else {
+ eld->eld_valid = false;
+ eld->eld_size = 0;
+ }
+
+ update_eld(codec, per_pin, eld);
+ snd_jack_report(per_pin->acomp_jack,
+ eld->monitor_present ? SND_JACK_AVOUT : 0);
+ unlock:
+ mutex_unlock(&per_pin->lock);
+}
+
+static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
+{
+ struct hda_codec *codec = per_pin->codec;
+
+ if (codec_has_acomp(codec)) {
+ sync_eld_via_acomp(codec, per_pin);
+ return false; /* don't call snd_hda_jack_report_sync() */
+ } else {
+ return hdmi_present_sense_via_verbs(per_pin, repoll);
+ }
+}
+
static void hdmi_repoll_eld(struct work_struct *work)
{
struct hdmi_spec_per_pin *per_pin =
@@ -1776,17 +1838,6 @@ static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
return non_pcm;
}
-/* There is a fixed mapping between audio pin node and display port
- * on current Intel platforms:
- * Pin Widget 5 - PORT B (port = 1 in i915 driver)
- * Pin Widget 6 - PORT C (port = 2 in i915 driver)
- * Pin Widget 7 - PORT D (port = 3 in i915 driver)
- */
-static int intel_pin2port(hda_nid_t pin_nid)
-{
- return pin_nid - 4;
-}
-
/*
* HDMI callbacks
*/
@@ -1803,7 +1854,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
hda_nid_t pin_nid = per_pin->pin_nid;
struct snd_pcm_runtime *runtime = substream->runtime;
- struct i915_audio_component *acomp = codec->bus->core.audio_component;
bool non_pcm;
int pinctl;
@@ -1822,10 +1872,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
/* Call sync_audio_rate to set the N/CTS/M manually if necessary */
/* Todo: add DP1.2 MST audio support later */
- if (acomp && acomp->ops && acomp->ops->sync_audio_rate)
- acomp->ops->sync_audio_rate(acomp->dev,
- intel_pin2port(pin_nid),
- runtime->rate);
+ snd_hdac_sync_audio_rate(&codec->bus->core, pin_nid, runtime->rate);
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
mutex_lock(&per_pin->lock);
@@ -2091,6 +2138,30 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
return 0;
}
+static void free_acomp_jack_priv(struct snd_jack *jack)
+{
+ struct hdmi_spec_per_pin *per_pin = jack->private_data;
+
+ per_pin->acomp_jack = NULL;
+}
+
+static int add_acomp_jack_kctl(struct hda_codec *codec,
+ struct hdmi_spec_per_pin *per_pin,
+ const char *name)
+{
+ struct snd_jack *jack;
+ int err;
+
+ err = snd_jack_new(codec->card, name, SND_JACK_AVOUT, &jack,
+ true, false);
+ if (err < 0)
+ return err;
+ per_pin->acomp_jack = jack;
+ jack->private_data = per_pin;
+ jack->private_free = free_acomp_jack_priv;
+ return 0;
+}
+
static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
{
char hdmi_str[32] = "HDMI/DP";
@@ -2101,6 +2172,8 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
if (pcmdev > 0)
sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
+ if (codec_has_acomp(codec))
+ return add_acomp_jack_kctl(codec, per_pin, hdmi_str);
phantom_jack = !is_jack_detectable(codec, per_pin->pin_nid);
if (phantom_jack)
strncat(hdmi_str, " Phantom",
@@ -2196,8 +2269,10 @@ static int generic_hdmi_init(struct hda_codec *codec)
hda_nid_t pin_nid = per_pin->pin_nid;
hdmi_init_pin(codec, pin_nid);
- snd_hda_jack_detect_enable_callback(codec, pin_nid,
- codec->jackpoll_interval > 0 ? jack_callback : NULL);
+ if (!codec_has_acomp(codec))
+ snd_hda_jack_detect_enable_callback(codec, pin_nid,
+ codec->jackpoll_interval > 0 ?
+ jack_callback : NULL);
}
return 0;
}
@@ -2219,7 +2294,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
struct hdmi_spec *spec = codec->spec;
int pin_idx;
- if (is_haswell_plus(codec) || is_valleyview_plus(codec))
+ if (codec_has_acomp(codec))
snd_hdac_i915_register_notifier(NULL);
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
@@ -2227,8 +2302,12 @@ static void generic_hdmi_free(struct hda_codec *codec)
cancel_delayed_work_sync(&per_pin->work);
eld_proc_free(per_pin);
+ if (per_pin->acomp_jack)
+ snd_device_free(codec->card, per_pin->acomp_jack);
}
+ if (spec->i915_bound)
+ snd_hdac_i915_exit(&codec->bus->core);
hdmi_array_free(spec);
kfree(spec);
}
@@ -2357,6 +2436,9 @@ static void intel_pin_eld_notify(void *audio_ptr, int port)
*/
if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0)
return;
+ /* ditto during suspend/resume process itself */
+ if (atomic_read(&(codec)->core.in_pm))
+ return;
check_presence_and_report(codec, pin_nid);
}
@@ -2373,6 +2455,12 @@ static int patch_generic_hdmi(struct hda_codec *codec)
codec->spec = spec;
hdmi_array_init(spec, 4);
+ /* Try to bind with i915 for any Intel codecs (if not done yet) */
+ if (!codec_has_acomp(codec) &&
+ (codec->core.vendor_id >> 16) == 0x8086)
+ if (!snd_hdac_i915_init(&codec->bus->core))
+ spec->i915_bound = true;
+
if (is_haswell_plus(codec)) {
intel_haswell_enable_all_pins(codec, true);
intel_haswell_fixup_enable_dp12(codec);
@@ -2388,7 +2476,7 @@ static int patch_generic_hdmi(struct hda_codec *codec)
is_broxton(codec))
codec->core.link_power_control = 1;
- if (is_haswell_plus(codec) || is_valleyview_plus(codec)) {
+ if (codec_has_acomp(codec)) {
codec->depop_delay = 0;
spec->i915_audio_ops.audio_ptr = codec;
spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
@@ -2396,6 +2484,8 @@ static int patch_generic_hdmi(struct hda_codec *codec)
}
if (hdmi_parse_codec(codec) < 0) {
+ if (spec->i915_bound)
+ snd_hdac_i915_exit(&codec->bus->core);
codec->spec = NULL;
kfree(spec);
return -EINVAL;
@@ -3579,6 +3669,7 @@ HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_generic_hdmi),
+HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_generic_hdmi),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3a89d82f8057..8143c0e24a27 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4666,6 +4666,7 @@ enum {
ALC290_FIXUP_SUBWOOFER,
ALC290_FIXUP_SUBWOOFER_HSJACK,
ALC269_FIXUP_THINKPAD_ACPI,
+ ALC269_FIXUP_DMIC_THINKPAD_ACPI,
ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
ALC255_FIXUP_HEADSET_MODE,
@@ -5103,6 +5104,12 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = hda_fixup_thinkpad_acpi,
},
+ [ALC269_FIXUP_DMIC_THINKPAD_ACPI] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc_fixup_inv_dmic,
+ .chained = true,
+ .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
+ },
[ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@@ -5324,6 +5331,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
+ SND_PCI_QUIRK(0x1028, 0x05be, "Dell Latitude E6540", ALC292_FIXUP_DELL_E7X),
SND_PCI_QUIRK(0x1028, 0x05ca, "Dell Latitude E7240", ALC292_FIXUP_DELL_E7X),
SND_PCI_QUIRK(0x1028, 0x05cb, "Dell Latitude E7440", ALC292_FIXUP_DELL_E7X),
SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
@@ -5332,6 +5340,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
+ SND_PCI_QUIRK(0x1028, 0x062c, "Dell Latitude E5550", ALC292_FIXUP_DELL_E7X),
SND_PCI_QUIRK(0x1028, 0x062e, "Dell Latitude E7450", ALC292_FIXUP_DELL_E7X),
SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -5457,6 +5466,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
+ SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -5617,6 +5627,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x21, 0x02211040}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x12, 0x90a60170},
+ {0x14, 0x90171130},
+ {0x21, 0x02211040}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x12, 0x90a60170},
{0x14, 0x90170140},
{0x21, 0x02211050}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5548", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index 496dbd0ad5db..3bfdc78cbc5f 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -174,7 +174,7 @@ static int ap_cs8427_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
return -ENOENT;
}
-static struct snd_i2c_ops ap_cs8427_i2c_ops = {
+static const struct snd_i2c_ops ap_cs8427_i2c_ops = {
.sendbytes = ap_cs8427_sendbytes,
.readbytes = ap_cs8427_readbytes,
.probeaddr = ap_cs8427_probeaddr,
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 7ff7d88e46dd..7ea66ee3653f 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -38,6 +38,7 @@ config SND_SOC_TOPOLOGY
# All the supported SoCs
source "sound/soc/adi/Kconfig"
+source "sound/soc/amd/Kconfig"
source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
source "sound/soc/bcm/Kconfig"
@@ -50,6 +51,7 @@ source "sound/soc/jz4740/Kconfig"
source "sound/soc/nuc900/Kconfig"
source "sound/soc/omap/Kconfig"
source "sound/soc/kirkwood/Kconfig"
+source "sound/soc/img/Kconfig"
source "sound/soc/intel/Kconfig"
source "sound/soc/mediatek/Kconfig"
source "sound/soc/mxs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 8eb06db32fa0..9a30f21d16ee 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/
obj-$(CONFIG_SND_SOC) += generic/
obj-$(CONFIG_SND_SOC) += adi/
+obj-$(CONFIG_SND_SOC) += amd/
obj-$(CONFIG_SND_SOC) += atmel/
obj-$(CONFIG_SND_SOC) += au1x/
obj-$(CONFIG_SND_SOC) += bcm/
@@ -27,6 +28,7 @@ obj-$(CONFIG_SND_SOC) += davinci/
obj-$(CONFIG_SND_SOC) += dwc/
obj-$(CONFIG_SND_SOC) += fsl/
obj-$(CONFIG_SND_SOC) += jz4740/
+obj-$(CONFIG_SND_SOC) += img/
obj-$(CONFIG_SND_SOC) += intel/
obj-$(CONFIG_SND_SOC) += mediatek/
obj-$(CONFIG_SND_SOC) += mxs/
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
new file mode 100644
index 000000000000..78187eb24f56
--- /dev/null
+++ b/sound/soc/amd/Kconfig
@@ -0,0 +1,4 @@
+config SND_SOC_AMD_ACP
+ tristate "AMD Audio Coprocessor support"
+ help
+ This option enables ACP DMA support on AMD platform.
diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile
new file mode 100644
index 000000000000..1a66ec0366b2
--- /dev/null
+++ b/sound/soc/amd/Makefile
@@ -0,0 +1,3 @@
+snd-soc-acp-pcm-objs := acp-pcm-dma.o
+
+obj-$(CONFIG_SND_SOC_AMD_ACP) += snd-soc-acp-pcm.o
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
new file mode 100644
index 000000000000..3191e0a7d273
--- /dev/null
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -0,0 +1,1043 @@
+/*
+ * AMD ALSA SoC PCM Driver for ACP 2.x
+ *
+ * Copyright 2014-2015 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include <linux/pm_runtime.h>
+
+#include <sound/soc.h>
+
+#include "acp.h"
+
+#define PLAYBACK_MIN_NUM_PERIODS 2
+#define PLAYBACK_MAX_NUM_PERIODS 2
+#define PLAYBACK_MAX_PERIOD_SIZE 16384
+#define PLAYBACK_MIN_PERIOD_SIZE 1024
+#define CAPTURE_MIN_NUM_PERIODS 2
+#define CAPTURE_MAX_NUM_PERIODS 2
+#define CAPTURE_MAX_PERIOD_SIZE 16384
+#define CAPTURE_MIN_PERIOD_SIZE 1024
+
+#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
+#define MIN_BUFFER MAX_BUFFER
+
+static const struct snd_pcm_hardware acp_pcm_hardware_playback = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .rate_min = 8000,
+ .rate_max = 96000,
+ .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
+ .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
+ .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
+ .periods_min = PLAYBACK_MIN_NUM_PERIODS,
+ .periods_max = PLAYBACK_MAX_NUM_PERIODS,
+};
+
+static const struct snd_pcm_hardware acp_pcm_hardware_capture = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
+ .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
+ .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
+ .periods_min = CAPTURE_MIN_NUM_PERIODS,
+ .periods_max = CAPTURE_MAX_NUM_PERIODS,
+};
+
+struct audio_drv_data {
+ struct snd_pcm_substream *play_stream;
+ struct snd_pcm_substream *capture_stream;
+ void __iomem *acp_mmio;
+};
+
+static u32 acp_reg_read(void __iomem *acp_mmio, u32 reg)
+{
+ return readl(acp_mmio + (reg * 4));
+}
+
+static void acp_reg_write(u32 val, void __iomem *acp_mmio, u32 reg)
+{
+ writel(val, acp_mmio + (reg * 4));
+}
+
+/* Configure a given dma channel parameters - enable/disble,
+ * number of descriptors, priority
+ */
+static void config_acp_dma_channel(void __iomem *acp_mmio, u8 ch_num,
+ u16 dscr_strt_idx, u16 num_dscrs,
+ enum acp_dma_priority_level priority_level)
+{
+ u32 dma_ctrl;
+
+ /* disable the channel run field */
+ dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+ dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRun_MASK;
+ acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+
+ /* program a DMA channel with first descriptor to be processed. */
+ acp_reg_write((ACP_DMA_DSCR_STRT_IDX_0__DMAChDscrStrtIdx_MASK
+ & dscr_strt_idx),
+ acp_mmio, mmACP_DMA_DSCR_STRT_IDX_0 + ch_num);
+
+ /* program a DMA channel with the number of descriptors to be
+ * processed in the transfer
+ */
+ acp_reg_write(ACP_DMA_DSCR_CNT_0__DMAChDscrCnt_MASK & num_dscrs,
+ acp_mmio, mmACP_DMA_DSCR_CNT_0 + ch_num);
+
+ /* set DMA channel priority */
+ acp_reg_write(priority_level, acp_mmio, mmACP_DMA_PRIO_0 + ch_num);
+}
+
+/* Initialize a dma descriptor in SRAM based on descritor information passed */
+static void config_dma_descriptor_in_sram(void __iomem *acp_mmio,
+ u16 descr_idx,
+ acp_dma_dscr_transfer_t *descr_info)
+{
+ u32 sram_offset;
+
+ sram_offset = (descr_idx * sizeof(acp_dma_dscr_transfer_t));
+
+ /* program the source base address. */
+ acp_reg_write(sram_offset, acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
+ acp_reg_write(descr_info->src, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
+ /* program the destination base address. */
+ acp_reg_write(sram_offset + 4, acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
+ acp_reg_write(descr_info->dest, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
+
+ /* program the number of bytes to be transferred for this descriptor. */
+ acp_reg_write(sram_offset + 8, acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
+ acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
+}
+
+/* Initialize the DMA descriptor information for transfer between
+ * system memory <-> ACP SRAM
+ */
+static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio,
+ u32 size, int direction,
+ u32 pte_offset)
+{
+ u16 i;
+ u16 dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
+ acp_dma_dscr_transfer_t dmadscr[NUM_DSCRS_PER_CHANNEL];
+
+ for (i = 0; i < NUM_DSCRS_PER_CHANNEL; i++) {
+ dmadscr[i].xfer_val = 0;
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12 + i;
+ dmadscr[i].dest = ACP_SHARED_RAM_BANK_1_ADDRESS +
+ (size / 2) - (i * (size/2));
+ dmadscr[i].src = ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS
+ + (pte_offset * SZ_4K) + (i * (size/2));
+ dmadscr[i].xfer_val |=
+ (ACP_DMA_ATTRIBUTES_DAGB_ONION_TO_SHAREDMEM << 16) |
+ (size / 2);
+ } else {
+ dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH14 + i;
+ dmadscr[i].src = ACP_SHARED_RAM_BANK_5_ADDRESS +
+ (i * (size/2));
+ dmadscr[i].dest = ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS
+ + (pte_offset * SZ_4K) +
+ (i * (size/2));
+ dmadscr[i].xfer_val |=
+ BIT(22) |
+ (ACP_DMA_ATTRIBUTES_SHAREDMEM_TO_DAGB_ONION << 16) |
+ (size / 2);
+ }
+ config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
+ &dmadscr[i]);
+ }
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM,
+ PLAYBACK_START_DMA_DESCR_CH12,
+ NUM_DSCRS_PER_CHANNEL,
+ ACP_DMA_PRIORITY_LEVEL_NORMAL);
+ else
+ config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM,
+ CAPTURE_START_DMA_DESCR_CH14,
+ NUM_DSCRS_PER_CHANNEL,
+ ACP_DMA_PRIORITY_LEVEL_NORMAL);
+}
+
+/* Initialize the DMA descriptor information for transfer between
+ * ACP SRAM <-> I2S
+ */
+static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio,
+ u32 size, int direction)
+{
+
+ u16 i;
+ u16 dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13;
+ acp_dma_dscr_transfer_t dmadscr[NUM_DSCRS_PER_CHANNEL];
+
+ for (i = 0; i < NUM_DSCRS_PER_CHANNEL; i++) {
+ dmadscr[i].xfer_val = 0;
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ dma_dscr_idx = PLAYBACK_START_DMA_DESCR_CH13 + i;
+ dmadscr[i].src = ACP_SHARED_RAM_BANK_1_ADDRESS +
+ (i * (size/2));
+ /* dmadscr[i].dest is unused by hardware. */
+ dmadscr[i].dest = 0;
+ dmadscr[i].xfer_val |= BIT(22) | (TO_ACP_I2S_1 << 16) |
+ (size / 2);
+ } else {
+ dma_dscr_idx = CAPTURE_START_DMA_DESCR_CH15 + i;
+ /* dmadscr[i].src is unused by hardware. */
+ dmadscr[i].src = 0;
+ dmadscr[i].dest = ACP_SHARED_RAM_BANK_5_ADDRESS +
+ (i * (size / 2));
+ dmadscr[i].xfer_val |= BIT(22) |
+ (FROM_ACP_I2S_1 << 16) | (size / 2);
+ }
+ config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
+ &dmadscr[i]);
+ }
+ /* Configure the DMA channel with the above descriptore */
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+ config_acp_dma_channel(acp_mmio, ACP_TO_I2S_DMA_CH_NUM,
+ PLAYBACK_START_DMA_DESCR_CH13,
+ NUM_DSCRS_PER_CHANNEL,
+ ACP_DMA_PRIORITY_LEVEL_NORMAL);
+ else
+ config_acp_dma_channel(acp_mmio, I2S_TO_ACP_DMA_CH_NUM,
+ CAPTURE_START_DMA_DESCR_CH15,
+ NUM_DSCRS_PER_CHANNEL,
+ ACP_DMA_PRIORITY_LEVEL_NORMAL);
+}
+
+/* Create page table entries in ACP SRAM for the allocated memory */
+static void acp_pte_config(void __iomem *acp_mmio, struct page *pg,
+ u16 num_of_pages, u32 pte_offset)
+{
+ u16 page_idx;
+ u64 addr;
+ u32 low;
+ u32 high;
+ u32 offset;
+
+ offset = ACP_DAGB_GRP_SRBM_SRAM_BASE_OFFSET + (pte_offset * 8);
+ for (page_idx = 0; page_idx < (num_of_pages); page_idx++) {
+ /* Load the low address of page int ACP SRAM through SRBM */
+ acp_reg_write((offset + (page_idx * 8)),
+ acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
+ addr = page_to_phys(pg);
+
+ low = lower_32_bits(addr);
+ high = upper_32_bits(addr);
+
+ acp_reg_write(low, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
+
+ /* Load the High address of page int ACP SRAM through SRBM */
+ acp_reg_write((offset + (page_idx * 8) + 4),
+ acp_mmio, mmACP_SRBM_Targ_Idx_Addr);
+
+ /* page enable in ACP */
+ high |= BIT(31);
+ acp_reg_write(high, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
+
+ /* Move to next physically contiguos page */
+ pg++;
+ }
+}
+
+static void config_acp_dma(void __iomem *acp_mmio,
+ struct audio_substream_data *audio_config)
+{
+ u32 pte_offset;
+
+ if (audio_config->direction == SNDRV_PCM_STREAM_PLAYBACK)
+ pte_offset = ACP_PLAYBACK_PTE_OFFSET;
+ else
+ pte_offset = ACP_CAPTURE_PTE_OFFSET;
+
+ acp_pte_config(acp_mmio, audio_config->pg, audio_config->num_of_pages,
+ pte_offset);
+
+ /* Configure System memory <-> ACP SRAM DMA descriptors */
+ set_acp_sysmem_dma_descriptors(acp_mmio, audio_config->size,
+ audio_config->direction, pte_offset);
+
+ /* Configure ACP SRAM <-> I2S DMA descriptors */
+ set_acp_to_i2s_dma_descriptors(acp_mmio, audio_config->size,
+ audio_config->direction);
+}
+
+/* Start a given DMA channel transfer */
+static void acp_dma_start(void __iomem *acp_mmio,
+ u16 ch_num, bool is_circular)
+{
+ u32 dma_ctrl;
+
+ /* read the dma control register and disable the channel run field */
+ dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+
+ /* Invalidating the DAGB cache */
+ acp_reg_write(1, acp_mmio, mmACP_DAGB_ATU_CTRL);
+
+ /* configure the DMA channel and start the DMA transfer
+ * set dmachrun bit to start the transfer and enable the
+ * interrupt on completion of the dma transfer
+ */
+ dma_ctrl |= ACP_DMA_CNTL_0__DMAChRun_MASK;
+
+ switch (ch_num) {
+ case ACP_TO_I2S_DMA_CH_NUM:
+ case ACP_TO_SYSRAM_CH_NUM:
+ case I2S_TO_ACP_DMA_CH_NUM:
+ dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
+ break;
+ default:
+ dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
+ break;
+ }
+
+ /* enable for ACP SRAM to/from I2S DMA channel */
+ if (is_circular == true)
+ dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+ else
+ dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+
+ acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+}
+
+/* Stop a given DMA channel transfer */
+static int acp_dma_stop(void __iomem *acp_mmio, u8 ch_num)
+{
+ u32 dma_ctrl;
+ u32 dma_ch_sts;
+ u32 count = ACP_DMA_RESET_TIME;
+
+ dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+
+ /* clear the dma control register fields before writing zero
+ * in reset bit
+ */
+ dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRun_MASK;
+ dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
+
+ acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+ dma_ch_sts = acp_reg_read(acp_mmio, mmACP_DMA_CH_STS);
+
+ if (dma_ch_sts & BIT(ch_num)) {
+ /* set the reset bit for this channel to stop the dma
+ * transfer
+ */
+ dma_ctrl |= ACP_DMA_CNTL_0__DMAChRst_MASK;
+ acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+ }
+
+ /* check the channel status bit for some time and return the status */
+ while (true) {
+ dma_ch_sts = acp_reg_read(acp_mmio, mmACP_DMA_CH_STS);
+ if (!(dma_ch_sts & BIT(ch_num))) {
+ /* clear the reset flag after successfully stopping
+ * the dma transfer and break from the loop
+ */
+ dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK;
+
+ acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0
+ + ch_num);
+ break;
+ }
+ if (--count == 0) {
+ pr_err("Failed to stop ACP DMA channel : %d\n", ch_num);
+ return -ETIMEDOUT;
+ }
+ udelay(100);
+ }
+ return 0;
+}
+
+static void acp_set_sram_bank_state(void __iomem *acp_mmio, u16 bank,
+ bool power_on)
+{
+ u32 val, req_reg, sts_reg, sts_reg_mask;
+ u32 loops = 1000;
+
+ if (bank < 32) {
+ req_reg = mmACP_MEM_SHUT_DOWN_REQ_LO;
+ sts_reg = mmACP_MEM_SHUT_DOWN_STS_LO;
+ sts_reg_mask = 0xFFFFFFFF;
+
+ } else {
+ bank -= 32;
+ req_reg = mmACP_MEM_SHUT_DOWN_REQ_HI;
+ sts_reg = mmACP_MEM_SHUT_DOWN_STS_HI;
+ sts_reg_mask = 0x0000FFFF;
+ }
+
+ val = acp_reg_read(acp_mmio, req_reg);
+ if (val & (1 << bank)) {
+ /* bank is in off state */
+ if (power_on == true)
+ /* request to on */
+ val &= ~(1 << bank);
+ else
+ /* request to off */
+ return;
+ } else {
+ /* bank is in on state */
+ if (power_on == false)
+ /* request to off */
+ val |= 1 << bank;
+ else
+ /* request to on */
+ return;
+ }
+ acp_reg_write(val, acp_mmio, req_reg);
+
+ while (acp_reg_read(acp_mmio, sts_reg) != sts_reg_mask) {
+ if (!loops--) {
+ pr_err("ACP SRAM bank %d state change failed\n", bank);
+ break;
+ }
+ cpu_relax();
+ }
+}
+
+/* Initialize and bring ACP hardware to default state. */
+static int acp_init(void __iomem *acp_mmio)
+{
+ u16 bank;
+ u32 val, count, sram_pte_offset;
+
+ /* Assert Soft reset of ACP */
+ val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET);
+
+ val |= ACP_SOFT_RESET__SoftResetAud_MASK;
+ acp_reg_write(val, acp_mmio, mmACP_SOFT_RESET);
+
+ count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE;
+ while (true) {
+ val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET);
+ if (ACP_SOFT_RESET__SoftResetAudDone_MASK ==
+ (val & ACP_SOFT_RESET__SoftResetAudDone_MASK))
+ break;
+ if (--count == 0) {
+ pr_err("Failed to reset ACP\n");
+ return -ETIMEDOUT;
+ }
+ udelay(100);
+ }
+
+ /* Enable clock to ACP and wait until the clock is enabled */
+ val = acp_reg_read(acp_mmio, mmACP_CONTROL);
+ val = val | ACP_CONTROL__ClkEn_MASK;
+ acp_reg_write(val, acp_mmio, mmACP_CONTROL);
+
+ count = ACP_CLOCK_EN_TIME_OUT_VALUE;
+
+ while (true) {
+ val = acp_reg_read(acp_mmio, mmACP_STATUS);
+ if (val & (u32) 0x1)
+ break;
+ if (--count == 0) {
+ pr_err("Failed to reset ACP\n");
+ return -ETIMEDOUT;
+ }
+ udelay(100);
+ }
+
+ /* Deassert the SOFT RESET flags */
+ val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET);
+ val &= ~ACP_SOFT_RESET__SoftResetAud_MASK;
+ acp_reg_write(val, acp_mmio, mmACP_SOFT_RESET);
+
+ /* initiailize Onion control DAGB register */
+ acp_reg_write(ACP_ONION_CNTL_DEFAULT, acp_mmio,
+ mmACP_AXI2DAGB_ONION_CNTL);
+
+ /* initiailize Garlic control DAGB registers */
+ acp_reg_write(ACP_GARLIC_CNTL_DEFAULT, acp_mmio,
+ mmACP_AXI2DAGB_GARLIC_CNTL);
+
+ sram_pte_offset = ACP_DAGB_GRP_SRAM_BASE_ADDRESS |
+ ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBSnoopSel_MASK |
+ ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBTargetMemSel_MASK |
+ ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBGrpEnable_MASK;
+ acp_reg_write(sram_pte_offset, acp_mmio, mmACP_DAGB_BASE_ADDR_GRP_1);
+ acp_reg_write(ACP_PAGE_SIZE_4K_ENABLE, acp_mmio,
+ mmACP_DAGB_PAGE_SIZE_GRP_1);
+
+ acp_reg_write(ACP_SRAM_BASE_ADDRESS, acp_mmio,
+ mmACP_DMA_DESC_BASE_ADDR);
+
+ /* Num of descriptiors in SRAM 0x4, means 256 descriptors;(64 * 4) */
+ acp_reg_write(0x4, acp_mmio, mmACP_DMA_DESC_MAX_NUM_DSCR);
+ acp_reg_write(ACP_EXTERNAL_INTR_CNTL__DMAIOCMask_MASK,
+ acp_mmio, mmACP_EXTERNAL_INTR_CNTL);
+
+ /* When ACP_TILE_P1 is turned on, all SRAM banks get turned on.
+ * Now, turn off all of them. This can't be done in 'poweron' of
+ * ACP pm domain, as this requires ACP to be initialized.
+ */
+ for (bank = 1; bank < 48; bank++)
+ acp_set_sram_bank_state(acp_mmio, bank, false);
+
+ return 0;
+}
+
+/* Deintialize ACP */
+static int acp_deinit(void __iomem *acp_mmio)
+{
+ u32 val;
+ u32 count;
+
+ /* Assert Soft reset of ACP */
+ val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET);
+
+ val |= ACP_SOFT_RESET__SoftResetAud_MASK;
+ acp_reg_write(val, acp_mmio, mmACP_SOFT_RESET);
+
+ count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE;
+ while (true) {
+ val = acp_reg_read(acp_mmio, mmACP_SOFT_RESET);
+ if (ACP_SOFT_RESET__SoftResetAudDone_MASK ==
+ (val & ACP_SOFT_RESET__SoftResetAudDone_MASK))
+ break;
+ if (--count == 0) {
+ pr_err("Failed to reset ACP\n");
+ return -ETIMEDOUT;
+ }
+ udelay(100);
+ }
+ /** Disable ACP clock */
+ val = acp_reg_read(acp_mmio, mmACP_CONTROL);
+ val &= ~ACP_CONTROL__ClkEn_MASK;
+ acp_reg_write(val, acp_mmio, mmACP_CONTROL);
+
+ count = ACP_CLOCK_EN_TIME_OUT_VALUE;
+
+ while (true) {
+ val = acp_reg_read(acp_mmio, mmACP_STATUS);
+ if (!(val & (u32) 0x1))
+ break;
+ if (--count == 0) {
+ pr_err("Failed to reset ACP\n");
+ return -ETIMEDOUT;
+ }
+ udelay(100);
+ }
+ return 0;
+}
+
+/* ACP DMA irq handler routine for playback, capture usecases */
+static irqreturn_t dma_irq_handler(int irq, void *arg)
+{
+ u16 dscr_idx;
+ u32 intr_flag, ext_intr_status;
+ struct audio_drv_data *irq_data;
+ void __iomem *acp_mmio;
+ struct device *dev = arg;
+ bool valid_irq = false;
+
+ irq_data = dev_get_drvdata(dev);
+ acp_mmio = irq_data->acp_mmio;
+
+ ext_intr_status = acp_reg_read(acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+ intr_flag = (((ext_intr_status &
+ ACP_EXTERNAL_INTR_STAT__DMAIOCStat_MASK) >>
+ ACP_EXTERNAL_INTR_STAT__DMAIOCStat__SHIFT));
+
+ if ((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) != 0) {
+ valid_irq = true;
+ if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_13) ==
+ PLAYBACK_START_DMA_DESCR_CH13)
+ dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
+ else
+ dscr_idx = PLAYBACK_END_DMA_DESCR_CH12;
+ config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM, dscr_idx,
+ 1, 0);
+ acp_dma_start(acp_mmio, SYSRAM_TO_ACP_CH_NUM, false);
+
+ snd_pcm_period_elapsed(irq_data->play_stream);
+
+ acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) << 16,
+ acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+ }
+
+ if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
+ valid_irq = true;
+ if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_15) ==
+ CAPTURE_START_DMA_DESCR_CH15)
+ dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
+ else
+ dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
+ config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
+ 1, 0);
+ acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
+
+ acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
+ acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+ }
+
+ if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
+ valid_irq = true;
+ snd_pcm_period_elapsed(irq_data->capture_stream);
+ acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
+ acp_mmio, mmACP_EXTERNAL_INTR_STAT);
+ }
+
+ if (valid_irq)
+ return IRQ_HANDLED;
+ else
+ return IRQ_NONE;
+}
+
+static int acp_dma_open(struct snd_pcm_substream *substream)
+{
+ u16 bank;
+ int ret = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *prtd = substream->private_data;
+ struct audio_drv_data *intr_data = dev_get_drvdata(prtd->platform->dev);
+
+ struct audio_substream_data *adata =
+ kzalloc(sizeof(struct audio_substream_data), GFP_KERNEL);
+ if (adata == NULL)
+ return -ENOMEM;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ runtime->hw = acp_pcm_hardware_playback;
+ else
+ runtime->hw = acp_pcm_hardware_capture;
+
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0) {
+ dev_err(prtd->platform->dev, "set integer constraint failed\n");
+ return ret;
+ }
+
+ adata->acp_mmio = intr_data->acp_mmio;
+ runtime->private_data = adata;
+
+ /* Enable ACP irq, when neither playback or capture streams are
+ * active by the time when a new stream is being opened.
+ * This enablement is not required for another stream, if current
+ * stream is not closed
+ */
+ if (!intr_data->play_stream && !intr_data->capture_stream)
+ acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ intr_data->play_stream = substream;
+ for (bank = 1; bank <= 4; bank++)
+ acp_set_sram_bank_state(intr_data->acp_mmio, bank,
+ true);
+ } else {
+ intr_data->capture_stream = substream;
+ for (bank = 5; bank <= 8; bank++)
+ acp_set_sram_bank_state(intr_data->acp_mmio, bank,
+ true);
+ }
+
+ return 0;
+}
+
+static int acp_dma_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ int status;
+ uint64_t size;
+ struct snd_dma_buffer *dma_buffer;
+ struct page *pg;
+ struct snd_pcm_runtime *runtime;
+ struct audio_substream_data *rtd;
+
+ dma_buffer = &substream->dma_buffer;
+
+ runtime = substream->runtime;
+ rtd = runtime->private_data;
+
+ if (WARN_ON(!rtd))
+ return -EINVAL;
+
+ size = params_buffer_bytes(params);
+ status = snd_pcm_lib_malloc_pages(substream, size);
+ if (status < 0)
+ return status;
+
+ memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
+ pg = virt_to_page(substream->dma_buffer.area);
+
+ if (pg != NULL) {
+ acp_set_sram_bank_state(rtd->acp_mmio, 0, true);
+ /* Save for runtime private data */
+ rtd->pg = pg;
+ rtd->order = get_order(size);
+
+ /* Fill the page table entries in ACP SRAM */
+ rtd->pg = pg;
+ rtd->size = size;
+ rtd->num_of_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ rtd->direction = substream->stream;
+
+ config_acp_dma(rtd->acp_mmio, rtd);
+ status = 0;
+ } else {
+ status = -ENOMEM;
+ }
+ return status;
+}
+
+static int acp_dma_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream)
+{
+ u16 dscr;
+ u32 mul, dma_config, period_bytes;
+ u32 pos = 0;
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct audio_substream_data *rtd = runtime->private_data;
+
+ period_bytes = frames_to_bytes(runtime, runtime->period_size);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ dscr = acp_reg_read(rtd->acp_mmio, mmACP_DMA_CUR_DSCR_13);
+
+ if (dscr == PLAYBACK_START_DMA_DESCR_CH13)
+ mul = 0;
+ else
+ mul = 1;
+ pos = (mul * period_bytes);
+ } else {
+ dma_config = acp_reg_read(rtd->acp_mmio, mmACP_DMA_CNTL_14);
+ if (dma_config != 0) {
+ dscr = acp_reg_read(rtd->acp_mmio,
+ mmACP_DMA_CUR_DSCR_14);
+ if (dscr == CAPTURE_START_DMA_DESCR_CH14)
+ mul = 1;
+ else
+ mul = 2;
+ pos = (mul * period_bytes);
+ }
+
+ if (pos >= (2 * period_bytes))
+ pos = 0;
+
+ }
+ return bytes_to_frames(runtime, pos);
+}
+
+static int acp_dma_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ return snd_pcm_lib_default_mmap(substream, vma);
+}
+
+static int acp_dma_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct audio_substream_data *rtd = runtime->private_data;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ config_acp_dma_channel(rtd->acp_mmio, SYSRAM_TO_ACP_CH_NUM,
+ PLAYBACK_START_DMA_DESCR_CH12,
+ NUM_DSCRS_PER_CHANNEL, 0);
+ config_acp_dma_channel(rtd->acp_mmio, ACP_TO_I2S_DMA_CH_NUM,
+ PLAYBACK_START_DMA_DESCR_CH13,
+ NUM_DSCRS_PER_CHANNEL, 0);
+ /* Fill ACP SRAM (2 periods) with zeros from System RAM
+ * which is zero-ed in hw_params
+ */
+ acp_dma_start(rtd->acp_mmio, SYSRAM_TO_ACP_CH_NUM, false);
+
+ /* ACP SRAM (2 periods of buffer size) is intially filled with
+ * zeros. Before rendering starts, 2nd half of SRAM will be
+ * filled with valid audio data DMA'ed from first half of system
+ * RAM and 1st half of SRAM will be filled with Zeros. This is
+ * the initial scenario when redering starts from SRAM. Later
+ * on, 2nd half of system memory will be DMA'ed to 1st half of
+ * SRAM, 1st half of system memory will be DMA'ed to 2nd half of
+ * SRAM in ping-pong way till rendering stops.
+ */
+ config_acp_dma_channel(rtd->acp_mmio, SYSRAM_TO_ACP_CH_NUM,
+ PLAYBACK_START_DMA_DESCR_CH12,
+ 1, 0);
+ } else {
+ config_acp_dma_channel(rtd->acp_mmio, ACP_TO_SYSRAM_CH_NUM,
+ CAPTURE_START_DMA_DESCR_CH14,
+ NUM_DSCRS_PER_CHANNEL, 0);
+ config_acp_dma_channel(rtd->acp_mmio, I2S_TO_ACP_DMA_CH_NUM,
+ CAPTURE_START_DMA_DESCR_CH15,
+ NUM_DSCRS_PER_CHANNEL, 0);
+ }
+ return 0;
+}
+
+static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ int ret;
+ u32 loops = 1000;
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *prtd = substream->private_data;
+ struct audio_substream_data *rtd = runtime->private_data;
+
+ if (!rtd)
+ return -EINVAL;
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ acp_dma_start(rtd->acp_mmio,
+ SYSRAM_TO_ACP_CH_NUM, false);
+ while (acp_reg_read(rtd->acp_mmio, mmACP_DMA_CH_STS) &
+ BIT(SYSRAM_TO_ACP_CH_NUM)) {
+ if (!loops--) {
+ dev_err(prtd->platform->dev,
+ "acp dma start timeout\n");
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ }
+
+ acp_dma_start(rtd->acp_mmio,
+ ACP_TO_I2S_DMA_CH_NUM, true);
+
+ } else {
+ acp_dma_start(rtd->acp_mmio,
+ I2S_TO_ACP_DMA_CH_NUM, true);
+ }
+ ret = 0;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ /* Need to stop only circular DMA channels :
+ * ACP_TO_I2S_DMA_CH_NUM / I2S_TO_ACP_DMA_CH_NUM. Non-circular
+ * channels will stopped automatically after its transfer
+ * completes : SYSRAM_TO_ACP_CH_NUM / ACP_TO_SYSRAM_CH_NUM
+ */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = acp_dma_stop(rtd->acp_mmio,
+ ACP_TO_I2S_DMA_CH_NUM);
+ else
+ ret = acp_dma_stop(rtd->acp_mmio,
+ I2S_TO_ACP_DMA_CH_NUM);
+ break;
+ default:
+ ret = -EINVAL;
+
+ }
+ return ret;
+}
+
+static int acp_dma_new(struct snd_soc_pcm_runtime *rtd)
+{
+ return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
+ SNDRV_DMA_TYPE_DEV,
+ NULL, MIN_BUFFER,
+ MAX_BUFFER);
+}
+
+static int acp_dma_close(struct snd_pcm_substream *substream)
+{
+ u16 bank;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct audio_substream_data *rtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *prtd = substream->private_data;
+ struct audio_drv_data *adata = dev_get_drvdata(prtd->platform->dev);
+
+ kfree(rtd);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ adata->play_stream = NULL;
+ for (bank = 1; bank <= 4; bank++)
+ acp_set_sram_bank_state(adata->acp_mmio, bank,
+ false);
+ } else {
+ adata->capture_stream = NULL;
+ for (bank = 5; bank <= 8; bank++)
+ acp_set_sram_bank_state(adata->acp_mmio, bank,
+ false);
+ }
+
+ /* Disable ACP irq, when the current stream is being closed and
+ * another stream is also not active.
+ */
+ if (!adata->play_stream && !adata->capture_stream)
+ acp_reg_write(0, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
+
+ return 0;
+}
+
+static struct snd_pcm_ops acp_dma_ops = {
+ .open = acp_dma_open,
+ .close = acp_dma_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = acp_dma_hw_params,
+ .hw_free = acp_dma_hw_free,
+ .trigger = acp_dma_trigger,
+ .pointer = acp_dma_pointer,
+ .mmap = acp_dma_mmap,
+ .prepare = acp_dma_prepare,
+};
+
+static struct snd_soc_platform_driver acp_asoc_platform = {
+ .ops = &acp_dma_ops,
+ .pcm_new = acp_dma_new,
+};
+
+static int acp_audio_probe(struct platform_device *pdev)
+{
+ int status;
+ struct audio_drv_data *audio_drv_data;
+ struct resource *res;
+
+ audio_drv_data = devm_kzalloc(&pdev->dev, sizeof(struct audio_drv_data),
+ GFP_KERNEL);
+ if (audio_drv_data == NULL)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ audio_drv_data->acp_mmio = devm_ioremap_resource(&pdev->dev, res);
+
+ /* The following members gets populated in device 'open'
+ * function. Till then interrupts are disabled in 'acp_init'
+ * and device doesn't generate any interrupts.
+ */
+
+ audio_drv_data->play_stream = NULL;
+ audio_drv_data->capture_stream = NULL;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+ return -ENODEV;
+ }
+
+ status = devm_request_irq(&pdev->dev, res->start, dma_irq_handler,
+ 0, "ACP_IRQ", &pdev->dev);
+ if (status) {
+ dev_err(&pdev->dev, "ACP IRQ request failed\n");
+ return status;
+ }
+
+ dev_set_drvdata(&pdev->dev, audio_drv_data);
+
+ /* Initialize the ACP */
+ acp_init(audio_drv_data->acp_mmio);
+
+ status = snd_soc_register_platform(&pdev->dev, &acp_asoc_platform);
+ if (status != 0) {
+ dev_err(&pdev->dev, "Fail to register ALSA platform device\n");
+ return status;
+ }
+
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ return status;
+}
+
+static int acp_audio_remove(struct platform_device *pdev)
+{
+ struct audio_drv_data *adata = dev_get_drvdata(&pdev->dev);
+
+ acp_deinit(adata->acp_mmio);
+ snd_soc_unregister_platform(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static int acp_pcm_resume(struct device *dev)
+{
+ u16 bank;
+ struct audio_drv_data *adata = dev_get_drvdata(dev);
+
+ acp_init(adata->acp_mmio);
+
+ if (adata->play_stream && adata->play_stream->runtime) {
+ for (bank = 1; bank <= 4; bank++)
+ acp_set_sram_bank_state(adata->acp_mmio, bank,
+ true);
+ config_acp_dma(adata->acp_mmio,
+ adata->play_stream->runtime->private_data);
+ }
+ if (adata->capture_stream && adata->capture_stream->runtime) {
+ for (bank = 5; bank <= 8; bank++)
+ acp_set_sram_bank_state(adata->acp_mmio, bank,
+ true);
+ config_acp_dma(adata->acp_mmio,
+ adata->capture_stream->runtime->private_data);
+ }
+ acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
+ return 0;
+}
+
+static int acp_pcm_runtime_suspend(struct device *dev)
+{
+ struct audio_drv_data *adata = dev_get_drvdata(dev);
+
+ acp_deinit(adata->acp_mmio);
+ acp_reg_write(0, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
+ return 0;
+}
+
+static int acp_pcm_runtime_resume(struct device *dev)
+{
+ struct audio_drv_data *adata = dev_get_drvdata(dev);
+
+ acp_init(adata->acp_mmio);
+ acp_reg_write(1, adata->acp_mmio, mmACP_EXTERNAL_INTR_ENB);
+ return 0;
+}
+
+static const struct dev_pm_ops acp_pm_ops = {
+ .resume = acp_pcm_resume,
+ .runtime_suspend = acp_pcm_runtime_suspend,
+ .runtime_resume = acp_pcm_runtime_resume,
+};
+
+static struct platform_driver acp_dma_driver = {
+ .probe = acp_audio_probe,
+ .remove = acp_audio_remove,
+ .driver = {
+ .name = "acp_audio_dma",
+ .pm = &acp_pm_ops,
+ },
+};
+
+module_platform_driver(acp_dma_driver);
+
+MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
+MODULE_DESCRIPTION("AMD ACP PCM Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:acp-dma-audio");
diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
new file mode 100644
index 000000000000..330832ef4e5e
--- /dev/null
+++ b/sound/soc/amd/acp.h
@@ -0,0 +1,118 @@
+#ifndef __ACP_HW_H
+#define __ACP_HW_H
+
+#include "include/acp_2_2_d.h"
+#include "include/acp_2_2_sh_mask.h"
+
+#define ACP_PAGE_SIZE_4K_ENABLE 0x02
+
+#define ACP_PLAYBACK_PTE_OFFSET 10
+#define ACP_CAPTURE_PTE_OFFSET 0
+
+#define ACP_GARLIC_CNTL_DEFAULT 0x00000FB4
+#define ACP_ONION_CNTL_DEFAULT 0x00000FB4
+
+#define ACP_PHYSICAL_BASE 0x14000
+
+/* Playback SRAM address (as a destination in dma descriptor) */
+#define ACP_SHARED_RAM_BANK_1_ADDRESS 0x4002000
+
+/* Capture SRAM address (as a source in dma descriptor) */
+#define ACP_SHARED_RAM_BANK_5_ADDRESS 0x400A000
+
+#define ACP_DMA_RESET_TIME 10000
+#define ACP_CLOCK_EN_TIME_OUT_VALUE 0x000000FF
+#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF
+#define ACP_DMA_COMPLETE_TIME_OUT_VALUE 0x000000FF
+
+#define ACP_SRAM_BASE_ADDRESS 0x4000000
+#define ACP_DAGB_GRP_SRAM_BASE_ADDRESS 0x4001000
+#define ACP_DAGB_GRP_SRBM_SRAM_BASE_OFFSET 0x1000
+#define ACP_INTERNAL_APERTURE_WINDOW_0_ADDRESS 0x00000000
+#define ACP_INTERNAL_APERTURE_WINDOW_4_ADDRESS 0x01800000
+
+#define TO_ACP_I2S_1 0x2
+#define TO_ACP_I2S_2 0x4
+#define FROM_ACP_I2S_1 0xa
+#define FROM_ACP_I2S_2 0xb
+
+#define ACP_TILE_ON_MASK 0x03
+#define ACP_TILE_OFF_MASK 0x02
+#define ACP_TILE_ON_RETAIN_REG_MASK 0x1f
+#define ACP_TILE_OFF_RETAIN_REG_MASK 0x20
+
+#define ACP_TILE_P1_MASK 0x3e
+#define ACP_TILE_P2_MASK 0x3d
+#define ACP_TILE_DSP0_MASK 0x3b
+#define ACP_TILE_DSP1_MASK 0x37
+
+#define ACP_TILE_DSP2_MASK 0x2f
+/* Playback DMA channels */
+#define SYSRAM_TO_ACP_CH_NUM 12
+#define ACP_TO_I2S_DMA_CH_NUM 13
+
+/* Capture DMA channels */
+#define ACP_TO_SYSRAM_CH_NUM 14
+#define I2S_TO_ACP_DMA_CH_NUM 15
+
+#define NUM_DSCRS_PER_CHANNEL 2
+
+#define PLAYBACK_START_DMA_DESCR_CH12 0
+#define PLAYBACK_END_DMA_DESCR_CH12 1
+#define PLAYBACK_START_DMA_DESCR_CH13 2
+#define PLAYBACK_END_DMA_DESCR_CH13 3
+
+#define CAPTURE_START_DMA_DESCR_CH14 4
+#define CAPTURE_END_DMA_DESCR_CH14 5
+#define CAPTURE_START_DMA_DESCR_CH15 6
+#define CAPTURE_END_DMA_DESCR_CH15 7
+
+enum acp_dma_priority_level {
+ /* 0x0 Specifies the DMA channel is given normal priority */
+ ACP_DMA_PRIORITY_LEVEL_NORMAL = 0x0,
+ /* 0x1 Specifies the DMA channel is given high priority */
+ ACP_DMA_PRIORITY_LEVEL_HIGH = 0x1,
+ ACP_DMA_PRIORITY_LEVEL_FORCESIZE = 0xFF
+};
+
+struct audio_substream_data {
+ struct page *pg;
+ unsigned int order;
+ u16 num_of_pages;
+ u16 direction;
+ uint64_t size;
+ void __iomem *acp_mmio;
+};
+
+enum {
+ ACP_TILE_P1 = 0,
+ ACP_TILE_P2,
+ ACP_TILE_DSP0,
+ ACP_TILE_DSP1,
+ ACP_TILE_DSP2,
+};
+
+enum {
+ ACP_DMA_ATTRIBUTES_SHAREDMEM_TO_DAGB_ONION = 0x0,
+ ACP_DMA_ATTRIBUTES_SHARED_MEM_TO_DAGB_GARLIC = 0x1,
+ ACP_DMA_ATTRIBUTES_DAGB_ONION_TO_SHAREDMEM = 0x8,
+ ACP_DMA_ATTRIBUTES_DAGB_GARLIC_TO_SHAREDMEM = 0x9,
+ ACP_DMA_ATTRIBUTES_FORCE_SIZE = 0xF
+};
+
+typedef struct acp_dma_dscr_transfer {
+ /* Specifies the source memory location for the DMA data transfer. */
+ u32 src;
+ /* Specifies the destination memory location to where the data will
+ * be transferred.
+ */
+ u32 dest;
+ /* Specifies the number of bytes need to be transferred
+ * from source to destination memory.Transfer direction & IOC enable
+ */
+ u32 xfer_val;
+ /* Reserved for future use */
+ u32 reserved;
+} acp_dma_dscr_transfer_t;
+
+#endif /*__ACP_HW_H */
diff --git a/sound/soc/amd/include/acp_2_2_d.h b/sound/soc/amd/include/acp_2_2_d.h
new file mode 100644
index 000000000000..0118fe9e6a87
--- /dev/null
+++ b/sound/soc/amd/include/acp_2_2_d.h
@@ -0,0 +1,609 @@
+/*
+ * ACP_2_2 Register documentation
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) 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 ACP_2_2_D_H
+#define ACP_2_2_D_H
+
+#define mmACP_DMA_CNTL_0 0x5000
+#define mmACP_DMA_CNTL_1 0x5001
+#define mmACP_DMA_CNTL_2 0x5002
+#define mmACP_DMA_CNTL_3 0x5003
+#define mmACP_DMA_CNTL_4 0x5004
+#define mmACP_DMA_CNTL_5 0x5005
+#define mmACP_DMA_CNTL_6 0x5006
+#define mmACP_DMA_CNTL_7 0x5007
+#define mmACP_DMA_CNTL_8 0x5008
+#define mmACP_DMA_CNTL_9 0x5009
+#define mmACP_DMA_CNTL_10 0x500a
+#define mmACP_DMA_CNTL_11 0x500b
+#define mmACP_DMA_CNTL_12 0x500c
+#define mmACP_DMA_CNTL_13 0x500d
+#define mmACP_DMA_CNTL_14 0x500e
+#define mmACP_DMA_CNTL_15 0x500f
+#define mmACP_DMA_DSCR_STRT_IDX_0 0x5010
+#define mmACP_DMA_DSCR_STRT_IDX_1 0x5011
+#define mmACP_DMA_DSCR_STRT_IDX_2 0x5012
+#define mmACP_DMA_DSCR_STRT_IDX_3 0x5013
+#define mmACP_DMA_DSCR_STRT_IDX_4 0x5014
+#define mmACP_DMA_DSCR_STRT_IDX_5 0x5015
+#define mmACP_DMA_DSCR_STRT_IDX_6 0x5016
+#define mmACP_DMA_DSCR_STRT_IDX_7 0x5017
+#define mmACP_DMA_DSCR_STRT_IDX_8 0x5018
+#define mmACP_DMA_DSCR_STRT_IDX_9 0x5019
+#define mmACP_DMA_DSCR_STRT_IDX_10 0x501a
+#define mmACP_DMA_DSCR_STRT_IDX_11 0x501b
+#define mmACP_DMA_DSCR_STRT_IDX_12 0x501c
+#define mmACP_DMA_DSCR_STRT_IDX_13 0x501d
+#define mmACP_DMA_DSCR_STRT_IDX_14 0x501e
+#define mmACP_DMA_DSCR_STRT_IDX_15 0x501f
+#define mmACP_DMA_DSCR_CNT_0 0x5020
+#define mmACP_DMA_DSCR_CNT_1 0x5021
+#define mmACP_DMA_DSCR_CNT_2 0x5022
+#define mmACP_DMA_DSCR_CNT_3 0x5023
+#define mmACP_DMA_DSCR_CNT_4 0x5024
+#define mmACP_DMA_DSCR_CNT_5 0x5025
+#define mmACP_DMA_DSCR_CNT_6 0x5026
+#define mmACP_DMA_DSCR_CNT_7 0x5027
+#define mmACP_DMA_DSCR_CNT_8 0x5028
+#define mmACP_DMA_DSCR_CNT_9 0x5029
+#define mmACP_DMA_DSCR_CNT_10 0x502a
+#define mmACP_DMA_DSCR_CNT_11 0x502b
+#define mmACP_DMA_DSCR_CNT_12 0x502c
+#define mmACP_DMA_DSCR_CNT_13 0x502d
+#define mmACP_DMA_DSCR_CNT_14 0x502e
+#define mmACP_DMA_DSCR_CNT_15 0x502f
+#define mmACP_DMA_PRIO_0 0x5030
+#define mmACP_DMA_PRIO_1 0x5031
+#define mmACP_DMA_PRIO_2 0x5032
+#define mmACP_DMA_PRIO_3 0x5033
+#define mmACP_DMA_PRIO_4 0x5034
+#define mmACP_DMA_PRIO_5 0x5035
+#define mmACP_DMA_PRIO_6 0x5036
+#define mmACP_DMA_PRIO_7 0x5037
+#define mmACP_DMA_PRIO_8 0x5038
+#define mmACP_DMA_PRIO_9 0x5039
+#define mmACP_DMA_PRIO_10 0x503a
+#define mmACP_DMA_PRIO_11 0x503b
+#define mmACP_DMA_PRIO_12 0x503c
+#define mmACP_DMA_PRIO_13 0x503d
+#define mmACP_DMA_PRIO_14 0x503e
+#define mmACP_DMA_PRIO_15 0x503f
+#define mmACP_DMA_CUR_DSCR_0 0x5040
+#define mmACP_DMA_CUR_DSCR_1 0x5041
+#define mmACP_DMA_CUR_DSCR_2 0x5042
+#define mmACP_DMA_CUR_DSCR_3 0x5043
+#define mmACP_DMA_CUR_DSCR_4 0x5044
+#define mmACP_DMA_CUR_DSCR_5 0x5045
+#define mmACP_DMA_CUR_DSCR_6 0x5046
+#define mmACP_DMA_CUR_DSCR_7 0x5047
+#define mmACP_DMA_CUR_DSCR_8 0x5048
+#define mmACP_DMA_CUR_DSCR_9 0x5049
+#define mmACP_DMA_CUR_DSCR_10 0x504a
+#define mmACP_DMA_CUR_DSCR_11 0x504b
+#define mmACP_DMA_CUR_DSCR_12 0x504c
+#define mmACP_DMA_CUR_DSCR_13 0x504d
+#define mmACP_DMA_CUR_DSCR_14 0x504e
+#define mmACP_DMA_CUR_DSCR_15 0x504f
+#define mmACP_DMA_CUR_TRANS_CNT_0 0x5050
+#define mmACP_DMA_CUR_TRANS_CNT_1 0x5051
+#define mmACP_DMA_CUR_TRANS_CNT_2 0x5052
+#define mmACP_DMA_CUR_TRANS_CNT_3 0x5053
+#define mmACP_DMA_CUR_TRANS_CNT_4 0x5054
+#define mmACP_DMA_CUR_TRANS_CNT_5 0x5055
+#define mmACP_DMA_CUR_TRANS_CNT_6 0x5056
+#define mmACP_DMA_CUR_TRANS_CNT_7 0x5057
+#define mmACP_DMA_CUR_TRANS_CNT_8 0x5058
+#define mmACP_DMA_CUR_TRANS_CNT_9 0x5059
+#define mmACP_DMA_CUR_TRANS_CNT_10 0x505a
+#define mmACP_DMA_CUR_TRANS_CNT_11 0x505b
+#define mmACP_DMA_CUR_TRANS_CNT_12 0x505c
+#define mmACP_DMA_CUR_TRANS_CNT_13 0x505d
+#define mmACP_DMA_CUR_TRANS_CNT_14 0x505e
+#define mmACP_DMA_CUR_TRANS_CNT_15 0x505f
+#define mmACP_DMA_ERR_STS_0 0x5060
+#define mmACP_DMA_ERR_STS_1 0x5061
+#define mmACP_DMA_ERR_STS_2 0x5062
+#define mmACP_DMA_ERR_STS_3 0x5063
+#define mmACP_DMA_ERR_STS_4 0x5064
+#define mmACP_DMA_ERR_STS_5 0x5065
+#define mmACP_DMA_ERR_STS_6 0x5066
+#define mmACP_DMA_ERR_STS_7 0x5067
+#define mmACP_DMA_ERR_STS_8 0x5068
+#define mmACP_DMA_ERR_STS_9 0x5069
+#define mmACP_DMA_ERR_STS_10 0x506a
+#define mmACP_DMA_ERR_STS_11 0x506b
+#define mmACP_DMA_ERR_STS_12 0x506c
+#define mmACP_DMA_ERR_STS_13 0x506d
+#define mmACP_DMA_ERR_STS_14 0x506e
+#define mmACP_DMA_ERR_STS_15 0x506f
+#define mmACP_DMA_DESC_BASE_ADDR 0x5070
+#define mmACP_DMA_DESC_MAX_NUM_DSCR 0x5071
+#define mmACP_DMA_CH_STS 0x5072
+#define mmACP_DMA_CH_GROUP 0x5073
+#define mmACP_DSP0_CACHE_OFFSET0 0x5078
+#define mmACP_DSP0_CACHE_SIZE0 0x5079
+#define mmACP_DSP0_CACHE_OFFSET1 0x507a
+#define mmACP_DSP0_CACHE_SIZE1 0x507b
+#define mmACP_DSP0_CACHE_OFFSET2 0x507c
+#define mmACP_DSP0_CACHE_SIZE2 0x507d
+#define mmACP_DSP0_CACHE_OFFSET3 0x507e
+#define mmACP_DSP0_CACHE_SIZE3 0x507f
+#define mmACP_DSP0_CACHE_OFFSET4 0x5080
+#define mmACP_DSP0_CACHE_SIZE4 0x5081
+#define mmACP_DSP0_CACHE_OFFSET5 0x5082
+#define mmACP_DSP0_CACHE_SIZE5 0x5083
+#define mmACP_DSP0_CACHE_OFFSET6 0x5084
+#define mmACP_DSP0_CACHE_SIZE6 0x5085
+#define mmACP_DSP0_CACHE_OFFSET7 0x5086
+#define mmACP_DSP0_CACHE_SIZE7 0x5087
+#define mmACP_DSP0_CACHE_OFFSET8 0x5088
+#define mmACP_DSP0_CACHE_SIZE8 0x5089
+#define mmACP_DSP0_NONCACHE_OFFSET0 0x508a
+#define mmACP_DSP0_NONCACHE_SIZE0 0x508b
+#define mmACP_DSP0_NONCACHE_OFFSET1 0x508c
+#define mmACP_DSP0_NONCACHE_SIZE1 0x508d
+#define mmACP_DSP0_DEBUG_PC 0x508e
+#define mmACP_DSP0_NMI_SEL 0x508f
+#define mmACP_DSP0_CLKRST_CNTL 0x5090
+#define mmACP_DSP0_RUNSTALL 0x5091
+#define mmACP_DSP0_OCD_HALT_ON_RST 0x5092
+#define mmACP_DSP0_WAIT_MODE 0x5093
+#define mmACP_DSP0_VECT_SEL 0x5094
+#define mmACP_DSP0_DEBUG_REG1 0x5095
+#define mmACP_DSP0_DEBUG_REG2 0x5096
+#define mmACP_DSP0_DEBUG_REG3 0x5097
+#define mmACP_DSP1_CACHE_OFFSET0 0x509d
+#define mmACP_DSP1_CACHE_SIZE0 0x509e
+#define mmACP_DSP1_CACHE_OFFSET1 0x509f
+#define mmACP_DSP1_CACHE_SIZE1 0x50a0
+#define mmACP_DSP1_CACHE_OFFSET2 0x50a1
+#define mmACP_DSP1_CACHE_SIZE2 0x50a2
+#define mmACP_DSP1_CACHE_OFFSET3 0x50a3
+#define mmACP_DSP1_CACHE_SIZE3 0x50a4
+#define mmACP_DSP1_CACHE_OFFSET4 0x50a5
+#define mmACP_DSP1_CACHE_SIZE4 0x50a6
+#define mmACP_DSP1_CACHE_OFFSET5 0x50a7
+#define mmACP_DSP1_CACHE_SIZE5 0x50a8
+#define mmACP_DSP1_CACHE_OFFSET6 0x50a9
+#define mmACP_DSP1_CACHE_SIZE6 0x50aa
+#define mmACP_DSP1_CACHE_OFFSET7 0x50ab
+#define mmACP_DSP1_CACHE_SIZE7 0x50ac
+#define mmACP_DSP1_CACHE_OFFSET8 0x50ad
+#define mmACP_DSP1_CACHE_SIZE8 0x50ae
+#define mmACP_DSP1_NONCACHE_OFFSET0 0x50af
+#define mmACP_DSP1_NONCACHE_SIZE0 0x50b0
+#define mmACP_DSP1_NONCACHE_OFFSET1 0x50b1
+#define mmACP_DSP1_NONCACHE_SIZE1 0x50b2
+#define mmACP_DSP1_DEBUG_PC 0x50b3
+#define mmACP_DSP1_NMI_SEL 0x50b4
+#define mmACP_DSP1_CLKRST_CNTL 0x50b5
+#define mmACP_DSP1_RUNSTALL 0x50b6
+#define mmACP_DSP1_OCD_HALT_ON_RST 0x50b7
+#define mmACP_DSP1_WAIT_MODE 0x50b8
+#define mmACP_DSP1_VECT_SEL 0x50b9
+#define mmACP_DSP1_DEBUG_REG1 0x50ba
+#define mmACP_DSP1_DEBUG_REG2 0x50bb
+#define mmACP_DSP1_DEBUG_REG3 0x50bc
+#define mmACP_DSP2_CACHE_OFFSET0 0x50c2
+#define mmACP_DSP2_CACHE_SIZE0 0x50c3
+#define mmACP_DSP2_CACHE_OFFSET1 0x50c4
+#define mmACP_DSP2_CACHE_SIZE1 0x50c5
+#define mmACP_DSP2_CACHE_OFFSET2 0x50c6
+#define mmACP_DSP2_CACHE_SIZE2 0x50c7
+#define mmACP_DSP2_CACHE_OFFSET3 0x50c8
+#define mmACP_DSP2_CACHE_SIZE3 0x50c9
+#define mmACP_DSP2_CACHE_OFFSET4 0x50ca
+#define mmACP_DSP2_CACHE_SIZE4 0x50cb
+#define mmACP_DSP2_CACHE_OFFSET5 0x50cc
+#define mmACP_DSP2_CACHE_SIZE5 0x50cd
+#define mmACP_DSP2_CACHE_OFFSET6 0x50ce
+#define mmACP_DSP2_CACHE_SIZE6 0x50cf
+#define mmACP_DSP2_CACHE_OFFSET7 0x50d0
+#define mmACP_DSP2_CACHE_SIZE7 0x50d1
+#define mmACP_DSP2_CACHE_OFFSET8 0x50d2
+#define mmACP_DSP2_CACHE_SIZE8 0x50d3
+#define mmACP_DSP2_NONCACHE_OFFSET0 0x50d4
+#define mmACP_DSP2_NONCACHE_SIZE0 0x50d5
+#define mmACP_DSP2_NONCACHE_OFFSET1 0x50d6
+#define mmACP_DSP2_NONCACHE_SIZE1 0x50d7
+#define mmACP_DSP2_DEBUG_PC 0x50d8
+#define mmACP_DSP2_NMI_SEL 0x50d9
+#define mmACP_DSP2_CLKRST_CNTL 0x50da
+#define mmACP_DSP2_RUNSTALL 0x50db
+#define mmACP_DSP2_OCD_HALT_ON_RST 0x50dc
+#define mmACP_DSP2_WAIT_MODE 0x50dd
+#define mmACP_DSP2_VECT_SEL 0x50de
+#define mmACP_DSP2_DEBUG_REG1 0x50df
+#define mmACP_DSP2_DEBUG_REG2 0x50e0
+#define mmACP_DSP2_DEBUG_REG3 0x50e1
+#define mmACP_AXI2DAGB_ONION_CNTL 0x50e7
+#define mmACP_AXI2DAGB_ONION_ERR_STATUS_WR 0x50e8
+#define mmACP_AXI2DAGB_ONION_ERR_STATUS_RD 0x50e9
+#define mmACP_DAGB_Onion_TransPerf_Counter_Control 0x50ea
+#define mmACP_DAGB_Onion_Wr_TransPerf_Counter_Current 0x50eb
+#define mmACP_DAGB_Onion_Wr_TransPerf_Counter_Peak 0x50ec
+#define mmACP_DAGB_Onion_Rd_TransPerf_Counter_Current 0x50ed
+#define mmACP_DAGB_Onion_Rd_TransPerf_Counter_Peak 0x50ee
+#define mmACP_AXI2DAGB_GARLIC_CNTL 0x50f3
+#define mmACP_AXI2DAGB_GARLIC_ERR_STATUS_WR 0x50f4
+#define mmACP_AXI2DAGB_GARLIC_ERR_STATUS_RD 0x50f5
+#define mmACP_DAGB_Garlic_TransPerf_Counter_Control 0x50f6
+#define mmACP_DAGB_Garlic_Wr_TransPerf_Counter_Current 0x50f7
+#define mmACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak 0x50f8
+#define mmACP_DAGB_Garlic_Rd_TransPerf_Counter_Current 0x50f9
+#define mmACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak 0x50fa
+#define mmACP_DAGB_PAGE_SIZE_GRP_1 0x50ff
+#define mmACP_DAGB_BASE_ADDR_GRP_1 0x5100
+#define mmACP_DAGB_PAGE_SIZE_GRP_2 0x5101
+#define mmACP_DAGB_BASE_ADDR_GRP_2 0x5102
+#define mmACP_DAGB_PAGE_SIZE_GRP_3 0x5103
+#define mmACP_DAGB_BASE_ADDR_GRP_3 0x5104
+#define mmACP_DAGB_PAGE_SIZE_GRP_4 0x5105
+#define mmACP_DAGB_BASE_ADDR_GRP_4 0x5106
+#define mmACP_DAGB_PAGE_SIZE_GRP_5 0x5107
+#define mmACP_DAGB_BASE_ADDR_GRP_5 0x5108
+#define mmACP_DAGB_PAGE_SIZE_GRP_6 0x5109
+#define mmACP_DAGB_BASE_ADDR_GRP_6 0x510a
+#define mmACP_DAGB_PAGE_SIZE_GRP_7 0x510b
+#define mmACP_DAGB_BASE_ADDR_GRP_7 0x510c
+#define mmACP_DAGB_PAGE_SIZE_GRP_8 0x510d
+#define mmACP_DAGB_BASE_ADDR_GRP_8 0x510e
+#define mmACP_DAGB_ATU_CTRL 0x510f
+#define mmACP_CONTROL 0x5131
+#define mmACP_STATUS 0x5133
+#define mmACP_SOFT_RESET 0x5134
+#define mmACP_PwrMgmt_CNTL 0x5135
+#define mmACP_CAC_INDICATOR_CONTROL 0x5136
+#define mmACP_SMU_MAILBOX 0x5137
+#define mmACP_FUTURE_REG_SCLK_0 0x5138
+#define mmACP_FUTURE_REG_SCLK_1 0x5139
+#define mmACP_FUTURE_REG_SCLK_2 0x513a
+#define mmACP_FUTURE_REG_SCLK_3 0x513b
+#define mmACP_FUTURE_REG_SCLK_4 0x513c
+#define mmACP_DAGB_DEBUG_CNT_ENABLE 0x513d
+#define mmACP_DAGBG_WR_ASK_CNT 0x513e
+#define mmACP_DAGBG_WR_GO_CNT 0x513f
+#define mmACP_DAGBG_WR_EXP_RESP_CNT 0x5140
+#define mmACP_DAGBG_WR_ACTUAL_RESP_CNT 0x5141
+#define mmACP_DAGBG_RD_ASK_CNT 0x5142
+#define mmACP_DAGBG_RD_GO_CNT 0x5143
+#define mmACP_DAGBG_RD_EXP_RESP_CNT 0x5144
+#define mmACP_DAGBG_RD_ACTUAL_RESP_CNT 0x5145
+#define mmACP_DAGBO_WR_ASK_CNT 0x5146
+#define mmACP_DAGBO_WR_GO_CNT 0x5147
+#define mmACP_DAGBO_WR_EXP_RESP_CNT 0x5148
+#define mmACP_DAGBO_WR_ACTUAL_RESP_CNT 0x5149
+#define mmACP_DAGBO_RD_ASK_CNT 0x514a
+#define mmACP_DAGBO_RD_GO_CNT 0x514b
+#define mmACP_DAGBO_RD_EXP_RESP_CNT 0x514c
+#define mmACP_DAGBO_RD_ACTUAL_RESP_CNT 0x514d
+#define mmACP_BRB_CONTROL 0x5156
+#define mmACP_EXTERNAL_INTR_ENB 0x5157
+#define mmACP_EXTERNAL_INTR_CNTL 0x5158
+#define mmACP_ERROR_SOURCE_STS 0x5159
+#define mmACP_DSP_SW_INTR_TRIG 0x515a
+#define mmACP_DSP_SW_INTR_CNTL 0x515b
+#define mmACP_DAGBG_TIMEOUT_CNTL 0x515c
+#define mmACP_DAGBO_TIMEOUT_CNTL 0x515d
+#define mmACP_EXTERNAL_INTR_STAT 0x515e
+#define mmACP_DSP_SW_INTR_STAT 0x515f
+#define mmACP_DSP0_INTR_CNTL 0x5160
+#define mmACP_DSP0_INTR_STAT 0x5161
+#define mmACP_DSP0_TIMEOUT_CNTL 0x5162
+#define mmACP_DSP1_INTR_CNTL 0x5163
+#define mmACP_DSP1_INTR_STAT 0x5164
+#define mmACP_DSP1_TIMEOUT_CNTL 0x5165
+#define mmACP_DSP2_INTR_CNTL 0x5166
+#define mmACP_DSP2_INTR_STAT 0x5167
+#define mmACP_DSP2_TIMEOUT_CNTL 0x5168
+#define mmACP_DSP0_EXT_TIMER_CNTL 0x5169
+#define mmACP_DSP1_EXT_TIMER_CNTL 0x516a
+#define mmACP_DSP2_EXT_TIMER_CNTL 0x516b
+#define mmACP_AXI2DAGB_SEM_0 0x516c
+#define mmACP_AXI2DAGB_SEM_1 0x516d
+#define mmACP_AXI2DAGB_SEM_2 0x516e
+#define mmACP_AXI2DAGB_SEM_3 0x516f
+#define mmACP_AXI2DAGB_SEM_4 0x5170
+#define mmACP_AXI2DAGB_SEM_5 0x5171
+#define mmACP_AXI2DAGB_SEM_6 0x5172
+#define mmACP_AXI2DAGB_SEM_7 0x5173
+#define mmACP_AXI2DAGB_SEM_8 0x5174
+#define mmACP_AXI2DAGB_SEM_9 0x5175
+#define mmACP_AXI2DAGB_SEM_10 0x5176
+#define mmACP_AXI2DAGB_SEM_11 0x5177
+#define mmACP_AXI2DAGB_SEM_12 0x5178
+#define mmACP_AXI2DAGB_SEM_13 0x5179
+#define mmACP_AXI2DAGB_SEM_14 0x517a
+#define mmACP_AXI2DAGB_SEM_15 0x517b
+#define mmACP_AXI2DAGB_SEM_16 0x517c
+#define mmACP_AXI2DAGB_SEM_17 0x517d
+#define mmACP_AXI2DAGB_SEM_18 0x517e
+#define mmACP_AXI2DAGB_SEM_19 0x517f
+#define mmACP_AXI2DAGB_SEM_20 0x5180
+#define mmACP_AXI2DAGB_SEM_21 0x5181
+#define mmACP_AXI2DAGB_SEM_22 0x5182
+#define mmACP_AXI2DAGB_SEM_23 0x5183
+#define mmACP_AXI2DAGB_SEM_24 0x5184
+#define mmACP_AXI2DAGB_SEM_25 0x5185
+#define mmACP_AXI2DAGB_SEM_26 0x5186
+#define mmACP_AXI2DAGB_SEM_27 0x5187
+#define mmACP_AXI2DAGB_SEM_28 0x5188
+#define mmACP_AXI2DAGB_SEM_29 0x5189
+#define mmACP_AXI2DAGB_SEM_30 0x518a
+#define mmACP_AXI2DAGB_SEM_31 0x518b
+#define mmACP_AXI2DAGB_SEM_32 0x518c
+#define mmACP_AXI2DAGB_SEM_33 0x518d
+#define mmACP_AXI2DAGB_SEM_34 0x518e
+#define mmACP_AXI2DAGB_SEM_35 0x518f
+#define mmACP_AXI2DAGB_SEM_36 0x5190
+#define mmACP_AXI2DAGB_SEM_37 0x5191
+#define mmACP_AXI2DAGB_SEM_38 0x5192
+#define mmACP_AXI2DAGB_SEM_39 0x5193
+#define mmACP_AXI2DAGB_SEM_40 0x5194
+#define mmACP_AXI2DAGB_SEM_41 0x5195
+#define mmACP_AXI2DAGB_SEM_42 0x5196
+#define mmACP_AXI2DAGB_SEM_43 0x5197
+#define mmACP_AXI2DAGB_SEM_44 0x5198
+#define mmACP_AXI2DAGB_SEM_45 0x5199
+#define mmACP_AXI2DAGB_SEM_46 0x519a
+#define mmACP_AXI2DAGB_SEM_47 0x519b
+#define mmACP_SRBM_Client_Base_Addr 0x519c
+#define mmACP_SRBM_Client_RDDATA 0x519d
+#define mmACP_SRBM_Cycle_Sts 0x519e
+#define mmACP_SRBM_Targ_Idx_Addr 0x519f
+#define mmACP_SRBM_Targ_Idx_Data 0x51a0
+#define mmACP_SEMA_ADDR_LOW 0x51a1
+#define mmACP_SEMA_ADDR_HIGH 0x51a2
+#define mmACP_SEMA_CMD 0x51a3
+#define mmACP_SEMA_STS 0x51a4
+#define mmACP_SEMA_REQ 0x51a5
+#define mmACP_FW_STATUS 0x51a6
+#define mmACP_FUTURE_REG_ACLK_0 0x51a7
+#define mmACP_FUTURE_REG_ACLK_1 0x51a8
+#define mmACP_FUTURE_REG_ACLK_2 0x51a9
+#define mmACP_FUTURE_REG_ACLK_3 0x51aa
+#define mmACP_FUTURE_REG_ACLK_4 0x51ab
+#define mmACP_TIMER 0x51ac
+#define mmACP_TIMER_CNTL 0x51ad
+#define mmACP_DSP0_TIMER 0x51ae
+#define mmACP_DSP1_TIMER 0x51af
+#define mmACP_DSP2_TIMER 0x51b0
+#define mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH 0x51b1
+#define mmACP_I2S_TRANSMIT_BYTE_CNT_LOW 0x51b2
+#define mmACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH 0x51b3
+#define mmACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW 0x51b4
+#define mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH 0x51b5
+#define mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW 0x51b6
+#define mmACP_DSP0_CS_STATE 0x51b7
+#define mmACP_DSP1_CS_STATE 0x51b8
+#define mmACP_DSP2_CS_STATE 0x51b9
+#define mmACP_SCRATCH_REG_BASE_ADDR 0x51ba
+#define mmCC_ACP_EFUSE 0x51c8
+#define mmACP_PGFSM_RETAIN_REG 0x51c9
+#define mmACP_PGFSM_CONFIG_REG 0x51ca
+#define mmACP_PGFSM_WRITE_REG 0x51cb
+#define mmACP_PGFSM_READ_REG_0 0x51cc
+#define mmACP_PGFSM_READ_REG_1 0x51cd
+#define mmACP_PGFSM_READ_REG_2 0x51ce
+#define mmACP_PGFSM_READ_REG_3 0x51cf
+#define mmACP_PGFSM_READ_REG_4 0x51d0
+#define mmACP_PGFSM_READ_REG_5 0x51d1
+#define mmACP_IP_PGFSM_ENABLE 0x51d2
+#define mmACP_I2S_PIN_CONFIG 0x51d3
+#define mmACP_AZALIA_I2S_SELECT 0x51d4
+#define mmACP_CHIP_PKG_FOR_PAD_ISOLATION 0x51d5
+#define mmACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL 0x51d6
+#define mmACP_BT_UART_PAD_SEL 0x51d7
+#define mmACP_SCRATCH_REG_0 0x52c0
+#define mmACP_SCRATCH_REG_1 0x52c1
+#define mmACP_SCRATCH_REG_2 0x52c2
+#define mmACP_SCRATCH_REG_3 0x52c3
+#define mmACP_SCRATCH_REG_4 0x52c4
+#define mmACP_SCRATCH_REG_5 0x52c5
+#define mmACP_SCRATCH_REG_6 0x52c6
+#define mmACP_SCRATCH_REG_7 0x52c7
+#define mmACP_SCRATCH_REG_8 0x52c8
+#define mmACP_SCRATCH_REG_9 0x52c9
+#define mmACP_SCRATCH_REG_10 0x52ca
+#define mmACP_SCRATCH_REG_11 0x52cb
+#define mmACP_SCRATCH_REG_12 0x52cc
+#define mmACP_SCRATCH_REG_13 0x52cd
+#define mmACP_SCRATCH_REG_14 0x52ce
+#define mmACP_SCRATCH_REG_15 0x52cf
+#define mmACP_SCRATCH_REG_16 0x52d0
+#define mmACP_SCRATCH_REG_17 0x52d1
+#define mmACP_SCRATCH_REG_18 0x52d2
+#define mmACP_SCRATCH_REG_19 0x52d3
+#define mmACP_SCRATCH_REG_20 0x52d4
+#define mmACP_SCRATCH_REG_21 0x52d5
+#define mmACP_SCRATCH_REG_22 0x52d6
+#define mmACP_SCRATCH_REG_23 0x52d7
+#define mmACP_SCRATCH_REG_24 0x52d8
+#define mmACP_SCRATCH_REG_25 0x52d9
+#define mmACP_SCRATCH_REG_26 0x52da
+#define mmACP_SCRATCH_REG_27 0x52db
+#define mmACP_SCRATCH_REG_28 0x52dc
+#define mmACP_SCRATCH_REG_29 0x52dd
+#define mmACP_SCRATCH_REG_30 0x52de
+#define mmACP_SCRATCH_REG_31 0x52df
+#define mmACP_SCRATCH_REG_32 0x52e0
+#define mmACP_SCRATCH_REG_33 0x52e1
+#define mmACP_SCRATCH_REG_34 0x52e2
+#define mmACP_SCRATCH_REG_35 0x52e3
+#define mmACP_SCRATCH_REG_36 0x52e4
+#define mmACP_SCRATCH_REG_37 0x52e5
+#define mmACP_SCRATCH_REG_38 0x52e6
+#define mmACP_SCRATCH_REG_39 0x52e7
+#define mmACP_SCRATCH_REG_40 0x52e8
+#define mmACP_SCRATCH_REG_41 0x52e9
+#define mmACP_SCRATCH_REG_42 0x52ea
+#define mmACP_SCRATCH_REG_43 0x52eb
+#define mmACP_SCRATCH_REG_44 0x52ec
+#define mmACP_SCRATCH_REG_45 0x52ed
+#define mmACP_SCRATCH_REG_46 0x52ee
+#define mmACP_SCRATCH_REG_47 0x52ef
+#define mmACP_VOICE_WAKEUP_ENABLE 0x51e8
+#define mmACP_VOICE_WAKEUP_STATUS 0x51e9
+#define mmI2S_VOICE_WAKEUP_LOWER_THRESHOLD 0x51ea
+#define mmI2S_VOICE_WAKEUP_HIGHER_THRESHOLD 0x51eb
+#define mmI2S_VOICE_WAKEUP_NO_OF_SAMPLES 0x51ec
+#define mmI2S_VOICE_WAKEUP_NO_OF_PEAKS 0x51ed
+#define mmI2S_VOICE_WAKEUP_DURATION_OF_N_PEAKS 0x51ee
+#define mmI2S_VOICE_WAKEUP_BITCLK_TOGGLE_DETECTION 0x51ef
+#define mmI2S_VOICE_WAKEUP_DATA_PATH_SWITCH 0x51f0
+#define mmI2S_VOICE_WAKEUP_DATA_POINTER 0x51f1
+#define mmI2S_VOICE_WAKEUP_AUTH_MATCH 0x51f2
+#define mmI2S_VOICE_WAKEUP_8KB_WRAP 0x51f3
+#define mmACP_I2S_RECEIVED_BYTE_CNT_HIGH 0x51f4
+#define mmACP_I2S_RECEIVED_BYTE_CNT_LOW 0x51f5
+#define mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_HIGH 0x51f6
+#define mmACP_I2S_MICSP_TRANSMIT_BYTE_CNT_LOW 0x51f7
+#define mmACP_MEM_SHUT_DOWN_REQ_LO 0x51f8
+#define mmACP_MEM_SHUT_DOWN_REQ_HI 0x51f9
+#define mmACP_MEM_SHUT_DOWN_STS_LO 0x51fa
+#define mmACP_MEM_SHUT_DOWN_STS_HI 0x51fb
+#define mmACP_MEM_DEEP_SLEEP_REQ_LO 0x51fc
+#define mmACP_MEM_DEEP_SLEEP_REQ_HI 0x51fd
+#define mmACP_MEM_DEEP_SLEEP_STS_LO 0x51fe
+#define mmACP_MEM_DEEP_SLEEP_STS_HI 0x51ff
+#define mmACP_MEM_WAKEUP_FROM_SHUT_DOWN_LO 0x5200
+#define mmACP_MEM_WAKEUP_FROM_SHUT_DOWN_HI 0x5201
+#define mmACP_MEM_WAKEUP_FROM_SLEEP_LO 0x5202
+#define mmACP_MEM_WAKEUP_FROM_SLEEP_HI 0x5203
+#define mmACP_I2SSP_IER 0x5210
+#define mmACP_I2SSP_IRER 0x5211
+#define mmACP_I2SSP_ITER 0x5212
+#define mmACP_I2SSP_CER 0x5213
+#define mmACP_I2SSP_CCR 0x5214
+#define mmACP_I2SSP_RXFFR 0x5215
+#define mmACP_I2SSP_TXFFR 0x5216
+#define mmACP_I2SSP_LRBR0 0x5218
+#define mmACP_I2SSP_RRBR0 0x5219
+#define mmACP_I2SSP_RER0 0x521a
+#define mmACP_I2SSP_TER0 0x521b
+#define mmACP_I2SSP_RCR0 0x521c
+#define mmACP_I2SSP_TCR0 0x521d
+#define mmACP_I2SSP_ISR0 0x521e
+#define mmACP_I2SSP_IMR0 0x521f
+#define mmACP_I2SSP_ROR0 0x5220
+#define mmACP_I2SSP_TOR0 0x5221
+#define mmACP_I2SSP_RFCR0 0x5222
+#define mmACP_I2SSP_TFCR0 0x5223
+#define mmACP_I2SSP_RFF0 0x5224
+#define mmACP_I2SSP_TFF0 0x5225
+#define mmACP_I2SSP_RXDMA 0x5226
+#define mmACP_I2SSP_RRXDMA 0x5227
+#define mmACP_I2SSP_TXDMA 0x5228
+#define mmACP_I2SSP_RTXDMA 0x5229
+#define mmACP_I2SSP_COMP_PARAM_2 0x522a
+#define mmACP_I2SSP_COMP_PARAM_1 0x522b
+#define mmACP_I2SSP_COMP_VERSION 0x522c
+#define mmACP_I2SSP_COMP_TYPE 0x522d
+#define mmACP_I2SMICSP_IER 0x522e
+#define mmACP_I2SMICSP_IRER 0x522f
+#define mmACP_I2SMICSP_ITER 0x5230
+#define mmACP_I2SMICSP_CER 0x5231
+#define mmACP_I2SMICSP_CCR 0x5232
+#define mmACP_I2SMICSP_RXFFR 0x5233
+#define mmACP_I2SMICSP_TXFFR 0x5234
+#define mmACP_I2SMICSP_LRBR0 0x5236
+#define mmACP_I2SMICSP_RRBR0 0x5237
+#define mmACP_I2SMICSP_RER0 0x5238
+#define mmACP_I2SMICSP_TER0 0x5239
+#define mmACP_I2SMICSP_RCR0 0x523a
+#define mmACP_I2SMICSP_TCR0 0x523b
+#define mmACP_I2SMICSP_ISR0 0x523c
+#define mmACP_I2SMICSP_IMR0 0x523d
+#define mmACP_I2SMICSP_ROR0 0x523e
+#define mmACP_I2SMICSP_TOR0 0x523f
+#define mmACP_I2SMICSP_RFCR0 0x5240
+#define mmACP_I2SMICSP_TFCR0 0x5241
+#define mmACP_I2SMICSP_RFF0 0x5242
+#define mmACP_I2SMICSP_TFF0 0x5243
+#define mmACP_I2SMICSP_LRBR1 0x5246
+#define mmACP_I2SMICSP_RRBR1 0x5247
+#define mmACP_I2SMICSP_RER1 0x5248
+#define mmACP_I2SMICSP_TER1 0x5249
+#define mmACP_I2SMICSP_RCR1 0x524a
+#define mmACP_I2SMICSP_TCR1 0x524b
+#define mmACP_I2SMICSP_ISR1 0x524c
+#define mmACP_I2SMICSP_IMR1 0x524d
+#define mmACP_I2SMICSP_ROR1 0x524e
+#define mmACP_I2SMICSP_TOR1 0x524f
+#define mmACP_I2SMICSP_RFCR1 0x5250
+#define mmACP_I2SMICSP_TFCR1 0x5251
+#define mmACP_I2SMICSP_RFF1 0x5252
+#define mmACP_I2SMICSP_TFF1 0x5253
+#define mmACP_I2SMICSP_RXDMA 0x5254
+#define mmACP_I2SMICSP_RRXDMA 0x5255
+#define mmACP_I2SMICSP_TXDMA 0x5256
+#define mmACP_I2SMICSP_RTXDMA 0x5257
+#define mmACP_I2SMICSP_COMP_PARAM_2 0x5258
+#define mmACP_I2SMICSP_COMP_PARAM_1 0x5259
+#define mmACP_I2SMICSP_COMP_VERSION 0x525a
+#define mmACP_I2SMICSP_COMP_TYPE 0x525b
+#define mmACP_I2SBT_IER 0x525c
+#define mmACP_I2SBT_IRER 0x525d
+#define mmACP_I2SBT_ITER 0x525e
+#define mmACP_I2SBT_CER 0x525f
+#define mmACP_I2SBT_CCR 0x5260
+#define mmACP_I2SBT_RXFFR 0x5261
+#define mmACP_I2SBT_TXFFR 0x5262
+#define mmACP_I2SBT_LRBR0 0x5264
+#define mmACP_I2SBT_RRBR0 0x5265
+#define mmACP_I2SBT_RER0 0x5266
+#define mmACP_I2SBT_TER0 0x5267
+#define mmACP_I2SBT_RCR0 0x5268
+#define mmACP_I2SBT_TCR0 0x5269
+#define mmACP_I2SBT_ISR0 0x526a
+#define mmACP_I2SBT_IMR0 0x526b
+#define mmACP_I2SBT_ROR0 0x526c
+#define mmACP_I2SBT_TOR0 0x526d
+#define mmACP_I2SBT_RFCR0 0x526e
+#define mmACP_I2SBT_TFCR0 0x526f
+#define mmACP_I2SBT_RFF0 0x5270
+#define mmACP_I2SBT_TFF0 0x5271
+#define mmACP_I2SBT_LRBR1 0x5274
+#define mmACP_I2SBT_RRBR1 0x5275
+#define mmACP_I2SBT_RER1 0x5276
+#define mmACP_I2SBT_TER1 0x5277
+#define mmACP_I2SBT_RCR1 0x5278
+#define mmACP_I2SBT_TCR1 0x5279
+#define mmACP_I2SBT_ISR1 0x527a
+#define mmACP_I2SBT_IMR1 0x527b
+#define mmACP_I2SBT_ROR1 0x527c
+#define mmACP_I2SBT_TOR1 0x527d
+#define mmACP_I2SBT_RFCR1 0x527e
+#define mmACP_I2SBT_TFCR1 0x527f
+#define mmACP_I2SBT_RFF1 0x5280
+#define mmACP_I2SBT_TFF1 0x5281
+#define mmACP_I2SBT_RXDMA 0x5282
+#define mmACP_I2SBT_RRXDMA 0x5283
+#define mmACP_I2SBT_TXDMA 0x5284
+#define mmACP_I2SBT_RTXDMA 0x5285
+#define mmACP_I2SBT_COMP_PARAM_2 0x5286
+#define mmACP_I2SBT_COMP_PARAM_1 0x5287
+#define mmACP_I2SBT_COMP_VERSION 0x5288
+#define mmACP_I2SBT_COMP_TYPE 0x5289
+
+#endif /* ACP_2_2_D_H */
diff --git a/sound/soc/amd/include/acp_2_2_enum.h b/sound/soc/amd/include/acp_2_2_enum.h
new file mode 100644
index 000000000000..f3577c851086
--- /dev/null
+++ b/sound/soc/amd/include/acp_2_2_enum.h
@@ -0,0 +1,1068 @@
+/*
+ * ACP_2_2 Register documentation
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) 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 ACP_2_2_ENUM_H
+#define ACP_2_2_ENUM_H
+
+typedef enum DebugBlockId {
+ DBG_BLOCK_ID_RESERVED = 0x0,
+ DBG_BLOCK_ID_DBG = 0x1,
+ DBG_BLOCK_ID_VMC = 0x2,
+ DBG_BLOCK_ID_PDMA = 0x3,
+ DBG_BLOCK_ID_CG = 0x4,
+ DBG_BLOCK_ID_SRBM = 0x5,
+ DBG_BLOCK_ID_GRBM = 0x6,
+ DBG_BLOCK_ID_RLC = 0x7,
+ DBG_BLOCK_ID_CSC = 0x8,
+ DBG_BLOCK_ID_SEM = 0x9,
+ DBG_BLOCK_ID_IH = 0xa,
+ DBG_BLOCK_ID_SC = 0xb,
+ DBG_BLOCK_ID_SQ = 0xc,
+ DBG_BLOCK_ID_UVDU = 0xd,
+ DBG_BLOCK_ID_SQA = 0xe,
+ DBG_BLOCK_ID_SDMA0 = 0xf,
+ DBG_BLOCK_ID_SDMA1 = 0x10,
+ DBG_BLOCK_ID_SPIM = 0x11,
+ DBG_BLOCK_ID_GDS = 0x12,
+ DBG_BLOCK_ID_VC0 = 0x13,
+ DBG_BLOCK_ID_VC1 = 0x14,
+ DBG_BLOCK_ID_PA0 = 0x15,
+ DBG_BLOCK_ID_PA1 = 0x16,
+ DBG_BLOCK_ID_CP0 = 0x17,
+ DBG_BLOCK_ID_CP1 = 0x18,
+ DBG_BLOCK_ID_CP2 = 0x19,
+ DBG_BLOCK_ID_XBR = 0x1a,
+ DBG_BLOCK_ID_UVDM = 0x1b,
+ DBG_BLOCK_ID_VGT0 = 0x1c,
+ DBG_BLOCK_ID_VGT1 = 0x1d,
+ DBG_BLOCK_ID_IA = 0x1e,
+ DBG_BLOCK_ID_SXM0 = 0x1f,
+ DBG_BLOCK_ID_SXM1 = 0x20,
+ DBG_BLOCK_ID_SCT0 = 0x21,
+ DBG_BLOCK_ID_SCT1 = 0x22,
+ DBG_BLOCK_ID_SPM0 = 0x23,
+ DBG_BLOCK_ID_SPM1 = 0x24,
+ DBG_BLOCK_ID_UNUSED0 = 0x25,
+ DBG_BLOCK_ID_UNUSED1 = 0x26,
+ DBG_BLOCK_ID_TCAA = 0x27,
+ DBG_BLOCK_ID_TCAB = 0x28,
+ DBG_BLOCK_ID_TCCA = 0x29,
+ DBG_BLOCK_ID_TCCB = 0x2a,
+ DBG_BLOCK_ID_MCC0 = 0x2b,
+ DBG_BLOCK_ID_MCC1 = 0x2c,
+ DBG_BLOCK_ID_MCC2 = 0x2d,
+ DBG_BLOCK_ID_MCC3 = 0x2e,
+ DBG_BLOCK_ID_SXS0 = 0x2f,
+ DBG_BLOCK_ID_SXS1 = 0x30,
+ DBG_BLOCK_ID_SXS2 = 0x31,
+ DBG_BLOCK_ID_SXS3 = 0x32,
+ DBG_BLOCK_ID_SXS4 = 0x33,
+ DBG_BLOCK_ID_SXS5 = 0x34,
+ DBG_BLOCK_ID_SXS6 = 0x35,
+ DBG_BLOCK_ID_SXS7 = 0x36,
+ DBG_BLOCK_ID_SXS8 = 0x37,
+ DBG_BLOCK_ID_SXS9 = 0x38,
+ DBG_BLOCK_ID_BCI0 = 0x39,
+ DBG_BLOCK_ID_BCI1 = 0x3a,
+ DBG_BLOCK_ID_BCI2 = 0x3b,
+ DBG_BLOCK_ID_BCI3 = 0x3c,
+ DBG_BLOCK_ID_MCB = 0x3d,
+ DBG_BLOCK_ID_UNUSED6 = 0x3e,
+ DBG_BLOCK_ID_SQA00 = 0x3f,
+ DBG_BLOCK_ID_SQA01 = 0x40,
+ DBG_BLOCK_ID_SQA02 = 0x41,
+ DBG_BLOCK_ID_SQA10 = 0x42,
+ DBG_BLOCK_ID_SQA11 = 0x43,
+ DBG_BLOCK_ID_SQA12 = 0x44,
+ DBG_BLOCK_ID_UNUSED7 = 0x45,
+ DBG_BLOCK_ID_UNUSED8 = 0x46,
+ DBG_BLOCK_ID_SQB00 = 0x47,
+ DBG_BLOCK_ID_SQB01 = 0x48,
+ DBG_BLOCK_ID_SQB10 = 0x49,
+ DBG_BLOCK_ID_SQB11 = 0x4a,
+ DBG_BLOCK_ID_SQ00 = 0x4b,
+ DBG_BLOCK_ID_SQ01 = 0x4c,
+ DBG_BLOCK_ID_SQ10 = 0x4d,
+ DBG_BLOCK_ID_SQ11 = 0x4e,
+ DBG_BLOCK_ID_CB00 = 0x4f,
+ DBG_BLOCK_ID_CB01 = 0x50,
+ DBG_BLOCK_ID_CB02 = 0x51,
+ DBG_BLOCK_ID_CB03 = 0x52,
+ DBG_BLOCK_ID_CB04 = 0x53,
+ DBG_BLOCK_ID_UNUSED9 = 0x54,
+ DBG_BLOCK_ID_UNUSED10 = 0x55,
+ DBG_BLOCK_ID_UNUSED11 = 0x56,
+ DBG_BLOCK_ID_CB10 = 0x57,
+ DBG_BLOCK_ID_CB11 = 0x58,
+ DBG_BLOCK_ID_CB12 = 0x59,
+ DBG_BLOCK_ID_CB13 = 0x5a,
+ DBG_BLOCK_ID_CB14 = 0x5b,
+ DBG_BLOCK_ID_UNUSED12 = 0x5c,
+ DBG_BLOCK_ID_UNUSED13 = 0x5d,
+ DBG_BLOCK_ID_UNUSED14 = 0x5e,
+ DBG_BLOCK_ID_TCP0 = 0x5f,
+ DBG_BLOCK_ID_TCP1 = 0x60,
+ DBG_BLOCK_ID_TCP2 = 0x61,
+ DBG_BLOCK_ID_TCP3 = 0x62,
+ DBG_BLOCK_ID_TCP4 = 0x63,
+ DBG_BLOCK_ID_TCP5 = 0x64,
+ DBG_BLOCK_ID_TCP6 = 0x65,
+ DBG_BLOCK_ID_TCP7 = 0x66,
+ DBG_BLOCK_ID_TCP8 = 0x67,
+ DBG_BLOCK_ID_TCP9 = 0x68,
+ DBG_BLOCK_ID_TCP10 = 0x69,
+ DBG_BLOCK_ID_TCP11 = 0x6a,
+ DBG_BLOCK_ID_TCP12 = 0x6b,
+ DBG_BLOCK_ID_TCP13 = 0x6c,
+ DBG_BLOCK_ID_TCP14 = 0x6d,
+ DBG_BLOCK_ID_TCP15 = 0x6e,
+ DBG_BLOCK_ID_TCP16 = 0x6f,
+ DBG_BLOCK_ID_TCP17 = 0x70,
+ DBG_BLOCK_ID_TCP18 = 0x71,
+ DBG_BLOCK_ID_TCP19 = 0x72,
+ DBG_BLOCK_ID_TCP20 = 0x73,
+ DBG_BLOCK_ID_TCP21 = 0x74,
+ DBG_BLOCK_ID_TCP22 = 0x75,
+ DBG_BLOCK_ID_TCP23 = 0x76,
+ DBG_BLOCK_ID_TCP_RESERVED0 = 0x77,
+ DBG_BLOCK_ID_TCP_RESERVED1 = 0x78,
+ DBG_BLOCK_ID_TCP_RESERVED2 = 0x79,
+ DBG_BLOCK_ID_TCP_RESERVED3 = 0x7a,
+ DBG_BLOCK_ID_TCP_RESERVED4 = 0x7b,
+ DBG_BLOCK_ID_TCP_RESERVED5 = 0x7c,
+ DBG_BLOCK_ID_TCP_RESERVED6 = 0x7d,
+ DBG_BLOCK_ID_TCP_RESERVED7 = 0x7e,
+ DBG_BLOCK_ID_DB00 = 0x7f,
+ DBG_BLOCK_ID_DB01 = 0x80,
+ DBG_BLOCK_ID_DB02 = 0x81,
+ DBG_BLOCK_ID_DB03 = 0x82,
+ DBG_BLOCK_ID_DB04 = 0x83,
+ DBG_BLOCK_ID_UNUSED15 = 0x84,
+ DBG_BLOCK_ID_UNUSED16 = 0x85,
+ DBG_BLOCK_ID_UNUSED17 = 0x86,
+ DBG_BLOCK_ID_DB10 = 0x87,
+ DBG_BLOCK_ID_DB11 = 0x88,
+ DBG_BLOCK_ID_DB12 = 0x89,
+ DBG_BLOCK_ID_DB13 = 0x8a,
+ DBG_BLOCK_ID_DB14 = 0x8b,
+ DBG_BLOCK_ID_UNUSED18 = 0x8c,
+ DBG_BLOCK_ID_UNUSED19 = 0x8d,
+ DBG_BLOCK_ID_UNUSED20 = 0x8e,
+ DBG_BLOCK_ID_TCC0 = 0x8f,
+ DBG_BLOCK_ID_TCC1 = 0x90,
+ DBG_BLOCK_ID_TCC2 = 0x91,
+ DBG_BLOCK_ID_TCC3 = 0x92,
+ DBG_BLOCK_ID_TCC4 = 0x93,
+ DBG_BLOCK_ID_TCC5 = 0x94,
+ DBG_BLOCK_ID_TCC6 = 0x95,
+ DBG_BLOCK_ID_TCC7 = 0x96,
+ DBG_BLOCK_ID_SPS00 = 0x97,
+ DBG_BLOCK_ID_SPS01 = 0x98,
+ DBG_BLOCK_ID_SPS02 = 0x99,
+ DBG_BLOCK_ID_SPS10 = 0x9a,
+ DBG_BLOCK_ID_SPS11 = 0x9b,
+ DBG_BLOCK_ID_SPS12 = 0x9c,
+ DBG_BLOCK_ID_UNUSED21 = 0x9d,
+ DBG_BLOCK_ID_UNUSED22 = 0x9e,
+ DBG_BLOCK_ID_TA00 = 0x9f,
+ DBG_BLOCK_ID_TA01 = 0xa0,
+ DBG_BLOCK_ID_TA02 = 0xa1,
+ DBG_BLOCK_ID_TA03 = 0xa2,
+ DBG_BLOCK_ID_TA04 = 0xa3,
+ DBG_BLOCK_ID_TA05 = 0xa4,
+ DBG_BLOCK_ID_TA06 = 0xa5,
+ DBG_BLOCK_ID_TA07 = 0xa6,
+ DBG_BLOCK_ID_TA08 = 0xa7,
+ DBG_BLOCK_ID_TA09 = 0xa8,
+ DBG_BLOCK_ID_TA0A = 0xa9,
+ DBG_BLOCK_ID_TA0B = 0xaa,
+ DBG_BLOCK_ID_UNUSED23 = 0xab,
+ DBG_BLOCK_ID_UNUSED24 = 0xac,
+ DBG_BLOCK_ID_UNUSED25 = 0xad,
+ DBG_BLOCK_ID_UNUSED26 = 0xae,
+ DBG_BLOCK_ID_TA10 = 0xaf,
+ DBG_BLOCK_ID_TA11 = 0xb0,
+ DBG_BLOCK_ID_TA12 = 0xb1,
+ DBG_BLOCK_ID_TA13 = 0xb2,
+ DBG_BLOCK_ID_TA14 = 0xb3,
+ DBG_BLOCK_ID_TA15 = 0xb4,
+ DBG_BLOCK_ID_TA16 = 0xb5,
+ DBG_BLOCK_ID_TA17 = 0xb6,
+ DBG_BLOCK_ID_TA18 = 0xb7,
+ DBG_BLOCK_ID_TA19 = 0xb8,
+ DBG_BLOCK_ID_TA1A = 0xb9,
+ DBG_BLOCK_ID_TA1B = 0xba,
+ DBG_BLOCK_ID_UNUSED27 = 0xbb,
+ DBG_BLOCK_ID_UNUSED28 = 0xbc,
+ DBG_BLOCK_ID_UNUSED29 = 0xbd,
+ DBG_BLOCK_ID_UNUSED30 = 0xbe,
+ DBG_BLOCK_ID_TD00 = 0xbf,
+ DBG_BLOCK_ID_TD01 = 0xc0,
+ DBG_BLOCK_ID_TD02 = 0xc1,
+ DBG_BLOCK_ID_TD03 = 0xc2,
+ DBG_BLOCK_ID_TD04 = 0xc3,
+ DBG_BLOCK_ID_TD05 = 0xc4,
+ DBG_BLOCK_ID_TD06 = 0xc5,
+ DBG_BLOCK_ID_TD07 = 0xc6,
+ DBG_BLOCK_ID_TD08 = 0xc7,
+ DBG_BLOCK_ID_TD09 = 0xc8,
+ DBG_BLOCK_ID_TD0A = 0xc9,
+ DBG_BLOCK_ID_TD0B = 0xca,
+ DBG_BLOCK_ID_UNUSED31 = 0xcb,
+ DBG_BLOCK_ID_UNUSED32 = 0xcc,
+ DBG_BLOCK_ID_UNUSED33 = 0xcd,
+ DBG_BLOCK_ID_UNUSED34 = 0xce,
+ DBG_BLOCK_ID_TD10 = 0xcf,
+ DBG_BLOCK_ID_TD11 = 0xd0,
+ DBG_BLOCK_ID_TD12 = 0xd1,
+ DBG_BLOCK_ID_TD13 = 0xd2,
+ DBG_BLOCK_ID_TD14 = 0xd3,
+ DBG_BLOCK_ID_TD15 = 0xd4,
+ DBG_BLOCK_ID_TD16 = 0xd5,
+ DBG_BLOCK_ID_TD17 = 0xd6,
+ DBG_BLOCK_ID_TD18 = 0xd7,
+ DBG_BLOCK_ID_TD19 = 0xd8,
+ DBG_BLOCK_ID_TD1A = 0xd9,
+ DBG_BLOCK_ID_TD1B = 0xda,
+ DBG_BLOCK_ID_UNUSED35 = 0xdb,
+ DBG_BLOCK_ID_UNUSED36 = 0xdc,
+ DBG_BLOCK_ID_UNUSED37 = 0xdd,
+ DBG_BLOCK_ID_UNUSED38 = 0xde,
+ DBG_BLOCK_ID_LDS00 = 0xdf,
+ DBG_BLOCK_ID_LDS01 = 0xe0,
+ DBG_BLOCK_ID_LDS02 = 0xe1,
+ DBG_BLOCK_ID_LDS03 = 0xe2,
+ DBG_BLOCK_ID_LDS04 = 0xe3,
+ DBG_BLOCK_ID_LDS05 = 0xe4,
+ DBG_BLOCK_ID_LDS06 = 0xe5,
+ DBG_BLOCK_ID_LDS07 = 0xe6,
+ DBG_BLOCK_ID_LDS08 = 0xe7,
+ DBG_BLOCK_ID_LDS09 = 0xe8,
+ DBG_BLOCK_ID_LDS0A = 0xe9,
+ DBG_BLOCK_ID_LDS0B = 0xea,
+ DBG_BLOCK_ID_UNUSED39 = 0xeb,
+ DBG_BLOCK_ID_UNUSED40 = 0xec,
+ DBG_BLOCK_ID_UNUSED41 = 0xed,
+ DBG_BLOCK_ID_UNUSED42 = 0xee,
+ DBG_BLOCK_ID_LDS10 = 0xef,
+ DBG_BLOCK_ID_LDS11 = 0xf0,
+ DBG_BLOCK_ID_LDS12 = 0xf1,
+ DBG_BLOCK_ID_LDS13 = 0xf2,
+ DBG_BLOCK_ID_LDS14 = 0xf3,
+ DBG_BLOCK_ID_LDS15 = 0xf4,
+ DBG_BLOCK_ID_LDS16 = 0xf5,
+ DBG_BLOCK_ID_LDS17 = 0xf6,
+ DBG_BLOCK_ID_LDS18 = 0xf7,
+ DBG_BLOCK_ID_LDS19 = 0xf8,
+ DBG_BLOCK_ID_LDS1A = 0xf9,
+ DBG_BLOCK_ID_LDS1B = 0xfa,
+ DBG_BLOCK_ID_UNUSED43 = 0xfb,
+ DBG_BLOCK_ID_UNUSED44 = 0xfc,
+ DBG_BLOCK_ID_UNUSED45 = 0xfd,
+ DBG_BLOCK_ID_UNUSED46 = 0xfe,
+} DebugBlockId;
+typedef enum DebugBlockId_BY2 {
+ DBG_BLOCK_ID_RESERVED_BY2 = 0x0,
+ DBG_BLOCK_ID_VMC_BY2 = 0x1,
+ DBG_BLOCK_ID_UNUSED0_BY2 = 0x2,
+ DBG_BLOCK_ID_GRBM_BY2 = 0x3,
+ DBG_BLOCK_ID_CSC_BY2 = 0x4,
+ DBG_BLOCK_ID_IH_BY2 = 0x5,
+ DBG_BLOCK_ID_SQ_BY2 = 0x6,
+ DBG_BLOCK_ID_UVD_BY2 = 0x7,
+ DBG_BLOCK_ID_SDMA0_BY2 = 0x8,
+ DBG_BLOCK_ID_SPIM_BY2 = 0x9,
+ DBG_BLOCK_ID_VC0_BY2 = 0xa,
+ DBG_BLOCK_ID_PA_BY2 = 0xb,
+ DBG_BLOCK_ID_CP0_BY2 = 0xc,
+ DBG_BLOCK_ID_CP2_BY2 = 0xd,
+ DBG_BLOCK_ID_PC0_BY2 = 0xe,
+ DBG_BLOCK_ID_BCI0_BY2 = 0xf,
+ DBG_BLOCK_ID_SXM0_BY2 = 0x10,
+ DBG_BLOCK_ID_SCT0_BY2 = 0x11,
+ DBG_BLOCK_ID_SPM0_BY2 = 0x12,
+ DBG_BLOCK_ID_BCI2_BY2 = 0x13,
+ DBG_BLOCK_ID_TCA_BY2 = 0x14,
+ DBG_BLOCK_ID_TCCA_BY2 = 0x15,
+ DBG_BLOCK_ID_MCC_BY2 = 0x16,
+ DBG_BLOCK_ID_MCC2_BY2 = 0x17,
+ DBG_BLOCK_ID_MCD_BY2 = 0x18,
+ DBG_BLOCK_ID_MCD2_BY2 = 0x19,
+ DBG_BLOCK_ID_MCD4_BY2 = 0x1a,
+ DBG_BLOCK_ID_MCB_BY2 = 0x1b,
+ DBG_BLOCK_ID_SQA_BY2 = 0x1c,
+ DBG_BLOCK_ID_SQA02_BY2 = 0x1d,
+ DBG_BLOCK_ID_SQA11_BY2 = 0x1e,
+ DBG_BLOCK_ID_UNUSED8_BY2 = 0x1f,
+ DBG_BLOCK_ID_SQB_BY2 = 0x20,
+ DBG_BLOCK_ID_SQB10_BY2 = 0x21,
+ DBG_BLOCK_ID_UNUSED10_BY2 = 0x22,
+ DBG_BLOCK_ID_UNUSED12_BY2 = 0x23,
+ DBG_BLOCK_ID_CB_BY2 = 0x24,
+ DBG_BLOCK_ID_CB02_BY2 = 0x25,
+ DBG_BLOCK_ID_CB10_BY2 = 0x26,
+ DBG_BLOCK_ID_CB12_BY2 = 0x27,
+ DBG_BLOCK_ID_SXS_BY2 = 0x28,
+ DBG_BLOCK_ID_SXS2_BY2 = 0x29,
+ DBG_BLOCK_ID_SXS4_BY2 = 0x2a,
+ DBG_BLOCK_ID_SXS6_BY2 = 0x2b,
+ DBG_BLOCK_ID_DB_BY2 = 0x2c,
+ DBG_BLOCK_ID_DB02_BY2 = 0x2d,
+ DBG_BLOCK_ID_DB10_BY2 = 0x2e,
+ DBG_BLOCK_ID_DB12_BY2 = 0x2f,
+ DBG_BLOCK_ID_TCP_BY2 = 0x30,
+ DBG_BLOCK_ID_TCP2_BY2 = 0x31,
+ DBG_BLOCK_ID_TCP4_BY2 = 0x32,
+ DBG_BLOCK_ID_TCP6_BY2 = 0x33,
+ DBG_BLOCK_ID_TCP8_BY2 = 0x34,
+ DBG_BLOCK_ID_TCP10_BY2 = 0x35,
+ DBG_BLOCK_ID_TCP12_BY2 = 0x36,
+ DBG_BLOCK_ID_TCP14_BY2 = 0x37,
+ DBG_BLOCK_ID_TCP16_BY2 = 0x38,
+ DBG_BLOCK_ID_TCP18_BY2 = 0x39,
+ DBG_BLOCK_ID_TCP20_BY2 = 0x3a,
+ DBG_BLOCK_ID_TCP22_BY2 = 0x3b,
+ DBG_BLOCK_ID_TCP_RESERVED0_BY2 = 0x3c,
+ DBG_BLOCK_ID_TCP_RESERVED2_BY2 = 0x3d,
+ DBG_BLOCK_ID_TCP_RESERVED4_BY2 = 0x3e,
+ DBG_BLOCK_ID_TCP_RESERVED6_BY2 = 0x3f,
+ DBG_BLOCK_ID_TCC_BY2 = 0x40,
+ DBG_BLOCK_ID_TCC2_BY2 = 0x41,
+ DBG_BLOCK_ID_TCC4_BY2 = 0x42,
+ DBG_BLOCK_ID_TCC6_BY2 = 0x43,
+ DBG_BLOCK_ID_SPS_BY2 = 0x44,
+ DBG_BLOCK_ID_SPS02_BY2 = 0x45,
+ DBG_BLOCK_ID_SPS11_BY2 = 0x46,
+ DBG_BLOCK_ID_UNUSED14_BY2 = 0x47,
+ DBG_BLOCK_ID_TA_BY2 = 0x48,
+ DBG_BLOCK_ID_TA02_BY2 = 0x49,
+ DBG_BLOCK_ID_TA04_BY2 = 0x4a,
+ DBG_BLOCK_ID_TA06_BY2 = 0x4b,
+ DBG_BLOCK_ID_TA08_BY2 = 0x4c,
+ DBG_BLOCK_ID_TA0A_BY2 = 0x4d,
+ DBG_BLOCK_ID_UNUSED20_BY2 = 0x4e,
+ DBG_BLOCK_ID_UNUSED22_BY2 = 0x4f,
+ DBG_BLOCK_ID_TA10_BY2 = 0x50,
+ DBG_BLOCK_ID_TA12_BY2 = 0x51,
+ DBG_BLOCK_ID_TA14_BY2 = 0x52,
+ DBG_BLOCK_ID_TA16_BY2 = 0x53,
+ DBG_BLOCK_ID_TA18_BY2 = 0x54,
+ DBG_BLOCK_ID_TA1A_BY2 = 0x55,
+ DBG_BLOCK_ID_UNUSED24_BY2 = 0x56,
+ DBG_BLOCK_ID_UNUSED26_BY2 = 0x57,
+ DBG_BLOCK_ID_TD_BY2 = 0x58,
+ DBG_BLOCK_ID_TD02_BY2 = 0x59,
+ DBG_BLOCK_ID_TD04_BY2 = 0x5a,
+ DBG_BLOCK_ID_TD06_BY2 = 0x5b,
+ DBG_BLOCK_ID_TD08_BY2 = 0x5c,
+ DBG_BLOCK_ID_TD0A_BY2 = 0x5d,
+ DBG_BLOCK_ID_UNUSED28_BY2 = 0x5e,
+ DBG_BLOCK_ID_UNUSED30_BY2 = 0x5f,
+ DBG_BLOCK_ID_TD10_BY2 = 0x60,
+ DBG_BLOCK_ID_TD12_BY2 = 0x61,
+ DBG_BLOCK_ID_TD14_BY2 = 0x62,
+ DBG_BLOCK_ID_TD16_BY2 = 0x63,
+ DBG_BLOCK_ID_TD18_BY2 = 0x64,
+ DBG_BLOCK_ID_TD1A_BY2 = 0x65,
+ DBG_BLOCK_ID_UNUSED32_BY2 = 0x66,
+ DBG_BLOCK_ID_UNUSED34_BY2 = 0x67,
+ DBG_BLOCK_ID_LDS_BY2 = 0x68,
+ DBG_BLOCK_ID_LDS02_BY2 = 0x69,
+ DBG_BLOCK_ID_LDS04_BY2 = 0x6a,
+ DBG_BLOCK_ID_LDS06_BY2 = 0x6b,
+ DBG_BLOCK_ID_LDS08_BY2 = 0x6c,
+ DBG_BLOCK_ID_LDS0A_BY2 = 0x6d,
+ DBG_BLOCK_ID_UNUSED36_BY2 = 0x6e,
+ DBG_BLOCK_ID_UNUSED38_BY2 = 0x6f,
+ DBG_BLOCK_ID_LDS10_BY2 = 0x70,
+ DBG_BLOCK_ID_LDS12_BY2 = 0x71,
+ DBG_BLOCK_ID_LDS14_BY2 = 0x72,
+ DBG_BLOCK_ID_LDS16_BY2 = 0x73,
+ DBG_BLOCK_ID_LDS18_BY2 = 0x74,
+ DBG_BLOCK_ID_LDS1A_BY2 = 0x75,
+ DBG_BLOCK_ID_UNUSED40_BY2 = 0x76,
+ DBG_BLOCK_ID_UNUSED42_BY2 = 0x77,
+} DebugBlockId_BY2;
+typedef enum DebugBlockId_BY4 {
+ DBG_BLOCK_ID_RESERVED_BY4 = 0x0,
+ DBG_BLOCK_ID_UNUSED0_BY4 = 0x1,
+ DBG_BLOCK_ID_CSC_BY4 = 0x2,
+ DBG_BLOCK_ID_SQ_BY4 = 0x3,
+ DBG_BLOCK_ID_SDMA0_BY4 = 0x4,
+ DBG_BLOCK_ID_VC0_BY4 = 0x5,
+ DBG_BLOCK_ID_CP0_BY4 = 0x6,
+ DBG_BLOCK_ID_UNUSED1_BY4 = 0x7,
+ DBG_BLOCK_ID_SXM0_BY4 = 0x8,
+ DBG_BLOCK_ID_SPM0_BY4 = 0x9,
+ DBG_BLOCK_ID_TCAA_BY4 = 0xa,
+ DBG_BLOCK_ID_MCC_BY4 = 0xb,
+ DBG_BLOCK_ID_MCD_BY4 = 0xc,
+ DBG_BLOCK_ID_MCD4_BY4 = 0xd,
+ DBG_BLOCK_ID_SQA_BY4 = 0xe,
+ DBG_BLOCK_ID_SQA11_BY4 = 0xf,
+ DBG_BLOCK_ID_SQB_BY4 = 0x10,
+ DBG_BLOCK_ID_UNUSED10_BY4 = 0x11,
+ DBG_BLOCK_ID_CB_BY4 = 0x12,
+ DBG_BLOCK_ID_CB10_BY4 = 0x13,
+ DBG_BLOCK_ID_SXS_BY4 = 0x14,
+ DBG_BLOCK_ID_SXS4_BY4 = 0x15,
+ DBG_BLOCK_ID_DB_BY4 = 0x16,
+ DBG_BLOCK_ID_DB10_BY4 = 0x17,
+ DBG_BLOCK_ID_TCP_BY4 = 0x18,
+ DBG_BLOCK_ID_TCP4_BY4 = 0x19,
+ DBG_BLOCK_ID_TCP8_BY4 = 0x1a,
+ DBG_BLOCK_ID_TCP12_BY4 = 0x1b,
+ DBG_BLOCK_ID_TCP16_BY4 = 0x1c,
+ DBG_BLOCK_ID_TCP20_BY4 = 0x1d,
+ DBG_BLOCK_ID_TCP_RESERVED0_BY4 = 0x1e,
+ DBG_BLOCK_ID_TCP_RESERVED4_BY4 = 0x1f,
+ DBG_BLOCK_ID_TCC_BY4 = 0x20,
+ DBG_BLOCK_ID_TCC4_BY4 = 0x21,
+ DBG_BLOCK_ID_SPS_BY4 = 0x22,
+ DBG_BLOCK_ID_SPS11_BY4 = 0x23,
+ DBG_BLOCK_ID_TA_BY4 = 0x24,
+ DBG_BLOCK_ID_TA04_BY4 = 0x25,
+ DBG_BLOCK_ID_TA08_BY4 = 0x26,
+ DBG_BLOCK_ID_UNUSED20_BY4 = 0x27,
+ DBG_BLOCK_ID_TA10_BY4 = 0x28,
+ DBG_BLOCK_ID_TA14_BY4 = 0x29,
+ DBG_BLOCK_ID_TA18_BY4 = 0x2a,
+ DBG_BLOCK_ID_UNUSED24_BY4 = 0x2b,
+ DBG_BLOCK_ID_TD_BY4 = 0x2c,
+ DBG_BLOCK_ID_TD04_BY4 = 0x2d,
+ DBG_BLOCK_ID_TD08_BY4 = 0x2e,
+ DBG_BLOCK_ID_UNUSED28_BY4 = 0x2f,
+ DBG_BLOCK_ID_TD10_BY4 = 0x30,
+ DBG_BLOCK_ID_TD14_BY4 = 0x31,
+ DBG_BLOCK_ID_TD18_BY4 = 0x32,
+ DBG_BLOCK_ID_UNUSED32_BY4 = 0x33,
+ DBG_BLOCK_ID_LDS_BY4 = 0x34,
+ DBG_BLOCK_ID_LDS04_BY4 = 0x35,
+ DBG_BLOCK_ID_LDS08_BY4 = 0x36,
+ DBG_BLOCK_ID_UNUSED36_BY4 = 0x37,
+ DBG_BLOCK_ID_LDS10_BY4 = 0x38,
+ DBG_BLOCK_ID_LDS14_BY4 = 0x39,
+ DBG_BLOCK_ID_LDS18_BY4 = 0x3a,
+ DBG_BLOCK_ID_UNUSED40_BY4 = 0x3b,
+} DebugBlockId_BY4;
+typedef enum DebugBlockId_BY8 {
+ DBG_BLOCK_ID_RESERVED_BY8 = 0x0,
+ DBG_BLOCK_ID_CSC_BY8 = 0x1,
+ DBG_BLOCK_ID_SDMA0_BY8 = 0x2,
+ DBG_BLOCK_ID_CP0_BY8 = 0x3,
+ DBG_BLOCK_ID_SXM0_BY8 = 0x4,
+ DBG_BLOCK_ID_TCA_BY8 = 0x5,
+ DBG_BLOCK_ID_MCD_BY8 = 0x6,
+ DBG_BLOCK_ID_SQA_BY8 = 0x7,
+ DBG_BLOCK_ID_SQB_BY8 = 0x8,
+ DBG_BLOCK_ID_CB_BY8 = 0x9,
+ DBG_BLOCK_ID_SXS_BY8 = 0xa,
+ DBG_BLOCK_ID_DB_BY8 = 0xb,
+ DBG_BLOCK_ID_TCP_BY8 = 0xc,
+ DBG_BLOCK_ID_TCP8_BY8 = 0xd,
+ DBG_BLOCK_ID_TCP16_BY8 = 0xe,
+ DBG_BLOCK_ID_TCP_RESERVED0_BY8 = 0xf,
+ DBG_BLOCK_ID_TCC_BY8 = 0x10,
+ DBG_BLOCK_ID_SPS_BY8 = 0x11,
+ DBG_BLOCK_ID_TA_BY8 = 0x12,
+ DBG_BLOCK_ID_TA08_BY8 = 0x13,
+ DBG_BLOCK_ID_TA10_BY8 = 0x14,
+ DBG_BLOCK_ID_TA18_BY8 = 0x15,
+ DBG_BLOCK_ID_TD_BY8 = 0x16,
+ DBG_BLOCK_ID_TD08_BY8 = 0x17,
+ DBG_BLOCK_ID_TD10_BY8 = 0x18,
+ DBG_BLOCK_ID_TD18_BY8 = 0x19,
+ DBG_BLOCK_ID_LDS_BY8 = 0x1a,
+ DBG_BLOCK_ID_LDS08_BY8 = 0x1b,
+ DBG_BLOCK_ID_LDS10_BY8 = 0x1c,
+ DBG_BLOCK_ID_LDS18_BY8 = 0x1d,
+} DebugBlockId_BY8;
+typedef enum DebugBlockId_BY16 {
+ DBG_BLOCK_ID_RESERVED_BY16 = 0x0,
+ DBG_BLOCK_ID_SDMA0_BY16 = 0x1,
+ DBG_BLOCK_ID_SXM_BY16 = 0x2,
+ DBG_BLOCK_ID_MCD_BY16 = 0x3,
+ DBG_BLOCK_ID_SQB_BY16 = 0x4,
+ DBG_BLOCK_ID_SXS_BY16 = 0x5,
+ DBG_BLOCK_ID_TCP_BY16 = 0x6,
+ DBG_BLOCK_ID_TCP16_BY16 = 0x7,
+ DBG_BLOCK_ID_TCC_BY16 = 0x8,
+ DBG_BLOCK_ID_TA_BY16 = 0x9,
+ DBG_BLOCK_ID_TA10_BY16 = 0xa,
+ DBG_BLOCK_ID_TD_BY16 = 0xb,
+ DBG_BLOCK_ID_TD10_BY16 = 0xc,
+ DBG_BLOCK_ID_LDS_BY16 = 0xd,
+ DBG_BLOCK_ID_LDS10_BY16 = 0xe,
+} DebugBlockId_BY16;
+typedef enum SurfaceEndian {
+ ENDIAN_NONE = 0x0,
+ ENDIAN_8IN16 = 0x1,
+ ENDIAN_8IN32 = 0x2,
+ ENDIAN_8IN64 = 0x3,
+} SurfaceEndian;
+typedef enum ArrayMode {
+ ARRAY_LINEAR_GENERAL = 0x0,
+ ARRAY_LINEAR_ALIGNED = 0x1,
+ ARRAY_1D_TILED_THIN1 = 0x2,
+ ARRAY_1D_TILED_THICK = 0x3,
+ ARRAY_2D_TILED_THIN1 = 0x4,
+ ARRAY_PRT_TILED_THIN1 = 0x5,
+ ARRAY_PRT_2D_TILED_THIN1 = 0x6,
+ ARRAY_2D_TILED_THICK = 0x7,
+ ARRAY_2D_TILED_XTHICK = 0x8,
+ ARRAY_PRT_TILED_THICK = 0x9,
+ ARRAY_PRT_2D_TILED_THICK = 0xa,
+ ARRAY_PRT_3D_TILED_THIN1 = 0xb,
+ ARRAY_3D_TILED_THIN1 = 0xc,
+ ARRAY_3D_TILED_THICK = 0xd,
+ ARRAY_3D_TILED_XTHICK = 0xe,
+ ARRAY_PRT_3D_TILED_THICK = 0xf,
+} ArrayMode;
+typedef enum PipeTiling {
+ CONFIG_1_PIPE = 0x0,
+ CONFIG_2_PIPE = 0x1,
+ CONFIG_4_PIPE = 0x2,
+ CONFIG_8_PIPE = 0x3,
+} PipeTiling;
+typedef enum BankTiling {
+ CONFIG_4_BANK = 0x0,
+ CONFIG_8_BANK = 0x1,
+} BankTiling;
+typedef enum GroupInterleave {
+ CONFIG_256B_GROUP = 0x0,
+ CONFIG_512B_GROUP = 0x1,
+} GroupInterleave;
+typedef enum RowTiling {
+ CONFIG_1KB_ROW = 0x0,
+ CONFIG_2KB_ROW = 0x1,
+ CONFIG_4KB_ROW = 0x2,
+ CONFIG_8KB_ROW = 0x3,
+ CONFIG_1KB_ROW_OPT = 0x4,
+ CONFIG_2KB_ROW_OPT = 0x5,
+ CONFIG_4KB_ROW_OPT = 0x6,
+ CONFIG_8KB_ROW_OPT = 0x7,
+} RowTiling;
+typedef enum BankSwapBytes {
+ CONFIG_128B_SWAPS = 0x0,
+ CONFIG_256B_SWAPS = 0x1,
+ CONFIG_512B_SWAPS = 0x2,
+ CONFIG_1KB_SWAPS = 0x3,
+} BankSwapBytes;
+typedef enum SampleSplitBytes {
+ CONFIG_1KB_SPLIT = 0x0,
+ CONFIG_2KB_SPLIT = 0x1,
+ CONFIG_4KB_SPLIT = 0x2,
+ CONFIG_8KB_SPLIT = 0x3,
+} SampleSplitBytes;
+typedef enum NumPipes {
+ ADDR_CONFIG_1_PIPE = 0x0,
+ ADDR_CONFIG_2_PIPE = 0x1,
+ ADDR_CONFIG_4_PIPE = 0x2,
+ ADDR_CONFIG_8_PIPE = 0x3,
+} NumPipes;
+typedef enum PipeInterleaveSize {
+ ADDR_CONFIG_PIPE_INTERLEAVE_256B = 0x0,
+ ADDR_CONFIG_PIPE_INTERLEAVE_512B = 0x1,
+} PipeInterleaveSize;
+typedef enum BankInterleaveSize {
+ ADDR_CONFIG_BANK_INTERLEAVE_1 = 0x0,
+ ADDR_CONFIG_BANK_INTERLEAVE_2 = 0x1,
+ ADDR_CONFIG_BANK_INTERLEAVE_4 = 0x2,
+ ADDR_CONFIG_BANK_INTERLEAVE_8 = 0x3,
+} BankInterleaveSize;
+typedef enum NumShaderEngines {
+ ADDR_CONFIG_1_SHADER_ENGINE = 0x0,
+ ADDR_CONFIG_2_SHADER_ENGINE = 0x1,
+} NumShaderEngines;
+typedef enum ShaderEngineTileSize {
+ ADDR_CONFIG_SE_TILE_16 = 0x0,
+ ADDR_CONFIG_SE_TILE_32 = 0x1,
+} ShaderEngineTileSize;
+typedef enum NumGPUs {
+ ADDR_CONFIG_1_GPU = 0x0,
+ ADDR_CONFIG_2_GPU = 0x1,
+ ADDR_CONFIG_4_GPU = 0x2,
+} NumGPUs;
+typedef enum MultiGPUTileSize {
+ ADDR_CONFIG_GPU_TILE_16 = 0x0,
+ ADDR_CONFIG_GPU_TILE_32 = 0x1,
+ ADDR_CONFIG_GPU_TILE_64 = 0x2,
+ ADDR_CONFIG_GPU_TILE_128 = 0x3,
+} MultiGPUTileSize;
+typedef enum RowSize {
+ ADDR_CONFIG_1KB_ROW = 0x0,
+ ADDR_CONFIG_2KB_ROW = 0x1,
+ ADDR_CONFIG_4KB_ROW = 0x2,
+} RowSize;
+typedef enum NumLowerPipes {
+ ADDR_CONFIG_1_LOWER_PIPES = 0x0,
+ ADDR_CONFIG_2_LOWER_PIPES = 0x1,
+} NumLowerPipes;
+typedef enum ColorTransform {
+ DCC_CT_AUTO = 0x0,
+ DCC_CT_NONE = 0x1,
+ ABGR_TO_A_BG_G_RB = 0x2,
+ BGRA_TO_BG_G_RB_A = 0x3,
+} ColorTransform;
+typedef enum CompareRef {
+ REF_NEVER = 0x0,
+ REF_LESS = 0x1,
+ REF_EQUAL = 0x2,
+ REF_LEQUAL = 0x3,
+ REF_GREATER = 0x4,
+ REF_NOTEQUAL = 0x5,
+ REF_GEQUAL = 0x6,
+ REF_ALWAYS = 0x7,
+} CompareRef;
+typedef enum ReadSize {
+ READ_256_BITS = 0x0,
+ READ_512_BITS = 0x1,
+} ReadSize;
+typedef enum DepthFormat {
+ DEPTH_INVALID = 0x0,
+ DEPTH_16 = 0x1,
+ DEPTH_X8_24 = 0x2,
+ DEPTH_8_24 = 0x3,
+ DEPTH_X8_24_FLOAT = 0x4,
+ DEPTH_8_24_FLOAT = 0x5,
+ DEPTH_32_FLOAT = 0x6,
+ DEPTH_X24_8_32_FLOAT = 0x7,
+} DepthFormat;
+typedef enum ZFormat {
+ Z_INVALID = 0x0,
+ Z_16 = 0x1,
+ Z_24 = 0x2,
+ Z_32_FLOAT = 0x3,
+} ZFormat;
+typedef enum StencilFormat {
+ STENCIL_INVALID = 0x0,
+ STENCIL_8 = 0x1,
+} StencilFormat;
+typedef enum CmaskMode {
+ CMASK_CLEAR_NONE = 0x0,
+ CMASK_CLEAR_ONE = 0x1,
+ CMASK_CLEAR_ALL = 0x2,
+ CMASK_ANY_EXPANDED = 0x3,
+ CMASK_ALPHA0_FRAG1 = 0x4,
+ CMASK_ALPHA0_FRAG2 = 0x5,
+ CMASK_ALPHA0_FRAG4 = 0x6,
+ CMASK_ALPHA0_FRAGS = 0x7,
+ CMASK_ALPHA1_FRAG1 = 0x8,
+ CMASK_ALPHA1_FRAG2 = 0x9,
+ CMASK_ALPHA1_FRAG4 = 0xa,
+ CMASK_ALPHA1_FRAGS = 0xb,
+ CMASK_ALPHAX_FRAG1 = 0xc,
+ CMASK_ALPHAX_FRAG2 = 0xd,
+ CMASK_ALPHAX_FRAG4 = 0xe,
+ CMASK_ALPHAX_FRAGS = 0xf,
+} CmaskMode;
+typedef enum QuadExportFormat {
+ EXPORT_UNUSED = 0x0,
+ EXPORT_32_R = 0x1,
+ EXPORT_32_GR = 0x2,
+ EXPORT_32_AR = 0x3,
+ EXPORT_FP16_ABGR = 0x4,
+ EXPORT_UNSIGNED16_ABGR = 0x5,
+ EXPORT_SIGNED16_ABGR = 0x6,
+ EXPORT_32_ABGR = 0x7,
+} QuadExportFormat;
+typedef enum QuadExportFormatOld {
+ EXPORT_4P_32BPC_ABGR = 0x0,
+ EXPORT_4P_16BPC_ABGR = 0x1,
+ EXPORT_4P_32BPC_GR = 0x2,
+ EXPORT_4P_32BPC_AR = 0x3,
+ EXPORT_2P_32BPC_ABGR = 0x4,
+ EXPORT_8P_32BPC_R = 0x5,
+} QuadExportFormatOld;
+typedef enum ColorFormat {
+ COLOR_INVALID = 0x0,
+ COLOR_8 = 0x1,
+ COLOR_16 = 0x2,
+ COLOR_8_8 = 0x3,
+ COLOR_32 = 0x4,
+ COLOR_16_16 = 0x5,
+ COLOR_10_11_11 = 0x6,
+ COLOR_11_11_10 = 0x7,
+ COLOR_10_10_10_2 = 0x8,
+ COLOR_2_10_10_10 = 0x9,
+ COLOR_8_8_8_8 = 0xa,
+ COLOR_32_32 = 0xb,
+ COLOR_16_16_16_16 = 0xc,
+ COLOR_RESERVED_13 = 0xd,
+ COLOR_32_32_32_32 = 0xe,
+ COLOR_RESERVED_15 = 0xf,
+ COLOR_5_6_5 = 0x10,
+ COLOR_1_5_5_5 = 0x11,
+ COLOR_5_5_5_1 = 0x12,
+ COLOR_4_4_4_4 = 0x13,
+ COLOR_8_24 = 0x14,
+ COLOR_24_8 = 0x15,
+ COLOR_X24_8_32_FLOAT = 0x16,
+ COLOR_RESERVED_23 = 0x17,
+} ColorFormat;
+typedef enum SurfaceFormat {
+ FMT_INVALID = 0x0,
+ FMT_8 = 0x1,
+ FMT_16 = 0x2,
+ FMT_8_8 = 0x3,
+ FMT_32 = 0x4,
+ FMT_16_16 = 0x5,
+ FMT_10_11_11 = 0x6,
+ FMT_11_11_10 = 0x7,
+ FMT_10_10_10_2 = 0x8,
+ FMT_2_10_10_10 = 0x9,
+ FMT_8_8_8_8 = 0xa,
+ FMT_32_32 = 0xb,
+ FMT_16_16_16_16 = 0xc,
+ FMT_32_32_32 = 0xd,
+ FMT_32_32_32_32 = 0xe,
+ FMT_RESERVED_4 = 0xf,
+ FMT_5_6_5 = 0x10,
+ FMT_1_5_5_5 = 0x11,
+ FMT_5_5_5_1 = 0x12,
+ FMT_4_4_4_4 = 0x13,
+ FMT_8_24 = 0x14,
+ FMT_24_8 = 0x15,
+ FMT_X24_8_32_FLOAT = 0x16,
+ FMT_RESERVED_33 = 0x17,
+ FMT_11_11_10_FLOAT = 0x18,
+ FMT_16_FLOAT = 0x19,
+ FMT_32_FLOAT = 0x1a,
+ FMT_16_16_FLOAT = 0x1b,
+ FMT_8_24_FLOAT = 0x1c,
+ FMT_24_8_FLOAT = 0x1d,
+ FMT_32_32_FLOAT = 0x1e,
+ FMT_10_11_11_FLOAT = 0x1f,
+ FMT_16_16_16_16_FLOAT = 0x20,
+ FMT_3_3_2 = 0x21,
+ FMT_6_5_5 = 0x22,
+ FMT_32_32_32_32_FLOAT = 0x23,
+ FMT_RESERVED_36 = 0x24,
+ FMT_1 = 0x25,
+ FMT_1_REVERSED = 0x26,
+ FMT_GB_GR = 0x27,
+ FMT_BG_RG = 0x28,
+ FMT_32_AS_8 = 0x29,
+ FMT_32_AS_8_8 = 0x2a,
+ FMT_5_9_9_9_SHAREDEXP = 0x2b,
+ FMT_8_8_8 = 0x2c,
+ FMT_16_16_16 = 0x2d,
+ FMT_16_16_16_FLOAT = 0x2e,
+ FMT_4_4 = 0x2f,
+ FMT_32_32_32_FLOAT = 0x30,
+ FMT_BC1 = 0x31,
+ FMT_BC2 = 0x32,
+ FMT_BC3 = 0x33,
+ FMT_BC4 = 0x34,
+ FMT_BC5 = 0x35,
+ FMT_BC6 = 0x36,
+ FMT_BC7 = 0x37,
+ FMT_32_AS_32_32_32_32 = 0x38,
+ FMT_APC3 = 0x39,
+ FMT_APC4 = 0x3a,
+ FMT_APC5 = 0x3b,
+ FMT_APC6 = 0x3c,
+ FMT_APC7 = 0x3d,
+ FMT_CTX1 = 0x3e,
+ FMT_RESERVED_63 = 0x3f,
+} SurfaceFormat;
+typedef enum BUF_DATA_FORMAT {
+ BUF_DATA_FORMAT_INVALID = 0x0,
+ BUF_DATA_FORMAT_8 = 0x1,
+ BUF_DATA_FORMAT_16 = 0x2,
+ BUF_DATA_FORMAT_8_8 = 0x3,
+ BUF_DATA_FORMAT_32 = 0x4,
+ BUF_DATA_FORMAT_16_16 = 0x5,
+ BUF_DATA_FORMAT_10_11_11 = 0x6,
+ BUF_DATA_FORMAT_11_11_10 = 0x7,
+ BUF_DATA_FORMAT_10_10_10_2 = 0x8,
+ BUF_DATA_FORMAT_2_10_10_10 = 0x9,
+ BUF_DATA_FORMAT_8_8_8_8 = 0xa,
+ BUF_DATA_FORMAT_32_32 = 0xb,
+ BUF_DATA_FORMAT_16_16_16_16 = 0xc,
+ BUF_DATA_FORMAT_32_32_32 = 0xd,
+ BUF_DATA_FORMAT_32_32_32_32 = 0xe,
+ BUF_DATA_FORMAT_RESERVED_15 = 0xf,
+} BUF_DATA_FORMAT;
+typedef enum IMG_DATA_FORMAT {
+ IMG_DATA_FORMAT_INVALID = 0x0,
+ IMG_DATA_FORMAT_8 = 0x1,
+ IMG_DATA_FORMAT_16 = 0x2,
+ IMG_DATA_FORMAT_8_8 = 0x3,
+ IMG_DATA_FORMAT_32 = 0x4,
+ IMG_DATA_FORMAT_16_16 = 0x5,
+ IMG_DATA_FORMAT_10_11_11 = 0x6,
+ IMG_DATA_FORMAT_11_11_10 = 0x7,
+ IMG_DATA_FORMAT_10_10_10_2 = 0x8,
+ IMG_DATA_FORMAT_2_10_10_10 = 0x9,
+ IMG_DATA_FORMAT_8_8_8_8 = 0xa,
+ IMG_DATA_FORMAT_32_32 = 0xb,
+ IMG_DATA_FORMAT_16_16_16_16 = 0xc,
+ IMG_DATA_FORMAT_32_32_32 = 0xd,
+ IMG_DATA_FORMAT_32_32_32_32 = 0xe,
+ IMG_DATA_FORMAT_RESERVED_15 = 0xf,
+ IMG_DATA_FORMAT_5_6_5 = 0x10,
+ IMG_DATA_FORMAT_1_5_5_5 = 0x11,
+ IMG_DATA_FORMAT_5_5_5_1 = 0x12,
+ IMG_DATA_FORMAT_4_4_4_4 = 0x13,
+ IMG_DATA_FORMAT_8_24 = 0x14,
+ IMG_DATA_FORMAT_24_8 = 0x15,
+ IMG_DATA_FORMAT_X24_8_32 = 0x16,
+ IMG_DATA_FORMAT_RESERVED_23 = 0x17,
+ IMG_DATA_FORMAT_RESERVED_24 = 0x18,
+ IMG_DATA_FORMAT_RESERVED_25 = 0x19,
+ IMG_DATA_FORMAT_RESERVED_26 = 0x1a,
+ IMG_DATA_FORMAT_RESERVED_27 = 0x1b,
+ IMG_DATA_FORMAT_RESERVED_28 = 0x1c,
+ IMG_DATA_FORMAT_RESERVED_29 = 0x1d,
+ IMG_DATA_FORMAT_RESERVED_30 = 0x1e,
+ IMG_DATA_FORMAT_RESERVED_31 = 0x1f,
+ IMG_DATA_FORMAT_GB_GR = 0x20,
+ IMG_DATA_FORMAT_BG_RG = 0x21,
+ IMG_DATA_FORMAT_5_9_9_9 = 0x22,
+ IMG_DATA_FORMAT_BC1 = 0x23,
+ IMG_DATA_FORMAT_BC2 = 0x24,
+ IMG_DATA_FORMAT_BC3 = 0x25,
+ IMG_DATA_FORMAT_BC4 = 0x26,
+ IMG_DATA_FORMAT_BC5 = 0x27,
+ IMG_DATA_FORMAT_BC6 = 0x28,
+ IMG_DATA_FORMAT_BC7 = 0x29,
+ IMG_DATA_FORMAT_RESERVED_42 = 0x2a,
+ IMG_DATA_FORMAT_RESERVED_43 = 0x2b,
+ IMG_DATA_FORMAT_FMASK8_S2_F1 = 0x2c,
+ IMG_DATA_FORMAT_FMASK8_S4_F1 = 0x2d,
+ IMG_DATA_FORMAT_FMASK8_S8_F1 = 0x2e,
+ IMG_DATA_FORMAT_FMASK8_S2_F2 = 0x2f,
+ IMG_DATA_FORMAT_FMASK8_S4_F2 = 0x30,
+ IMG_DATA_FORMAT_FMASK8_S4_F4 = 0x31,
+ IMG_DATA_FORMAT_FMASK16_S16_F1 = 0x32,
+ IMG_DATA_FORMAT_FMASK16_S8_F2 = 0x33,
+ IMG_DATA_FORMAT_FMASK32_S16_F2 = 0x34,
+ IMG_DATA_FORMAT_FMASK32_S8_F4 = 0x35,
+ IMG_DATA_FORMAT_FMASK32_S8_F8 = 0x36,
+ IMG_DATA_FORMAT_FMASK64_S16_F4 = 0x37,
+ IMG_DATA_FORMAT_FMASK64_S16_F8 = 0x38,
+ IMG_DATA_FORMAT_4_4 = 0x39,
+ IMG_DATA_FORMAT_6_5_5 = 0x3a,
+ IMG_DATA_FORMAT_1 = 0x3b,
+ IMG_DATA_FORMAT_1_REVERSED = 0x3c,
+ IMG_DATA_FORMAT_32_AS_8 = 0x3d,
+ IMG_DATA_FORMAT_32_AS_8_8 = 0x3e,
+ IMG_DATA_FORMAT_32_AS_32_32_32_32 = 0x3f,
+} IMG_DATA_FORMAT;
+typedef enum BUF_NUM_FORMAT {
+ BUF_NUM_FORMAT_UNORM = 0x0,
+ BUF_NUM_FORMAT_SNORM = 0x1,
+ BUF_NUM_FORMAT_USCALED = 0x2,
+ BUF_NUM_FORMAT_SSCALED = 0x3,
+ BUF_NUM_FORMAT_UINT = 0x4,
+ BUF_NUM_FORMAT_SINT = 0x5,
+ BUF_NUM_FORMAT_RESERVED_6 = 0x6,
+ BUF_NUM_FORMAT_FLOAT = 0x7,
+} BUF_NUM_FORMAT;
+typedef enum IMG_NUM_FORMAT {
+ IMG_NUM_FORMAT_UNORM = 0x0,
+ IMG_NUM_FORMAT_SNORM = 0x1,
+ IMG_NUM_FORMAT_USCALED = 0x2,
+ IMG_NUM_FORMAT_SSCALED = 0x3,
+ IMG_NUM_FORMAT_UINT = 0x4,
+ IMG_NUM_FORMAT_SINT = 0x5,
+ IMG_NUM_FORMAT_RESERVED_6 = 0x6,
+ IMG_NUM_FORMAT_FLOAT = 0x7,
+ IMG_NUM_FORMAT_RESERVED_8 = 0x8,
+ IMG_NUM_FORMAT_SRGB = 0x9,
+ IMG_NUM_FORMAT_RESERVED_10 = 0xa,
+ IMG_NUM_FORMAT_RESERVED_11 = 0xb,
+ IMG_NUM_FORMAT_RESERVED_12 = 0xc,
+ IMG_NUM_FORMAT_RESERVED_13 = 0xd,
+ IMG_NUM_FORMAT_RESERVED_14 = 0xe,
+ IMG_NUM_FORMAT_RESERVED_15 = 0xf,
+} IMG_NUM_FORMAT;
+typedef enum TileType {
+ ARRAY_COLOR_TILE = 0x0,
+ ARRAY_DEPTH_TILE = 0x1,
+} TileType;
+typedef enum NonDispTilingOrder {
+ ADDR_SURF_MICRO_TILING_DISPLAY = 0x0,
+ ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1,
+} NonDispTilingOrder;
+typedef enum MicroTileMode {
+ ADDR_SURF_DISPLAY_MICRO_TILING = 0x0,
+ ADDR_SURF_THIN_MICRO_TILING = 0x1,
+ ADDR_SURF_DEPTH_MICRO_TILING = 0x2,
+ ADDR_SURF_ROTATED_MICRO_TILING = 0x3,
+ ADDR_SURF_THICK_MICRO_TILING = 0x4,
+} MicroTileMode;
+typedef enum TileSplit {
+ ADDR_SURF_TILE_SPLIT_64B = 0x0,
+ ADDR_SURF_TILE_SPLIT_128B = 0x1,
+ ADDR_SURF_TILE_SPLIT_256B = 0x2,
+ ADDR_SURF_TILE_SPLIT_512B = 0x3,
+ ADDR_SURF_TILE_SPLIT_1KB = 0x4,
+ ADDR_SURF_TILE_SPLIT_2KB = 0x5,
+ ADDR_SURF_TILE_SPLIT_4KB = 0x6,
+} TileSplit;
+typedef enum SampleSplit {
+ ADDR_SURF_SAMPLE_SPLIT_1 = 0x0,
+ ADDR_SURF_SAMPLE_SPLIT_2 = 0x1,
+ ADDR_SURF_SAMPLE_SPLIT_4 = 0x2,
+ ADDR_SURF_SAMPLE_SPLIT_8 = 0x3,
+} SampleSplit;
+typedef enum PipeConfig {
+ ADDR_SURF_P2 = 0x0,
+ ADDR_SURF_P2_RESERVED0 = 0x1,
+ ADDR_SURF_P2_RESERVED1 = 0x2,
+ ADDR_SURF_P2_RESERVED2 = 0x3,
+ ADDR_SURF_P4_8x16 = 0x4,
+ ADDR_SURF_P4_16x16 = 0x5,
+ ADDR_SURF_P4_16x32 = 0x6,
+ ADDR_SURF_P4_32x32 = 0x7,
+ ADDR_SURF_P8_16x16_8x16 = 0x8,
+ ADDR_SURF_P8_16x32_8x16 = 0x9,
+ ADDR_SURF_P8_32x32_8x16 = 0xa,
+ ADDR_SURF_P8_16x32_16x16 = 0xb,
+ ADDR_SURF_P8_32x32_16x16 = 0xc,
+ ADDR_SURF_P8_32x32_16x32 = 0xd,
+ ADDR_SURF_P8_32x64_32x32 = 0xe,
+ ADDR_SURF_P8_RESERVED0 = 0xf,
+ ADDR_SURF_P16_32x32_8x16 = 0x10,
+ ADDR_SURF_P16_32x32_16x16 = 0x11,
+} PipeConfig;
+typedef enum NumBanks {
+ ADDR_SURF_2_BANK = 0x0,
+ ADDR_SURF_4_BANK = 0x1,
+ ADDR_SURF_8_BANK = 0x2,
+ ADDR_SURF_16_BANK = 0x3,
+} NumBanks;
+typedef enum BankWidth {
+ ADDR_SURF_BANK_WIDTH_1 = 0x0,
+ ADDR_SURF_BANK_WIDTH_2 = 0x1,
+ ADDR_SURF_BANK_WIDTH_4 = 0x2,
+ ADDR_SURF_BANK_WIDTH_8 = 0x3,
+} BankWidth;
+typedef enum BankHeight {
+ ADDR_SURF_BANK_HEIGHT_1 = 0x0,
+ ADDR_SURF_BANK_HEIGHT_2 = 0x1,
+ ADDR_SURF_BANK_HEIGHT_4 = 0x2,
+ ADDR_SURF_BANK_HEIGHT_8 = 0x3,
+} BankHeight;
+typedef enum BankWidthHeight {
+ ADDR_SURF_BANK_WH_1 = 0x0,
+ ADDR_SURF_BANK_WH_2 = 0x1,
+ ADDR_SURF_BANK_WH_4 = 0x2,
+ ADDR_SURF_BANK_WH_8 = 0x3,
+} BankWidthHeight;
+typedef enum MacroTileAspect {
+ ADDR_SURF_MACRO_ASPECT_1 = 0x0,
+ ADDR_SURF_MACRO_ASPECT_2 = 0x1,
+ ADDR_SURF_MACRO_ASPECT_4 = 0x2,
+ ADDR_SURF_MACRO_ASPECT_8 = 0x3,
+} MacroTileAspect;
+typedef enum GATCL1RequestType {
+ GATCL1_TYPE_NORMAL = 0x0,
+ GATCL1_TYPE_SHOOTDOWN = 0x1,
+ GATCL1_TYPE_BYPASS = 0x2,
+} GATCL1RequestType;
+typedef enum TCC_CACHE_POLICIES {
+ TCC_CACHE_POLICY_LRU = 0x0,
+ TCC_CACHE_POLICY_STREAM = 0x1,
+} TCC_CACHE_POLICIES;
+typedef enum MTYPE {
+ MTYPE_NC_NV = 0x0,
+ MTYPE_NC = 0x1,
+ MTYPE_CC = 0x2,
+ MTYPE_UC = 0x3,
+} MTYPE;
+typedef enum PERFMON_COUNTER_MODE {
+ PERFMON_COUNTER_MODE_ACCUM = 0x0,
+ PERFMON_COUNTER_MODE_ACTIVE_CYCLES = 0x1,
+ PERFMON_COUNTER_MODE_MAX = 0x2,
+ PERFMON_COUNTER_MODE_DIRTY = 0x3,
+ PERFMON_COUNTER_MODE_SAMPLE = 0x4,
+ PERFMON_COUNTER_MODE_CYCLES_SINCE_FIRST_EVENT = 0x5,
+ PERFMON_COUNTER_MODE_CYCLES_SINCE_LAST_EVENT = 0x6,
+ PERFMON_COUNTER_MODE_CYCLES_GE_HI = 0x7,
+ PERFMON_COUNTER_MODE_CYCLES_EQ_HI = 0x8,
+ PERFMON_COUNTER_MODE_INACTIVE_CYCLES = 0x9,
+ PERFMON_COUNTER_MODE_RESERVED = 0xf,
+} PERFMON_COUNTER_MODE;
+typedef enum PERFMON_SPM_MODE {
+ PERFMON_SPM_MODE_OFF = 0x0,
+ PERFMON_SPM_MODE_16BIT_CLAMP = 0x1,
+ PERFMON_SPM_MODE_16BIT_NO_CLAMP = 0x2,
+ PERFMON_SPM_MODE_32BIT_CLAMP = 0x3,
+ PERFMON_SPM_MODE_32BIT_NO_CLAMP = 0x4,
+ PERFMON_SPM_MODE_RESERVED_5 = 0x5,
+ PERFMON_SPM_MODE_RESERVED_6 = 0x6,
+ PERFMON_SPM_MODE_RESERVED_7 = 0x7,
+ PERFMON_SPM_MODE_TEST_MODE_0 = 0x8,
+ PERFMON_SPM_MODE_TEST_MODE_1 = 0x9,
+ PERFMON_SPM_MODE_TEST_MODE_2 = 0xa,
+} PERFMON_SPM_MODE;
+typedef enum SurfaceTiling {
+ ARRAY_LINEAR = 0x0,
+ ARRAY_TILED = 0x1,
+} SurfaceTiling;
+typedef enum SurfaceArray {
+ ARRAY_1D = 0x0,
+ ARRAY_2D = 0x1,
+ ARRAY_3D = 0x2,
+ ARRAY_3D_SLICE = 0x3,
+} SurfaceArray;
+typedef enum ColorArray {
+ ARRAY_2D_ALT_COLOR = 0x0,
+ ARRAY_2D_COLOR = 0x1,
+ ARRAY_3D_SLICE_COLOR = 0x3,
+} ColorArray;
+typedef enum DepthArray {
+ ARRAY_2D_ALT_DEPTH = 0x0,
+ ARRAY_2D_DEPTH = 0x1,
+} DepthArray;
+typedef enum ENUM_NUM_SIMD_PER_CU {
+ NUM_SIMD_PER_CU = 0x4,
+} ENUM_NUM_SIMD_PER_CU;
+typedef enum MEM_PWR_FORCE_CTRL {
+ NO_FORCE_REQUEST = 0x0,
+ FORCE_LIGHT_SLEEP_REQUEST = 0x1,
+ FORCE_DEEP_SLEEP_REQUEST = 0x2,
+ FORCE_SHUT_DOWN_REQUEST = 0x3,
+} MEM_PWR_FORCE_CTRL;
+typedef enum MEM_PWR_FORCE_CTRL2 {
+ NO_FORCE_REQ = 0x0,
+ FORCE_LIGHT_SLEEP_REQ = 0x1,
+} MEM_PWR_FORCE_CTRL2;
+typedef enum MEM_PWR_DIS_CTRL {
+ ENABLE_MEM_PWR_CTRL = 0x0,
+ DISABLE_MEM_PWR_CTRL = 0x1,
+} MEM_PWR_DIS_CTRL;
+typedef enum MEM_PWR_SEL_CTRL {
+ DYNAMIC_SHUT_DOWN_ENABLE = 0x0,
+ DYNAMIC_DEEP_SLEEP_ENABLE = 0x1,
+ DYNAMIC_LIGHT_SLEEP_ENABLE = 0x2,
+} MEM_PWR_SEL_CTRL;
+typedef enum MEM_PWR_SEL_CTRL2 {
+ DYNAMIC_DEEP_SLEEP_EN = 0x0,
+ DYNAMIC_LIGHT_SLEEP_EN = 0x1,
+} MEM_PWR_SEL_CTRL2;
+
+#endif /* ACP_2_2_ENUM_H */
diff --git a/sound/soc/amd/include/acp_2_2_sh_mask.h b/sound/soc/amd/include/acp_2_2_sh_mask.h
new file mode 100644
index 000000000000..32d2d4104309
--- /dev/null
+++ b/sound/soc/amd/include/acp_2_2_sh_mask.h
@@ -0,0 +1,2292 @@
+/*
+ * ACP_2_2 Register documentation
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) 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 ACP_2_2_SH_MASK_H
+#define ACP_2_2_SH_MASK_H
+
+#define ACP_DMA_CNTL_0__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_0__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_0__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_0__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_0__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_0__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_0__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_0__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_0__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_0__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_1__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_1__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_1__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_1__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_1__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_1__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_1__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_1__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_1__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_1__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_2__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_2__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_2__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_2__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_2__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_2__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_2__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_2__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_2__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_2__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_3__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_3__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_3__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_3__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_3__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_3__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_3__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_3__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_3__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_3__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_4__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_4__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_4__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_4__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_4__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_4__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_4__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_4__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_4__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_4__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_5__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_5__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_5__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_5__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_5__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_5__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_5__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_5__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_5__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_5__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_6__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_6__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_6__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_6__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_6__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_6__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_6__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_6__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_6__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_6__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_7__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_7__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_7__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_7__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_7__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_7__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_7__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_7__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_7__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_7__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_8__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_8__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_8__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_8__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_8__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_8__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_8__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_8__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_8__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_8__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_9__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_9__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_9__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_9__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_9__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_9__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_9__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_9__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_9__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_9__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_10__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_10__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_10__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_10__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_10__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_10__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_10__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_10__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_10__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_10__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_11__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_11__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_11__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_11__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_11__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_11__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_11__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_11__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_11__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_11__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_12__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_12__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_12__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_12__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_12__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_12__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_12__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_12__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_12__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_12__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_13__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_13__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_13__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_13__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_13__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_13__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_13__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_13__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_13__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_13__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_14__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_14__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_14__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_14__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_14__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_14__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_14__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_14__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_14__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_14__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_CNTL_15__DMAChRst_MASK 0x1
+#define ACP_DMA_CNTL_15__DMAChRst__SHIFT 0x0
+#define ACP_DMA_CNTL_15__DMAChRun_MASK 0x2
+#define ACP_DMA_CNTL_15__DMAChRun__SHIFT 0x1
+#define ACP_DMA_CNTL_15__DMAChIOCEn_MASK 0x4
+#define ACP_DMA_CNTL_15__DMAChIOCEn__SHIFT 0x2
+#define ACP_DMA_CNTL_15__Circular_DMA_En_MASK 0x8
+#define ACP_DMA_CNTL_15__Circular_DMA_En__SHIFT 0x3
+#define ACP_DMA_CNTL_15__DMAChGracefulRstEn_MASK 0x10
+#define ACP_DMA_CNTL_15__DMAChGracefulRstEn__SHIFT 0x4
+#define ACP_DMA_DSCR_STRT_IDX_0__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_0__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_1__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_1__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_2__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_2__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_3__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_3__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_4__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_4__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_5__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_5__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_6__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_6__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_7__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_7__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_8__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_8__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_9__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_9__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_10__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_10__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_11__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_11__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_12__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_12__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_13__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_13__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_14__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_14__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_STRT_IDX_15__DMAChDscrStrtIdx_MASK 0x3ff
+#define ACP_DMA_DSCR_STRT_IDX_15__DMAChDscrStrtIdx__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_0__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_0__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_1__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_1__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_2__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_2__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_3__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_3__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_4__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_4__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_5__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_5__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_6__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_6__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_7__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_7__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_8__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_8__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_9__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_9__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_10__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_10__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_11__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_11__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_12__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_12__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_13__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_13__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_14__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_14__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_DSCR_CNT_15__DMAChDscrCnt_MASK 0x3ff
+#define ACP_DMA_DSCR_CNT_15__DMAChDscrCnt__SHIFT 0x0
+#define ACP_DMA_PRIO_0__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_0__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_1__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_1__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_2__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_2__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_3__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_3__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_4__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_4__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_5__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_5__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_6__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_6__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_7__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_7__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_8__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_8__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_9__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_9__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_10__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_10__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_11__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_11__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_12__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_12__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_13__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_13__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_14__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_14__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_PRIO_15__DMAChPrioLvl_MASK 0x1
+#define ACP_DMA_PRIO_15__DMAChPrioLvl__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_0__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_0__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_1__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_1__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_2__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_2__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_3__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_3__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_4__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_4__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_5__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_5__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_6__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_6__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_7__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_7__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_8__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_8__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_9__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_9__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_10__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_10__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_11__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_11__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_12__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_12__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_13__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_13__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_14__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_14__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_DSCR_15__DMAChCurDscrIdx_MASK 0x3ff
+#define ACP_DMA_CUR_DSCR_15__DMAChCurDscrIdx__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_0__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_0__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_1__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_1__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_2__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_2__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_3__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_3__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_4__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_4__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_5__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_5__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_6__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_6__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_7__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_7__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_8__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_8__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_9__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_9__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_10__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_10__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_11__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_11__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_12__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_12__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_13__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_13__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_14__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_14__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_CUR_TRANS_CNT_15__DMAChCurTransCnt_MASK 0x1ffff
+#define ACP_DMA_CUR_TRANS_CNT_15__DMAChCurTransCnt__SHIFT 0x0
+#define ACP_DMA_ERR_STS_0__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_0__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_0__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_0__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_1__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_1__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_1__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_1__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_2__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_2__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_2__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_2__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_3__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_3__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_3__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_3__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_4__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_4__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_4__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_4__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_5__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_5__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_5__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_5__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_6__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_6__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_6__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_6__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_7__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_7__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_7__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_7__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_8__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_8__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_8__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_8__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_9__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_9__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_9__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_9__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_10__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_10__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_10__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_10__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_11__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_11__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_11__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_11__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_12__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_12__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_12__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_12__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_13__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_13__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_13__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_13__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_14__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_14__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_14__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_14__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_ERR_STS_15__DMAChTermErr_MASK 0x1
+#define ACP_DMA_ERR_STS_15__DMAChTermErr__SHIFT 0x0
+#define ACP_DMA_ERR_STS_15__DMAChErrCode_MASK 0x1e
+#define ACP_DMA_ERR_STS_15__DMAChErrCode__SHIFT 0x1
+#define ACP_DMA_DESC_BASE_ADDR__DescriptorBaseAddr_MASK 0xffffffff
+#define ACP_DMA_DESC_BASE_ADDR__DescriptorBaseAddr__SHIFT 0x0
+#define ACP_DMA_DESC_MAX_NUM_DSCR__MaximumNumberDescr_MASK 0xf
+#define ACP_DMA_DESC_MAX_NUM_DSCR__MaximumNumberDescr__SHIFT 0x0
+#define ACP_DMA_CH_STS__DMAChSts_MASK 0xffff
+#define ACP_DMA_CH_STS__DMAChSts__SHIFT 0x0
+#define ACP_DMA_CH_GROUP__DMAChanelGrouping_MASK 0x1
+#define ACP_DMA_CH_GROUP__DMAChanelGrouping__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET0__Offset_MASK 0xfffffff
+#define ACP_DSP0_CACHE_OFFSET0__Offset__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_CACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_CACHE_SIZE0__Size_MASK 0xffffff
+#define ACP_DSP0_CACHE_SIZE0__Size__SHIFT 0x0
+#define ACP_DSP0_CACHE_SIZE0__PageEnable_MASK 0x80000000
+#define ACP_DSP0_CACHE_SIZE0__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_CACHE_OFFSET1__Offset_MASK 0xfffffff
+#define ACP_DSP0_CACHE_OFFSET1__Offset__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_CACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_CACHE_SIZE1__Size_MASK 0xffffff
+#define ACP_DSP0_CACHE_SIZE1__Size__SHIFT 0x0
+#define ACP_DSP0_CACHE_SIZE1__PageEnable_MASK 0x80000000
+#define ACP_DSP0_CACHE_SIZE1__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_CACHE_OFFSET2__Offset_MASK 0xfffffff
+#define ACP_DSP0_CACHE_OFFSET2__Offset__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET2__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_CACHE_OFFSET2__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_CACHE_SIZE2__Size_MASK 0xffffff
+#define ACP_DSP0_CACHE_SIZE2__Size__SHIFT 0x0
+#define ACP_DSP0_CACHE_SIZE2__PageEnable_MASK 0x80000000
+#define ACP_DSP0_CACHE_SIZE2__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_CACHE_OFFSET3__Offset_MASK 0xfffffff
+#define ACP_DSP0_CACHE_OFFSET3__Offset__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET3__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_CACHE_OFFSET3__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_CACHE_SIZE3__Size_MASK 0xffffff
+#define ACP_DSP0_CACHE_SIZE3__Size__SHIFT 0x0
+#define ACP_DSP0_CACHE_SIZE3__PageEnable_MASK 0x80000000
+#define ACP_DSP0_CACHE_SIZE3__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_CACHE_OFFSET4__Offset_MASK 0xfffffff
+#define ACP_DSP0_CACHE_OFFSET4__Offset__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET4__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_CACHE_OFFSET4__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_CACHE_SIZE4__Size_MASK 0xffffff
+#define ACP_DSP0_CACHE_SIZE4__Size__SHIFT 0x0
+#define ACP_DSP0_CACHE_SIZE4__PageEnable_MASK 0x80000000
+#define ACP_DSP0_CACHE_SIZE4__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_CACHE_OFFSET5__Offset_MASK 0xfffffff
+#define ACP_DSP0_CACHE_OFFSET5__Offset__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET5__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_CACHE_OFFSET5__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_CACHE_SIZE5__Size_MASK 0xffffff
+#define ACP_DSP0_CACHE_SIZE5__Size__SHIFT 0x0
+#define ACP_DSP0_CACHE_SIZE5__PageEnable_MASK 0x80000000
+#define ACP_DSP0_CACHE_SIZE5__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_CACHE_OFFSET6__Offset_MASK 0xfffffff
+#define ACP_DSP0_CACHE_OFFSET6__Offset__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET6__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_CACHE_OFFSET6__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_CACHE_SIZE6__Size_MASK 0xffffff
+#define ACP_DSP0_CACHE_SIZE6__Size__SHIFT 0x0
+#define ACP_DSP0_CACHE_SIZE6__PageEnable_MASK 0x80000000
+#define ACP_DSP0_CACHE_SIZE6__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_CACHE_OFFSET7__Offset_MASK 0xfffffff
+#define ACP_DSP0_CACHE_OFFSET7__Offset__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET7__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_CACHE_OFFSET7__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_CACHE_SIZE7__Size_MASK 0xffffff
+#define ACP_DSP0_CACHE_SIZE7__Size__SHIFT 0x0
+#define ACP_DSP0_CACHE_SIZE7__PageEnable_MASK 0x80000000
+#define ACP_DSP0_CACHE_SIZE7__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_CACHE_OFFSET8__Offset_MASK 0xfffffff
+#define ACP_DSP0_CACHE_OFFSET8__Offset__SHIFT 0x0
+#define ACP_DSP0_CACHE_OFFSET8__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_CACHE_OFFSET8__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_CACHE_SIZE8__Size_MASK 0xffffff
+#define ACP_DSP0_CACHE_SIZE8__Size__SHIFT 0x0
+#define ACP_DSP0_CACHE_SIZE8__PageEnable_MASK 0x80000000
+#define ACP_DSP0_CACHE_SIZE8__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_NONCACHE_OFFSET0__Offset_MASK 0xfffffff
+#define ACP_DSP0_NONCACHE_OFFSET0__Offset__SHIFT 0x0
+#define ACP_DSP0_NONCACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_NONCACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_NONCACHE_SIZE0__Size_MASK 0xffffff
+#define ACP_DSP0_NONCACHE_SIZE0__Size__SHIFT 0x0
+#define ACP_DSP0_NONCACHE_SIZE0__PageEnable_MASK 0x80000000
+#define ACP_DSP0_NONCACHE_SIZE0__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_NONCACHE_OFFSET1__Offset_MASK 0xfffffff
+#define ACP_DSP0_NONCACHE_OFFSET1__Offset__SHIFT 0x0
+#define ACP_DSP0_NONCACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP0_NONCACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP0_NONCACHE_SIZE1__Size_MASK 0xffffff
+#define ACP_DSP0_NONCACHE_SIZE1__Size__SHIFT 0x0
+#define ACP_DSP0_NONCACHE_SIZE1__PageEnable_MASK 0x80000000
+#define ACP_DSP0_NONCACHE_SIZE1__PageEnable__SHIFT 0x1f
+#define ACP_DSP0_DEBUG_PC__DebugPC_MASK 0xffffffff
+#define ACP_DSP0_DEBUG_PC__DebugPC__SHIFT 0x0
+#define ACP_DSP0_NMI_SEL__NMISel_MASK 0x1
+#define ACP_DSP0_NMI_SEL__NMISel__SHIFT 0x0
+#define ACP_DSP0_CLKRST_CNTL__ClkEn_MASK 0x1
+#define ACP_DSP0_CLKRST_CNTL__ClkEn__SHIFT 0x0
+#define ACP_DSP0_CLKRST_CNTL__SoftResetDSP_MASK 0x2
+#define ACP_DSP0_CLKRST_CNTL__SoftResetDSP__SHIFT 0x1
+#define ACP_DSP0_CLKRST_CNTL__InternalSoftResetMode_MASK 0x4
+#define ACP_DSP0_CLKRST_CNTL__InternalSoftResetMode__SHIFT 0x2
+#define ACP_DSP0_CLKRST_CNTL__ExternalSoftResetMode_MASK 0x8
+#define ACP_DSP0_CLKRST_CNTL__ExternalSoftResetMode__SHIFT 0x3
+#define ACP_DSP0_CLKRST_CNTL__SoftResetDSPDone_MASK 0x10
+#define ACP_DSP0_CLKRST_CNTL__SoftResetDSPDone__SHIFT 0x4
+#define ACP_DSP0_CLKRST_CNTL__Clk_ON_Status_MASK 0x20
+#define ACP_DSP0_CLKRST_CNTL__Clk_ON_Status__SHIFT 0x5
+#define ACP_DSP0_RUNSTALL__RunStallCntl_MASK 0x1
+#define ACP_DSP0_RUNSTALL__RunStallCntl__SHIFT 0x0
+#define ACP_DSP0_OCD_HALT_ON_RST__OCD_HALT_ON_RST_MASK 0x1
+#define ACP_DSP0_OCD_HALT_ON_RST__OCD_HALT_ON_RST__SHIFT 0x0
+#define ACP_DSP0_WAIT_MODE__WaitMode_MASK 0x1
+#define ACP_DSP0_WAIT_MODE__WaitMode__SHIFT 0x0
+#define ACP_DSP0_VECT_SEL__StaticVectorSel_MASK 0x1
+#define ACP_DSP0_VECT_SEL__StaticVectorSel__SHIFT 0x0
+#define ACP_DSP0_DEBUG_REG1__ACP_DSP_DEBUG_REG1_MASK 0xffffffff
+#define ACP_DSP0_DEBUG_REG1__ACP_DSP_DEBUG_REG1__SHIFT 0x0
+#define ACP_DSP0_DEBUG_REG2__ACP_DSP_DEBUG_REG2_MASK 0xffffffff
+#define ACP_DSP0_DEBUG_REG2__ACP_DSP_DEBUG_REG2__SHIFT 0x0
+#define ACP_DSP0_DEBUG_REG3__ACP_DSP_DEBUG_REG3_MASK 0xffffffff
+#define ACP_DSP0_DEBUG_REG3__ACP_DSP_DEBUG_REG3__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET0__Offset_MASK 0xfffffff
+#define ACP_DSP1_CACHE_OFFSET0__Offset__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_CACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_CACHE_SIZE0__Size_MASK 0xffffff
+#define ACP_DSP1_CACHE_SIZE0__Size__SHIFT 0x0
+#define ACP_DSP1_CACHE_SIZE0__PageEnable_MASK 0x80000000
+#define ACP_DSP1_CACHE_SIZE0__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_CACHE_OFFSET1__Offset_MASK 0xfffffff
+#define ACP_DSP1_CACHE_OFFSET1__Offset__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_CACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_CACHE_SIZE1__Size_MASK 0xffffff
+#define ACP_DSP1_CACHE_SIZE1__Size__SHIFT 0x0
+#define ACP_DSP1_CACHE_SIZE1__PageEnable_MASK 0x80000000
+#define ACP_DSP1_CACHE_SIZE1__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_CACHE_OFFSET2__Offset_MASK 0xfffffff
+#define ACP_DSP1_CACHE_OFFSET2__Offset__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET2__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_CACHE_OFFSET2__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_CACHE_SIZE2__Size_MASK 0xffffff
+#define ACP_DSP1_CACHE_SIZE2__Size__SHIFT 0x0
+#define ACP_DSP1_CACHE_SIZE2__PageEnable_MASK 0x80000000
+#define ACP_DSP1_CACHE_SIZE2__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_CACHE_OFFSET3__Offset_MASK 0xfffffff
+#define ACP_DSP1_CACHE_OFFSET3__Offset__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET3__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_CACHE_OFFSET3__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_CACHE_SIZE3__Size_MASK 0xffffff
+#define ACP_DSP1_CACHE_SIZE3__Size__SHIFT 0x0
+#define ACP_DSP1_CACHE_SIZE3__PageEnable_MASK 0x80000000
+#define ACP_DSP1_CACHE_SIZE3__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_CACHE_OFFSET4__Offset_MASK 0xfffffff
+#define ACP_DSP1_CACHE_OFFSET4__Offset__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET4__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_CACHE_OFFSET4__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_CACHE_SIZE4__Size_MASK 0xffffff
+#define ACP_DSP1_CACHE_SIZE4__Size__SHIFT 0x0
+#define ACP_DSP1_CACHE_SIZE4__PageEnable_MASK 0x80000000
+#define ACP_DSP1_CACHE_SIZE4__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_CACHE_OFFSET5__Offset_MASK 0xfffffff
+#define ACP_DSP1_CACHE_OFFSET5__Offset__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET5__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_CACHE_OFFSET5__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_CACHE_SIZE5__Size_MASK 0xffffff
+#define ACP_DSP1_CACHE_SIZE5__Size__SHIFT 0x0
+#define ACP_DSP1_CACHE_SIZE5__PageEnable_MASK 0x80000000
+#define ACP_DSP1_CACHE_SIZE5__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_CACHE_OFFSET6__Offset_MASK 0xfffffff
+#define ACP_DSP1_CACHE_OFFSET6__Offset__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET6__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_CACHE_OFFSET6__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_CACHE_SIZE6__Size_MASK 0xffffff
+#define ACP_DSP1_CACHE_SIZE6__Size__SHIFT 0x0
+#define ACP_DSP1_CACHE_SIZE6__PageEnable_MASK 0x80000000
+#define ACP_DSP1_CACHE_SIZE6__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_CACHE_OFFSET7__Offset_MASK 0xfffffff
+#define ACP_DSP1_CACHE_OFFSET7__Offset__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET7__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_CACHE_OFFSET7__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_CACHE_SIZE7__Size_MASK 0xffffff
+#define ACP_DSP1_CACHE_SIZE7__Size__SHIFT 0x0
+#define ACP_DSP1_CACHE_SIZE7__PageEnable_MASK 0x80000000
+#define ACP_DSP1_CACHE_SIZE7__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_CACHE_OFFSET8__Offset_MASK 0xfffffff
+#define ACP_DSP1_CACHE_OFFSET8__Offset__SHIFT 0x0
+#define ACP_DSP1_CACHE_OFFSET8__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_CACHE_OFFSET8__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_CACHE_SIZE8__Size_MASK 0xffffff
+#define ACP_DSP1_CACHE_SIZE8__Size__SHIFT 0x0
+#define ACP_DSP1_CACHE_SIZE8__PageEnable_MASK 0x80000000
+#define ACP_DSP1_CACHE_SIZE8__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_NONCACHE_OFFSET0__Offset_MASK 0xfffffff
+#define ACP_DSP1_NONCACHE_OFFSET0__Offset__SHIFT 0x0
+#define ACP_DSP1_NONCACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_NONCACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_NONCACHE_SIZE0__Size_MASK 0xffffff
+#define ACP_DSP1_NONCACHE_SIZE0__Size__SHIFT 0x0
+#define ACP_DSP1_NONCACHE_SIZE0__PageEnable_MASK 0x80000000
+#define ACP_DSP1_NONCACHE_SIZE0__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_NONCACHE_OFFSET1__Offset_MASK 0xfffffff
+#define ACP_DSP1_NONCACHE_OFFSET1__Offset__SHIFT 0x0
+#define ACP_DSP1_NONCACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP1_NONCACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP1_NONCACHE_SIZE1__Size_MASK 0xffffff
+#define ACP_DSP1_NONCACHE_SIZE1__Size__SHIFT 0x0
+#define ACP_DSP1_NONCACHE_SIZE1__PageEnable_MASK 0x80000000
+#define ACP_DSP1_NONCACHE_SIZE1__PageEnable__SHIFT 0x1f
+#define ACP_DSP1_DEBUG_PC__DebugPC_MASK 0xffffffff
+#define ACP_DSP1_DEBUG_PC__DebugPC__SHIFT 0x0
+#define ACP_DSP1_NMI_SEL__NMISel_MASK 0x1
+#define ACP_DSP1_NMI_SEL__NMISel__SHIFT 0x0
+#define ACP_DSP1_CLKRST_CNTL__ClkEn_MASK 0x1
+#define ACP_DSP1_CLKRST_CNTL__ClkEn__SHIFT 0x0
+#define ACP_DSP1_CLKRST_CNTL__SoftResetDSP_MASK 0x2
+#define ACP_DSP1_CLKRST_CNTL__SoftResetDSP__SHIFT 0x1
+#define ACP_DSP1_CLKRST_CNTL__InternalSoftResetMode_MASK 0x4
+#define ACP_DSP1_CLKRST_CNTL__InternalSoftResetMode__SHIFT 0x2
+#define ACP_DSP1_CLKRST_CNTL__ExternalSoftResetMode_MASK 0x8
+#define ACP_DSP1_CLKRST_CNTL__ExternalSoftResetMode__SHIFT 0x3
+#define ACP_DSP1_CLKRST_CNTL__SoftResetDSPDone_MASK 0x10
+#define ACP_DSP1_CLKRST_CNTL__SoftResetDSPDone__SHIFT 0x4
+#define ACP_DSP1_CLKRST_CNTL__Clk_ON_Status_MASK 0x20
+#define ACP_DSP1_CLKRST_CNTL__Clk_ON_Status__SHIFT 0x5
+#define ACP_DSP1_RUNSTALL__RunStallCntl_MASK 0x1
+#define ACP_DSP1_RUNSTALL__RunStallCntl__SHIFT 0x0
+#define ACP_DSP1_OCD_HALT_ON_RST__OCD_HALT_ON_RST_MASK 0x1
+#define ACP_DSP1_OCD_HALT_ON_RST__OCD_HALT_ON_RST__SHIFT 0x0
+#define ACP_DSP1_WAIT_MODE__WaitMode_MASK 0x1
+#define ACP_DSP1_WAIT_MODE__WaitMode__SHIFT 0x0
+#define ACP_DSP1_VECT_SEL__StaticVectorSel_MASK 0x1
+#define ACP_DSP1_VECT_SEL__StaticVectorSel__SHIFT 0x0
+#define ACP_DSP1_DEBUG_REG1__ACP_DSP_DEBUG_REG1_MASK 0xffffffff
+#define ACP_DSP1_DEBUG_REG1__ACP_DSP_DEBUG_REG1__SHIFT 0x0
+#define ACP_DSP1_DEBUG_REG2__ACP_DSP_DEBUG_REG2_MASK 0xffffffff
+#define ACP_DSP1_DEBUG_REG2__ACP_DSP_DEBUG_REG2__SHIFT 0x0
+#define ACP_DSP1_DEBUG_REG3__ACP_DSP_DEBUG_REG3_MASK 0xffffffff
+#define ACP_DSP1_DEBUG_REG3__ACP_DSP_DEBUG_REG3__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET0__Offset_MASK 0xfffffff
+#define ACP_DSP2_CACHE_OFFSET0__Offset__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_CACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_CACHE_SIZE0__Size_MASK 0xffffff
+#define ACP_DSP2_CACHE_SIZE0__Size__SHIFT 0x0
+#define ACP_DSP2_CACHE_SIZE0__PageEnable_MASK 0x80000000
+#define ACP_DSP2_CACHE_SIZE0__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_CACHE_OFFSET1__Offset_MASK 0xfffffff
+#define ACP_DSP2_CACHE_OFFSET1__Offset__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_CACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_CACHE_SIZE1__Size_MASK 0xffffff
+#define ACP_DSP2_CACHE_SIZE1__Size__SHIFT 0x0
+#define ACP_DSP2_CACHE_SIZE1__PageEnable_MASK 0x80000000
+#define ACP_DSP2_CACHE_SIZE1__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_CACHE_OFFSET2__Offset_MASK 0xfffffff
+#define ACP_DSP2_CACHE_OFFSET2__Offset__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET2__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_CACHE_OFFSET2__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_CACHE_SIZE2__Size_MASK 0xffffff
+#define ACP_DSP2_CACHE_SIZE2__Size__SHIFT 0x0
+#define ACP_DSP2_CACHE_SIZE2__PageEnable_MASK 0x80000000
+#define ACP_DSP2_CACHE_SIZE2__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_CACHE_OFFSET3__Offset_MASK 0xfffffff
+#define ACP_DSP2_CACHE_OFFSET3__Offset__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET3__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_CACHE_OFFSET3__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_CACHE_SIZE3__Size_MASK 0xffffff
+#define ACP_DSP2_CACHE_SIZE3__Size__SHIFT 0x0
+#define ACP_DSP2_CACHE_SIZE3__PageEnable_MASK 0x80000000
+#define ACP_DSP2_CACHE_SIZE3__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_CACHE_OFFSET4__Offset_MASK 0xfffffff
+#define ACP_DSP2_CACHE_OFFSET4__Offset__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET4__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_CACHE_OFFSET4__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_CACHE_SIZE4__Size_MASK 0xffffff
+#define ACP_DSP2_CACHE_SIZE4__Size__SHIFT 0x0
+#define ACP_DSP2_CACHE_SIZE4__PageEnable_MASK 0x80000000
+#define ACP_DSP2_CACHE_SIZE4__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_CACHE_OFFSET5__Offset_MASK 0xfffffff
+#define ACP_DSP2_CACHE_OFFSET5__Offset__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET5__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_CACHE_OFFSET5__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_CACHE_SIZE5__Size_MASK 0xffffff
+#define ACP_DSP2_CACHE_SIZE5__Size__SHIFT 0x0
+#define ACP_DSP2_CACHE_SIZE5__PageEnable_MASK 0x80000000
+#define ACP_DSP2_CACHE_SIZE5__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_CACHE_OFFSET6__Offset_MASK 0xfffffff
+#define ACP_DSP2_CACHE_OFFSET6__Offset__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET6__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_CACHE_OFFSET6__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_CACHE_SIZE6__Size_MASK 0xffffff
+#define ACP_DSP2_CACHE_SIZE6__Size__SHIFT 0x0
+#define ACP_DSP2_CACHE_SIZE6__PageEnable_MASK 0x80000000
+#define ACP_DSP2_CACHE_SIZE6__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_CACHE_OFFSET7__Offset_MASK 0xfffffff
+#define ACP_DSP2_CACHE_OFFSET7__Offset__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET7__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_CACHE_OFFSET7__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_CACHE_SIZE7__Size_MASK 0xffffff
+#define ACP_DSP2_CACHE_SIZE7__Size__SHIFT 0x0
+#define ACP_DSP2_CACHE_SIZE7__PageEnable_MASK 0x80000000
+#define ACP_DSP2_CACHE_SIZE7__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_CACHE_OFFSET8__Offset_MASK 0xfffffff
+#define ACP_DSP2_CACHE_OFFSET8__Offset__SHIFT 0x0
+#define ACP_DSP2_CACHE_OFFSET8__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_CACHE_OFFSET8__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_CACHE_SIZE8__Size_MASK 0xffffff
+#define ACP_DSP2_CACHE_SIZE8__Size__SHIFT 0x0
+#define ACP_DSP2_CACHE_SIZE8__PageEnable_MASK 0x80000000
+#define ACP_DSP2_CACHE_SIZE8__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_NONCACHE_OFFSET0__Offset_MASK 0xfffffff
+#define ACP_DSP2_NONCACHE_OFFSET0__Offset__SHIFT 0x0
+#define ACP_DSP2_NONCACHE_OFFSET0__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_NONCACHE_OFFSET0__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_NONCACHE_SIZE0__Size_MASK 0xffffff
+#define ACP_DSP2_NONCACHE_SIZE0__Size__SHIFT 0x0
+#define ACP_DSP2_NONCACHE_SIZE0__PageEnable_MASK 0x80000000
+#define ACP_DSP2_NONCACHE_SIZE0__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_NONCACHE_OFFSET1__Offset_MASK 0xfffffff
+#define ACP_DSP2_NONCACHE_OFFSET1__Offset__SHIFT 0x0
+#define ACP_DSP2_NONCACHE_OFFSET1__OnionGarlicSel_MASK 0x80000000
+#define ACP_DSP2_NONCACHE_OFFSET1__OnionGarlicSel__SHIFT 0x1f
+#define ACP_DSP2_NONCACHE_SIZE1__Size_MASK 0xffffff
+#define ACP_DSP2_NONCACHE_SIZE1__Size__SHIFT 0x0
+#define ACP_DSP2_NONCACHE_SIZE1__PageEnable_MASK 0x80000000
+#define ACP_DSP2_NONCACHE_SIZE1__PageEnable__SHIFT 0x1f
+#define ACP_DSP2_DEBUG_PC__DebugPC_MASK 0xffffffff
+#define ACP_DSP2_DEBUG_PC__DebugPC__SHIFT 0x0
+#define ACP_DSP2_NMI_SEL__NMISel_MASK 0x1
+#define ACP_DSP2_NMI_SEL__NMISel__SHIFT 0x0
+#define ACP_DSP2_CLKRST_CNTL__ClkEn_MASK 0x1
+#define ACP_DSP2_CLKRST_CNTL__ClkEn__SHIFT 0x0
+#define ACP_DSP2_CLKRST_CNTL__SoftResetDSP_MASK 0x2
+#define ACP_DSP2_CLKRST_CNTL__SoftResetDSP__SHIFT 0x1
+#define ACP_DSP2_CLKRST_CNTL__InternalSoftResetMode_MASK 0x4
+#define ACP_DSP2_CLKRST_CNTL__InternalSoftResetMode__SHIFT 0x2
+#define ACP_DSP2_CLKRST_CNTL__ExternalSoftResetMode_MASK 0x8
+#define ACP_DSP2_CLKRST_CNTL__ExternalSoftResetMode__SHIFT 0x3
+#define ACP_DSP2_CLKRST_CNTL__SoftResetDSPDone_MASK 0x10
+#define ACP_DSP2_CLKRST_CNTL__SoftResetDSPDone__SHIFT 0x4
+#define ACP_DSP2_CLKRST_CNTL__Clk_ON_Status_MASK 0x20
+#define ACP_DSP2_CLKRST_CNTL__Clk_ON_Status__SHIFT 0x5
+#define ACP_DSP2_RUNSTALL__RunStallCntl_MASK 0x1
+#define ACP_DSP2_RUNSTALL__RunStallCntl__SHIFT 0x0
+#define ACP_DSP2_OCD_HALT_ON_RST__OCD_HALT_ON_RST_MASK 0x1
+#define ACP_DSP2_OCD_HALT_ON_RST__OCD_HALT_ON_RST__SHIFT 0x0
+#define ACP_DSP2_WAIT_MODE__WaitMode_MASK 0x1
+#define ACP_DSP2_WAIT_MODE__WaitMode__SHIFT 0x0
+#define ACP_DSP2_VECT_SEL__StaticVectorSel_MASK 0x1
+#define ACP_DSP2_VECT_SEL__StaticVectorSel__SHIFT 0x0
+#define ACP_DSP2_DEBUG_REG1__ACP_DSP_DEBUG_REG1_MASK 0xffffffff
+#define ACP_DSP2_DEBUG_REG1__ACP_DSP_DEBUG_REG1__SHIFT 0x0
+#define ACP_DSP2_DEBUG_REG2__ACP_DSP_DEBUG_REG2_MASK 0xffffffff
+#define ACP_DSP2_DEBUG_REG2__ACP_DSP_DEBUG_REG2__SHIFT 0x0
+#define ACP_DSP2_DEBUG_REG3__ACP_DSP_DEBUG_REG3_MASK 0xffffffff
+#define ACP_DSP2_DEBUG_REG3__ACP_DSP_DEBUG_REG3__SHIFT 0x0
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBDataSwap_MASK 0x3
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBDataSwap__SHIFT 0x0
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBEnbMultRdReq_MASK 0x4
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBEnbMultRdReq__SHIFT 0x2
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBEnbMultWrReq_MASK 0x18
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBEnbMultWrReq__SHIFT 0x3
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBMaxReadBurst_MASK 0x60
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBMaxReadBurst__SHIFT 0x5
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBStallEnb_MASK 0x80
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBStallEnb__SHIFT 0x7
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBNackChkEnb_MASK 0x100
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBNackChkEnb__SHIFT 0x8
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBAdrWinViolChkEnb_MASK 0x200
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBAdrWinViolChkEnb__SHIFT 0x9
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBUrgEnb_MASK 0x400
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBUrgEnb__SHIFT 0xa
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBUrgCntMult_MASK 0x1800
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBUrgCntMult__SHIFT 0xb
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBStallMode_MASK 0x2000
+#define ACP_AXI2DAGB_ONION_CNTL__AXI2DAGBStallMode__SHIFT 0xd
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViolOver_MASK 0x2000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViolOver__SHIFT 0x19
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViolSource_MASK 0x1c000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViolSource__SHIFT 0x1a
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViol_MASK 0x20000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBAdrWinViol__SHIFT 0x1d
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBNackOver_MASK 0x40000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBNackOver__SHIFT 0x1e
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBNackVal_MASK 0x80000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_WR__AXI2DAGBNackVal__SHIFT 0x1f
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViolOver_MASK 0x2000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViolOver__SHIFT 0x19
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViolSource_MASK 0x1c000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViolSource__SHIFT 0x1a
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViol_MASK 0x20000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBAdrWinViol__SHIFT 0x1d
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBNackOver_MASK 0x40000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBNackOver__SHIFT 0x1e
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBNackVal_MASK 0x80000000
+#define ACP_AXI2DAGB_ONION_ERR_STATUS_RD__AXI2DAGBNackVal__SHIFT 0x1f
+#define ACP_DAGB_Onion_TransPerf_Counter_Control__EnbDAGBTransPerfCntr_MASK 0x1
+#define ACP_DAGB_Onion_TransPerf_Counter_Control__EnbDAGBTransPerfCntr__SHIFT 0x0
+#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime_MASK 0x1ffff
+#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime__SHIFT 0x0
+#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr_MASK 0x80000000
+#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr__SHIFT 0x1f
+#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime_MASK 0x1ffff
+#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime__SHIFT 0x0
+#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr_MASK 0x80000000
+#define ACP_DAGB_Onion_Wr_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr__SHIFT 0x1f
+#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime_MASK 0x1ffff
+#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime__SHIFT 0x0
+#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr_MASK 0x80000000
+#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr__SHIFT 0x1f
+#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime_MASK 0x1ffff
+#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime__SHIFT 0x0
+#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr_MASK 0x80000000
+#define ACP_DAGB_Onion_Rd_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr__SHIFT 0x1f
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBDataSwap_MASK 0x3
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBDataSwap__SHIFT 0x0
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBEnbMultRdReq_MASK 0x4
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBEnbMultRdReq__SHIFT 0x2
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBEnbMultWrReq_MASK 0x18
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBEnbMultWrReq__SHIFT 0x3
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBMaxReadBurst_MASK 0x60
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBMaxReadBurst__SHIFT 0x5
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBStallEnb_MASK 0x80
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBStallEnb__SHIFT 0x7
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBNackChkEnb_MASK 0x100
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBNackChkEnb__SHIFT 0x8
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBAdrWinViolChkEnb_MASK 0x200
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBAdrWinViolChkEnb__SHIFT 0x9
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBUrgEnb_MASK 0x400
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBUrgEnb__SHIFT 0xa
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBUrgCntMult_MASK 0x1800
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBUrgCntMult__SHIFT 0xb
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBStallMode_MASK 0x2000
+#define ACP_AXI2DAGB_GARLIC_CNTL__AXI2DAGBStallMode__SHIFT 0xd
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViolOver_MASK 0x2000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViolOver__SHIFT 0x19
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViolSource_MASK 0x1c000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViolSource__SHIFT 0x1a
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViol_MASK 0x20000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBAdrWinViol__SHIFT 0x1d
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBNackOver_MASK 0x40000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBNackOver__SHIFT 0x1e
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBNackVal_MASK 0x80000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_WR__AXI2DAGBNackVal__SHIFT 0x1f
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViolOver_MASK 0x2000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViolOver__SHIFT 0x19
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViolSource_MASK 0x1c000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViolSource__SHIFT 0x1a
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViol_MASK 0x20000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBAdrWinViol__SHIFT 0x1d
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBNackOver_MASK 0x40000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBNackOver__SHIFT 0x1e
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBNackVal_MASK 0x80000000
+#define ACP_AXI2DAGB_GARLIC_ERR_STATUS_RD__AXI2DAGBNackVal__SHIFT 0x1f
+#define ACP_DAGB_Garlic_TransPerf_Counter_Control__EnbDAGBTransPerfCntr_MASK 0x1
+#define ACP_DAGB_Garlic_TransPerf_Counter_Control__EnbDAGBTransPerfCntr__SHIFT 0x0
+#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime_MASK 0x1ffff
+#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime__SHIFT 0x0
+#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr_MASK 0x80000000
+#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr__SHIFT 0x1f
+#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime_MASK 0x1ffff
+#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime__SHIFT 0x0
+#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr_MASK 0x80000000
+#define ACP_DAGB_Garlic_Wr_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr__SHIFT 0x1f
+#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime_MASK 0x1ffff
+#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Current__CurDAGBTransPerfCntrTime__SHIFT 0x0
+#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr_MASK 0x80000000
+#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Current__ClrCurDAGBTransPerfCntr__SHIFT 0x1f
+#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime_MASK 0x1ffff
+#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak__PeakDAGBTransPerfCntrTime__SHIFT 0x0
+#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr_MASK 0x80000000
+#define ACP_DAGB_Garlic_Rd_TransPerf_Counter_Peak__ClrPeakDAGBTransPerfCntr__SHIFT 0x1f
+#define ACP_DAGB_PAGE_SIZE_GRP_1__AXI2DAGBPageSize_MASK 0x3
+#define ACP_DAGB_PAGE_SIZE_GRP_1__AXI2DAGBPageSize__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBBaseAddr_MASK 0xfffffff
+#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBBaseAddr__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBSnoopSel_MASK 0x20000000
+#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBSnoopSel__SHIFT 0x1d
+#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBTargetMemSel_MASK 0x40000000
+#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBTargetMemSel__SHIFT 0x1e
+#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBGrpEnable_MASK 0x80000000
+#define ACP_DAGB_BASE_ADDR_GRP_1__AXI2DAGBGrpEnable__SHIFT 0x1f
+#define ACP_DAGB_PAGE_SIZE_GRP_2__AXI2DAGBPageSize_MASK 0x3
+#define ACP_DAGB_PAGE_SIZE_GRP_2__AXI2DAGBPageSize__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBBaseAddr_MASK 0xfffffff
+#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBBaseAddr__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBSnoopSel_MASK 0x20000000
+#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBSnoopSel__SHIFT 0x1d
+#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBTargetMemSel_MASK 0x40000000
+#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBTargetMemSel__SHIFT 0x1e
+#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBGrpEnable_MASK 0x80000000
+#define ACP_DAGB_BASE_ADDR_GRP_2__AXI2DAGBGrpEnable__SHIFT 0x1f
+#define ACP_DAGB_PAGE_SIZE_GRP_3__AXI2DAGBPageSize_MASK 0x3
+#define ACP_DAGB_PAGE_SIZE_GRP_3__AXI2DAGBPageSize__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBBaseAddr_MASK 0xfffffff
+#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBBaseAddr__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBSnoopSel_MASK 0x20000000
+#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBSnoopSel__SHIFT 0x1d
+#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBTargetMemSel_MASK 0x40000000
+#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBTargetMemSel__SHIFT 0x1e
+#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBGrpEnable_MASK 0x80000000
+#define ACP_DAGB_BASE_ADDR_GRP_3__AXI2DAGBGrpEnable__SHIFT 0x1f
+#define ACP_DAGB_PAGE_SIZE_GRP_4__AXI2DAGBPageSize_MASK 0x3
+#define ACP_DAGB_PAGE_SIZE_GRP_4__AXI2DAGBPageSize__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBBaseAddr_MASK 0xfffffff
+#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBBaseAddr__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBSnoopSel_MASK 0x20000000
+#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBSnoopSel__SHIFT 0x1d
+#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBTargetMemSel_MASK 0x40000000
+#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBTargetMemSel__SHIFT 0x1e
+#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBGrpEnable_MASK 0x80000000
+#define ACP_DAGB_BASE_ADDR_GRP_4__AXI2DAGBGrpEnable__SHIFT 0x1f
+#define ACP_DAGB_PAGE_SIZE_GRP_5__AXI2DAGBPageSize_MASK 0x3
+#define ACP_DAGB_PAGE_SIZE_GRP_5__AXI2DAGBPageSize__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBBaseAddr_MASK 0xfffffff
+#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBBaseAddr__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBSnoopSel_MASK 0x20000000
+#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBSnoopSel__SHIFT 0x1d
+#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBTargetMemSel_MASK 0x40000000
+#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBTargetMemSel__SHIFT 0x1e
+#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBGrpEnable_MASK 0x80000000
+#define ACP_DAGB_BASE_ADDR_GRP_5__AXI2DAGBGrpEnable__SHIFT 0x1f
+#define ACP_DAGB_PAGE_SIZE_GRP_6__AXI2DAGBPageSize_MASK 0x3
+#define ACP_DAGB_PAGE_SIZE_GRP_6__AXI2DAGBPageSize__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBBaseAddr_MASK 0xfffffff
+#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBBaseAddr__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBSnoopSel_MASK 0x20000000
+#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBSnoopSel__SHIFT 0x1d
+#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBTargetMemSel_MASK 0x40000000
+#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBTargetMemSel__SHIFT 0x1e
+#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBGrpEnable_MASK 0x80000000
+#define ACP_DAGB_BASE_ADDR_GRP_6__AXI2DAGBGrpEnable__SHIFT 0x1f
+#define ACP_DAGB_PAGE_SIZE_GRP_7__AXI2DAGBPageSize_MASK 0x3
+#define ACP_DAGB_PAGE_SIZE_GRP_7__AXI2DAGBPageSize__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBBaseAddr_MASK 0xfffffff
+#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBBaseAddr__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBSnoopSel_MASK 0x20000000
+#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBSnoopSel__SHIFT 0x1d
+#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBTargetMemSel_MASK 0x40000000
+#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBTargetMemSel__SHIFT 0x1e
+#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBGrpEnable_MASK 0x80000000
+#define ACP_DAGB_BASE_ADDR_GRP_7__AXI2DAGBGrpEnable__SHIFT 0x1f
+#define ACP_DAGB_PAGE_SIZE_GRP_8__AXI2DAGBPageSize_MASK 0x3
+#define ACP_DAGB_PAGE_SIZE_GRP_8__AXI2DAGBPageSize__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBBaseAddr_MASK 0xfffffff
+#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBBaseAddr__SHIFT 0x0
+#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBSnoopSel_MASK 0x20000000
+#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBSnoopSel__SHIFT 0x1d
+#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBTargetMemSel_MASK 0x40000000
+#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBTargetMemSel__SHIFT 0x1e
+#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBGrpEnable_MASK 0x80000000
+#define ACP_DAGB_BASE_ADDR_GRP_8__AXI2DAGBGrpEnable__SHIFT 0x1f
+#define ACP_DAGB_ATU_CTRL__AXI2DAGBCacheInvalidate_MASK 0x1
+#define ACP_DAGB_ATU_CTRL__AXI2DAGBCacheInvalidate__SHIFT 0x0
+#define ACP_CONTROL__ClkEn_MASK 0x1
+#define ACP_CONTROL__ClkEn__SHIFT 0x0
+#define ACP_CONTROL__JtagEn_MASK 0x400
+#define ACP_CONTROL__JtagEn__SHIFT 0xa
+#define ACP_STATUS__ClkOn_MASK 0x1
+#define ACP_STATUS__ClkOn__SHIFT 0x0
+#define ACP_STATUS__ACPRefClkSpd_MASK 0x2
+#define ACP_STATUS__ACPRefClkSpd__SHIFT 0x1
+#define ACP_STATUS__SMUStutterLastEdge_MASK 0x4
+#define ACP_STATUS__SMUStutterLastEdge__SHIFT 0x2
+#define ACP_STATUS__MCStutterLastEdge_MASK 0x8
+#define ACP_STATUS__MCStutterLastEdge__SHIFT 0x3
+#define ACP_SOFT_RESET__SoftResetAud_MASK 0x100
+#define ACP_SOFT_RESET__SoftResetAud__SHIFT 0x8
+#define ACP_SOFT_RESET__SoftResetDMA_MASK 0x200
+#define ACP_SOFT_RESET__SoftResetDMA__SHIFT 0x9
+#define ACP_SOFT_RESET__InternalSoftResetMode_MASK 0x4000
+#define ACP_SOFT_RESET__InternalSoftResetMode__SHIFT 0xe
+#define ACP_SOFT_RESET__ExternalSoftResetMode_MASK 0x8000
+#define ACP_SOFT_RESET__ExternalSoftResetMode__SHIFT 0xf
+#define ACP_SOFT_RESET__SoftResetAudDone_MASK 0x1000000
+#define ACP_SOFT_RESET__SoftResetAudDone__SHIFT 0x18
+#define ACP_SOFT_RESET__SoftResetDMADone_MASK 0x2000000
+#define ACP_SOFT_RESET__SoftResetDMADone__SHIFT 0x19
+#define ACP_PwrMgmt_CNTL__SCLKSleepCntl_MASK 0x3
+#define ACP_PwrMgmt_CNTL__SCLKSleepCntl__SHIFT 0x0
+#define ACP_CAC_INDICATOR_CONTROL__ACP_Cac_Indicator_Counter_MASK 0xffff
+#define ACP_CAC_INDICATOR_CONTROL__ACP_Cac_Indicator_Counter__SHIFT 0x0
+#define ACP_SMU_MAILBOX__ACP_SMU_Mailbox_MASK 0xffffffff
+#define ACP_SMU_MAILBOX__ACP_SMU_Mailbox__SHIFT 0x0
+#define ACP_FUTURE_REG_SCLK_0__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_SCLK_0__ACPFutureReg__SHIFT 0x0
+#define ACP_FUTURE_REG_SCLK_1__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_SCLK_1__ACPFutureReg__SHIFT 0x0
+#define ACP_FUTURE_REG_SCLK_2__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_SCLK_2__ACPFutureReg__SHIFT 0x0
+#define ACP_FUTURE_REG_SCLK_3__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_SCLK_3__ACPFutureReg__SHIFT 0x0
+#define ACP_FUTURE_REG_SCLK_4__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_SCLK_4__ACPFutureReg__SHIFT 0x0
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_ask_cnt_enable_MASK 0x1
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_ask_cnt_enable__SHIFT 0x0
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_go_cnt_enable_MASK 0x2
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_go_cnt_enable__SHIFT 0x1
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_exp_respcnt_enable_MASK 0x4
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_exp_respcnt_enable__SHIFT 0x2
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_actual_respcnt_enable_MASK 0x8
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_wr_actual_respcnt_enable__SHIFT 0x3
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_ask_cnt_enable_MASK 0x10
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_ask_cnt_enable__SHIFT 0x4
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_go_cnt_enable_MASK 0x20
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_go_cnt_enable__SHIFT 0x5
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_exp_respcnt_enable_MASK 0x40
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_exp_respcnt_enable__SHIFT 0x6
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_actual_respcnt_enable_MASK 0x80
+#define ACP_DAGB_DEBUG_CNT_ENABLE__garlic_rd_actual_respcnt_enable__SHIFT 0x7
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_ask_cnt_enable_MASK 0x100
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_ask_cnt_enable__SHIFT 0x8
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_go_cnt_enable_MASK 0x200
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_go_cnt_enable__SHIFT 0x9
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_exp_respcnt_enable_MASK 0x400
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_exp_respcnt_enable__SHIFT 0xa
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_actual_respcnt_enable_MASK 0x800
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_wr_actual_respcnt_enable__SHIFT 0xb
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_ask_cnt_enable_MASK 0x1000
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_ask_cnt_enable__SHIFT 0xc
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_go_cnt_enable_MASK 0x2000
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_go_cnt_enable__SHIFT 0xd
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_exp_respcnt_enable_MASK 0x4000
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_exp_respcnt_enable__SHIFT 0xe
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_actual_respcnt_enable_MASK 0x8000
+#define ACP_DAGB_DEBUG_CNT_ENABLE__onion_rd_actual_respcnt_enable__SHIFT 0xf
+#define ACP_DAGBG_WR_ASK_CNT__garlic_wr_only_ask_cnt_MASK 0xffff
+#define ACP_DAGBG_WR_ASK_CNT__garlic_wr_only_ask_cnt__SHIFT 0x0
+#define ACP_DAGBG_WR_GO_CNT__garlic_wr_only_go_cnt_MASK 0xffff
+#define ACP_DAGBG_WR_GO_CNT__garlic_wr_only_go_cnt__SHIFT 0x0
+#define ACP_DAGBG_WR_EXP_RESP_CNT__garlic_wr_exp_resp_cnt_MASK 0xffff
+#define ACP_DAGBG_WR_EXP_RESP_CNT__garlic_wr_exp_resp_cnt__SHIFT 0x0
+#define ACP_DAGBG_WR_ACTUAL_RESP_CNT__garlic_wr_actual_resp_cnt_MASK 0xffff
+#define ACP_DAGBG_WR_ACTUAL_RESP_CNT__garlic_wr_actual_resp_cnt__SHIFT 0x0
+#define ACP_DAGBG_RD_ASK_CNT__garlic_rd_only_ask_cnt_MASK 0xffff
+#define ACP_DAGBG_RD_ASK_CNT__garlic_rd_only_ask_cnt__SHIFT 0x0
+#define ACP_DAGBG_RD_GO_CNT__garlic_rd_only_go_cnt_MASK 0xffff
+#define ACP_DAGBG_RD_GO_CNT__garlic_rd_only_go_cnt__SHIFT 0x0
+#define ACP_DAGBG_RD_EXP_RESP_CNT__garlic_rd_exp_resp_cnt_MASK 0xffff
+#define ACP_DAGBG_RD_EXP_RESP_CNT__garlic_rd_exp_resp_cnt__SHIFT 0x0
+#define ACP_DAGBG_RD_ACTUAL_RESP_CNT__garlic_rd_actual_resp_cnt_MASK 0xffff
+#define ACP_DAGBG_RD_ACTUAL_RESP_CNT__garlic_rd_actual_resp_cnt__SHIFT 0x0
+#define ACP_DAGBO_WR_ASK_CNT__onion_wr_only_ask_cnt_MASK 0xffff
+#define ACP_DAGBO_WR_ASK_CNT__onion_wr_only_ask_cnt__SHIFT 0x0
+#define ACP_DAGBO_WR_GO_CNT__onion_wr_only_go_cnt_MASK 0xffff
+#define ACP_DAGBO_WR_GO_CNT__onion_wr_only_go_cnt__SHIFT 0x0
+#define ACP_DAGBO_WR_EXP_RESP_CNT__onion_wr_exp_resp_cnt_MASK 0xffff
+#define ACP_DAGBO_WR_EXP_RESP_CNT__onion_wr_exp_resp_cnt__SHIFT 0x0
+#define ACP_DAGBO_WR_ACTUAL_RESP_CNT__onion_wr_actual_resp_cnt_MASK 0xffff
+#define ACP_DAGBO_WR_ACTUAL_RESP_CNT__onion_wr_actual_resp_cnt__SHIFT 0x0
+#define ACP_DAGBO_RD_ASK_CNT__onion_rd_only_ask_cnt_MASK 0xffff
+#define ACP_DAGBO_RD_ASK_CNT__onion_rd_only_ask_cnt__SHIFT 0x0
+#define ACP_DAGBO_RD_GO_CNT__onion_rd_only_go_cnt_MASK 0xffff
+#define ACP_DAGBO_RD_GO_CNT__onion_rd_only_go_cnt__SHIFT 0x0
+#define ACP_DAGBO_RD_EXP_RESP_CNT__onion_rd_exp_resp_cnt_MASK 0xffff
+#define ACP_DAGBO_RD_EXP_RESP_CNT__onion_rd_exp_resp_cnt__SHIFT 0x0
+#define ACP_DAGBO_RD_ACTUAL_RESP_CNT__onion_rd_actual_resp_cnt_MASK 0xffff
+#define ACP_DAGBO_RD_ACTUAL_RESP_CNT__onion_rd_actual_resp_cnt__SHIFT 0x0
+#define ACP_BRB_CONTROL__BRB_BlockSharedRAMArbCntrl_MASK 0xf
+#define ACP_BRB_CONTROL__BRB_BlockSharedRAMArbCntrl__SHIFT 0x0
+#define ACP_EXTERNAL_INTR_ENB__ACPExtIntrEnb_MASK 0x1
+#define ACP_EXTERNAL_INTR_ENB__ACPExtIntrEnb__SHIFT 0x0
+#define ACP_EXTERNAL_INTR_CNTL__ACPErrMask_MASK 0x1
+#define ACP_EXTERNAL_INTR_CNTL__ACPErrMask__SHIFT 0x0
+#define ACP_EXTERNAL_INTR_CNTL__I2SMicDataAvMask_MASK 0x2
+#define ACP_EXTERNAL_INTR_CNTL__I2SMicDataAvMask__SHIFT 0x1
+#define ACP_EXTERNAL_INTR_CNTL__I2SSpkr0DataEmptyMask_MASK 0x4
+#define ACP_EXTERNAL_INTR_CNTL__I2SSpkr0DataEmptyMask__SHIFT 0x2
+#define ACP_EXTERNAL_INTR_CNTL__I2SSpkr1DataEmptyMask_MASK 0x8
+#define ACP_EXTERNAL_INTR_CNTL__I2SSpkr1DataEmptyMask__SHIFT 0x3
+#define ACP_EXTERNAL_INTR_CNTL__I2SBTDataAvMask_MASK 0x10
+#define ACP_EXTERNAL_INTR_CNTL__I2SBTDataAvMask__SHIFT 0x4
+#define ACP_EXTERNAL_INTR_CNTL__AzaliaIntrMask_MASK 0x40
+#define ACP_EXTERNAL_INTR_CNTL__AzaliaIntrMask__SHIFT 0x6
+#define ACP_EXTERNAL_INTR_CNTL__DSP0TimeoutMask_MASK 0x100
+#define ACP_EXTERNAL_INTR_CNTL__DSP0TimeoutMask__SHIFT 0x8
+#define ACP_EXTERNAL_INTR_CNTL__DSP1TimeoutMask_MASK 0x200
+#define ACP_EXTERNAL_INTR_CNTL__DSP1TimeoutMask__SHIFT 0x9
+#define ACP_EXTERNAL_INTR_CNTL__DSP2TimeoutMask_MASK 0x400
+#define ACP_EXTERNAL_INTR_CNTL__DSP2TimeoutMask__SHIFT 0xa
+#define ACP_EXTERNAL_INTR_CNTL__I2SBTDataEmptyMask_MASK 0x800
+#define ACP_EXTERNAL_INTR_CNTL__I2SBTDataEmptyMask__SHIFT 0xb
+#define ACP_EXTERNAL_INTR_CNTL__DMAIOCMask_MASK 0xffff0000
+#define ACP_EXTERNAL_INTR_CNTL__DMAIOCMask__SHIFT 0x10
+#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErr_MASK 0x1
+#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErr__SHIFT 0x0
+#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErrSource_MASK 0xe
+#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErrSource__SHIFT 0x1
+#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErrSourceOver_MASK 0x10
+#define ACP_ERROR_SOURCE_STS__ACPRegUdefADDRErrSourceOver__SHIFT 0x4
+#define ACP_ERROR_SOURCE_STS__BRBAddrErr_MASK 0x20
+#define ACP_ERROR_SOURCE_STS__BRBAddrErr__SHIFT 0x5
+#define ACP_ERROR_SOURCE_STS__BRBAddrErrSource_MASK 0x3c0
+#define ACP_ERROR_SOURCE_STS__BRBAddrErrSource__SHIFT 0x6
+#define ACP_ERROR_SOURCE_STS__BRBAddrErrSourceOver_MASK 0x400
+#define ACP_ERROR_SOURCE_STS__BRBAddrErrSourceOver__SHIFT 0xa
+#define ACP_ERROR_SOURCE_STS__I2SMicOverFlowErr_MASK 0x800
+#define ACP_ERROR_SOURCE_STS__I2SMicOverFlowErr__SHIFT 0xb
+#define ACP_ERROR_SOURCE_STS__I2SSpeaker0OverFlowErr_MASK 0x1000
+#define ACP_ERROR_SOURCE_STS__I2SSpeaker0OverFlowErr__SHIFT 0xc
+#define ACP_ERROR_SOURCE_STS__I2SSpeaker1OverFlowErr_MASK 0x2000
+#define ACP_ERROR_SOURCE_STS__I2SSpeaker1OverFlowErr__SHIFT 0xd
+#define ACP_ERROR_SOURCE_STS__I2SBTRxFifoOverFlowErr_MASK 0x4000
+#define ACP_ERROR_SOURCE_STS__I2SBTRxFifoOverFlowErr__SHIFT 0xe
+#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErr_MASK 0x8000
+#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErr__SHIFT 0xf
+#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErrSource_MASK 0x70000
+#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErrSource__SHIFT 0x10
+#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErrSourceOver_MASK 0x80000
+#define ACP_ERROR_SOURCE_STS__DSPAdrTransRangeErrSourceOver__SHIFT 0x13
+#define ACP_ERROR_SOURCE_STS__DAGBErr_MASK 0x100000
+#define ACP_ERROR_SOURCE_STS__DAGBErr__SHIFT 0x14
+#define ACP_ERROR_SOURCE_STS__DAGBErrSource_MASK 0x1e00000
+#define ACP_ERROR_SOURCE_STS__DAGBErrSource__SHIFT 0x15
+#define ACP_ERROR_SOURCE_STS__DAGBErrSourceOver_MASK 0x2000000
+#define ACP_ERROR_SOURCE_STS__DAGBErrSourceOver__SHIFT 0x19
+#define ACP_ERROR_SOURCE_STS__DMATermOnErr_MASK 0x4000000
+#define ACP_ERROR_SOURCE_STS__DMATermOnErr__SHIFT 0x1a
+#define ACP_ERROR_SOURCE_STS__I2SBTTxFifoOverFlowErr_MASK 0x10000000
+#define ACP_ERROR_SOURCE_STS__I2SBTTxFifoOverFlowErr__SHIFT 0x1c
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP0_MASK 0x1
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP0__SHIFT 0x0
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP1_MASK 0x2
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP1__SHIFT 0x1
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP2_MASK 0x4
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntHostDSP2__SHIFT 0x2
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP0_MASK 0x100
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP0__SHIFT 0x8
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP1_MASK 0x200
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP1__SHIFT 0x9
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP2_MASK 0x400
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSPnDSP2__SHIFT 0xa
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP0Host_MASK 0x10000
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP0Host__SHIFT 0x10
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP1Host_MASK 0x20000
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP1Host__SHIFT 0x11
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP2Host_MASK 0x40000
+#define ACP_DSP_SW_INTR_TRIG__TrigSWIntDSP2Host__SHIFT 0x12
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP0_MASK 0x1
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP0__SHIFT 0x0
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP1_MASK 0x2
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP1__SHIFT 0x1
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP2_MASK 0x4
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntHostDSP2__SHIFT 0x2
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP0_MASK 0x100
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP0__SHIFT 0x8
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP1_MASK 0x200
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP1__SHIFT 0x9
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP2_MASK 0x400
+#define ACP_DSP_SW_INTR_CNTL__EnbSWIntDSPnDSP2__SHIFT 0xa
+#define ACP_DSP_SW_INTR_CNTL__EnbKernelIntrDSP0Mask_MASK 0x10000
+#define ACP_DSP_SW_INTR_CNTL__EnbKernelIntrDSP0Mask__SHIFT 0x10
+#define ACP_DSP_SW_INTR_CNTL__EmbKernelIntrDSP1Mask_MASK 0x20000
+#define ACP_DSP_SW_INTR_CNTL__EmbKernelIntrDSP1Mask__SHIFT 0x11
+#define ACP_DSP_SW_INTR_CNTL__EmbKernelIntrDSP2Mask_MASK 0x40000
+#define ACP_DSP_SW_INTR_CNTL__EmbKernelIntrDSP2Mask__SHIFT 0x12
+#define ACP_DAGBG_TIMEOUT_CNTL__DAGBGTimeoutValue_MASK 0x3ffff
+#define ACP_DAGBG_TIMEOUT_CNTL__DAGBGTimeoutValue__SHIFT 0x0
+#define ACP_DAGBG_TIMEOUT_CNTL__CntEn_MASK 0x80000000
+#define ACP_DAGBG_TIMEOUT_CNTL__CntEn__SHIFT 0x1f
+#define ACP_DAGBO_TIMEOUT_CNTL__DAGBOTimeoutValue_MASK 0x3ffff
+#define ACP_DAGBO_TIMEOUT_CNTL__DAGBOTimeoutValue__SHIFT 0x0
+#define ACP_DAGBO_TIMEOUT_CNTL__CntEn_MASK 0x80000000
+#define ACP_DAGBO_TIMEOUT_CNTL__CntEn__SHIFT 0x1f
+#define ACP_EXTERNAL_INTR_STAT__ACPErrStat_MASK 0x1
+#define ACP_EXTERNAL_INTR_STAT__ACPErrStat__SHIFT 0x0
+#define ACP_EXTERNAL_INTR_STAT__ACPErrAck_MASK 0x1
+#define ACP_EXTERNAL_INTR_STAT__ACPErrAck__SHIFT 0x0
+#define ACP_EXTERNAL_INTR_STAT__I2SMicDataAvStat_MASK 0x2
+#define ACP_EXTERNAL_INTR_STAT__I2SMicDataAvStat__SHIFT 0x1
+#define ACP_EXTERNAL_INTR_STAT__I2SMicDataAvAck_MASK 0x2
+#define ACP_EXTERNAL_INTR_STAT__I2SMicDataAvAck__SHIFT 0x1
+#define ACP_EXTERNAL_INTR_STAT__I2SSpkr0DataEmptyStat_MASK 0x4
+#define ACP_EXTERNAL_INTR_STAT__I2SSpkr0DataEmptyStat__SHIFT 0x2
+#define ACP_EXTERNAL_INTR_STAT__I2SSpkr0DataEmptyAck_MASK 0x4
+#define ACP_EXTERNAL_INTR_STAT__I2SSpkr0DataEmptyAck__SHIFT 0x2
+#define ACP_EXTERNAL_INTR_STAT__I2SSpkr1DataEmptyStat_MASK 0x8
+#define ACP_EXTERNAL_INTR_STAT__I2SSpkr1DataEmptyStat__SHIFT 0x3
+#define ACP_EXTERNAL_INTR_STAT__I2SSpkr1DataEmptyAck_MASK 0x8
+#define ACP_EXTERNAL_INTR_STAT__I2SSpkr1DataEmptyAck__SHIFT 0x3
+#define ACP_EXTERNAL_INTR_STAT__I2SBTDataAvStat_MASK 0x10
+#define ACP_EXTERNAL_INTR_STAT__I2SBTDataAvStat__SHIFT 0x4
+#define ACP_EXTERNAL_INTR_STAT__I2SBTDataAvAck_MASK 0x10
+#define ACP_EXTERNAL_INTR_STAT__I2SBTDataAvAck__SHIFT 0x4
+#define ACP_EXTERNAL_INTR_STAT__AzaliaIntrStat_MASK 0x40
+#define ACP_EXTERNAL_INTR_STAT__AzaliaIntrStat__SHIFT 0x6
+#define ACP_EXTERNAL_INTR_STAT__AzaliaIntrAck_MASK 0x40
+#define ACP_EXTERNAL_INTR_STAT__AzaliaIntrAck__SHIFT 0x6
+#define ACP_EXTERNAL_INTR_STAT__DSP0TimeoutStat_MASK 0x100
+#define ACP_EXTERNAL_INTR_STAT__DSP0TimeoutStat__SHIFT 0x8
+#define ACP_EXTERNAL_INTR_STAT__DSP0TimeoutAck_MASK 0x100
+#define ACP_EXTERNAL_INTR_STAT__DSP0TimeoutAck__SHIFT 0x8
+#define ACP_EXTERNAL_INTR_STAT__DSP1TimeoutStat_MASK 0x200
+#define ACP_EXTERNAL_INTR_STAT__DSP1TimeoutStat__SHIFT 0x9
+#define ACP_EXTERNAL_INTR_STAT__DSP1TimeoutAck_MASK 0x200
+#define ACP_EXTERNAL_INTR_STAT__DSP1TimeoutAck__SHIFT 0x9
+#define ACP_EXTERNAL_INTR_STAT__DSP2TimeoutStat_MASK 0x400
+#define ACP_EXTERNAL_INTR_STAT__DSP2TimeoutStat__SHIFT 0xa
+#define ACP_EXTERNAL_INTR_STAT__DSP2TimeoutAck_MASK 0x400
+#define ACP_EXTERNAL_INTR_STAT__DSP2TimeoutAck__SHIFT 0xa
+#define ACP_EXTERNAL_INTR_STAT__I2SBTDataEmptyStat_MASK 0x800
+#define ACP_EXTERNAL_INTR_STAT__I2SBTDataEmptyStat__SHIFT 0xb
+#define ACP_EXTERNAL_INTR_STAT__I2SBTDataEmptyAck_MASK 0x800
+#define ACP_EXTERNAL_INTR_STAT__I2SBTDataEmptyAck__SHIFT 0xb
+#define ACP_EXTERNAL_INTR_STAT__DMAIOCStat_MASK 0xffff0000
+#define ACP_EXTERNAL_INTR_STAT__DMAIOCStat__SHIFT 0x10
+#define ACP_EXTERNAL_INTR_STAT__DMAIOCAck_MASK 0xffff0000
+#define ACP_EXTERNAL_INTR_STAT__DMAIOCAck__SHIFT 0x10
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP0Stat_MASK 0x1
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP0Stat__SHIFT 0x0
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP0Ack_MASK 0x1
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP0Ack__SHIFT 0x0
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP1Stat_MASK 0x2
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP1Stat__SHIFT 0x1
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP1Ack_MASK 0x2
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP1Ack__SHIFT 0x1
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP2Stat_MASK 0x4
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP2Stat__SHIFT 0x2
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP2Ack_MASK 0x4
+#define ACP_DSP_SW_INTR_STAT__SWIntHostDSP2Ack__SHIFT 0x2
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP0Stat_MASK 0x100
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP0Stat__SHIFT 0x8
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP0Ack_MASK 0x100
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP0Ack__SHIFT 0x8
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP1Stat_MASK 0x200
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP1Stat__SHIFT 0x9
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP1Ack_MASK 0x200
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP1Ack__SHIFT 0x9
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP2Stat_MASK 0x400
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP2Stat__SHIFT 0xa
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP2Ack_MASK 0x400
+#define ACP_DSP_SW_INTR_STAT__SWIntDSPnDSP2Ack__SHIFT 0xa
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP0Stat_MASK 0x10000
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP0Stat__SHIFT 0x10
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP0Ack_MASK 0x10000
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP0Ack__SHIFT 0x10
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP1Stat_MASK 0x20000
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP1Stat__SHIFT 0x11
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP1Ack_MASK 0x20000
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP1Ack__SHIFT 0x11
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP2Stat_MASK 0x40000
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP2Stat__SHIFT 0x12
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP2Ack_MASK 0x40000
+#define ACP_DSP_SW_INTR_STAT__SWKernelIntrDSP2Ack__SHIFT 0x12
+#define ACP_DSP0_INTR_CNTL__ACPErrMask_MASK 0x1
+#define ACP_DSP0_INTR_CNTL__ACPErrMask__SHIFT 0x0
+#define ACP_DSP0_INTR_CNTL__I2SMicDataAvMask_MASK 0x2
+#define ACP_DSP0_INTR_CNTL__I2SMicDataAvMask__SHIFT 0x1
+#define ACP_DSP0_INTR_CNTL__I2SSpkr0DataEmptyMask_MASK 0x4
+#define ACP_DSP0_INTR_CNTL__I2SSpkr0DataEmptyMask__SHIFT 0x2
+#define ACP_DSP0_INTR_CNTL__I2SSpkr1DataEmptyMask_MASK 0x8
+#define ACP_DSP0_INTR_CNTL__I2SSpkr1DataEmptyMask__SHIFT 0x3
+#define ACP_DSP0_INTR_CNTL__I2SBTDataAvMask_MASK 0x10
+#define ACP_DSP0_INTR_CNTL__I2SBTDataAvMask__SHIFT 0x4
+#define ACP_DSP0_INTR_CNTL__AzaliaIntrMask_MASK 0x40
+#define ACP_DSP0_INTR_CNTL__AzaliaIntrMask__SHIFT 0x6
+#define ACP_DSP0_INTR_CNTL__SMUMailboxWriteMask_MASK 0x100
+#define ACP_DSP0_INTR_CNTL__SMUMailboxWriteMask__SHIFT 0x8
+#define ACP_DSP0_INTR_CNTL__SMUStutterStatusMask_MASK 0x200
+#define ACP_DSP0_INTR_CNTL__SMUStutterStatusMask__SHIFT 0x9
+#define ACP_DSP0_INTR_CNTL__MCStutterStatusMask_MASK 0x400
+#define ACP_DSP0_INTR_CNTL__MCStutterStatusMask__SHIFT 0xa
+#define ACP_DSP0_INTR_CNTL__DSPExtTimerMask_MASK 0x800
+#define ACP_DSP0_INTR_CNTL__DSPExtTimerMask__SHIFT 0xb
+#define ACP_DSP0_INTR_CNTL__DSPSemRespMask_MASK 0x1000
+#define ACP_DSP0_INTR_CNTL__DSPSemRespMask__SHIFT 0xc
+#define ACP_DSP0_INTR_CNTL__I2SBTDataEmptyMask_MASK 0x2000
+#define ACP_DSP0_INTR_CNTL__I2SBTDataEmptyMask__SHIFT 0xd
+#define ACP_DSP0_INTR_CNTL__DMAIOCMask_MASK 0xffff0000
+#define ACP_DSP0_INTR_CNTL__DMAIOCMask__SHIFT 0x10
+#define ACP_DSP0_INTR_STAT__ACPErrStat_MASK 0x1
+#define ACP_DSP0_INTR_STAT__ACPErrStat__SHIFT 0x0
+#define ACP_DSP0_INTR_STAT__ACPErrAck_MASK 0x1
+#define ACP_DSP0_INTR_STAT__ACPErrAck__SHIFT 0x0
+#define ACP_DSP0_INTR_STAT__I2SMicDataAvStat_MASK 0x2
+#define ACP_DSP0_INTR_STAT__I2SMicDataAvStat__SHIFT 0x1
+#define ACP_DSP0_INTR_STAT__I2SMicDataAvAck_MASK 0x2
+#define ACP_DSP0_INTR_STAT__I2SMicDataAvAck__SHIFT 0x1
+#define ACP_DSP0_INTR_STAT__I2SSpkr0DataEmptyStat_MASK 0x4
+#define ACP_DSP0_INTR_STAT__I2SSpkr0DataEmptyStat__SHIFT 0x2
+#define ACP_DSP0_INTR_STAT__I2SSpkr0DataEmptyAck_MASK 0x4
+#define ACP_DSP0_INTR_STAT__I2SSpkr0DataEmptyAck__SHIFT 0x2
+#define ACP_DSP0_INTR_STAT__I2SSpkr1DataEmptyStat_MASK 0x8
+#define ACP_DSP0_INTR_STAT__I2SSpkr1DataEmptyStat__SHIFT 0x3
+#define ACP_DSP0_INTR_STAT__I2SSpkr1DataEmptyAck_MASK 0x8
+#define ACP_DSP0_INTR_STAT__I2SSpkr1DataEmptyAck__SHIFT 0x3
+#define ACP_DSP0_INTR_STAT__I2SBTDataAvStat_MASK 0x10
+#define ACP_DSP0_INTR_STAT__I2SBTDataAvStat__SHIFT 0x4
+#define ACP_DSP0_INTR_STAT__I2SBTDataAvAck_MASK 0x10
+#define ACP_DSP0_INTR_STAT__I2SBTDataAvAck__SHIFT 0x4
+#define ACP_DSP0_INTR_STAT__AzaliaIntrStat_MASK 0x40
+#define ACP_DSP0_INTR_STAT__AzaliaIntrStat__SHIFT 0x6
+#define ACP_DSP0_INTR_STAT__AzaliaIntrAck_MASK 0x40
+#define ACP_DSP0_INTR_STAT__AzaliaIntrAck__SHIFT 0x6
+#define ACP_DSP0_INTR_STAT__SMUMailboxWriteStat_MASK 0x100
+#define ACP_DSP0_INTR_STAT__SMUMailboxWriteStat__SHIFT 0x8
+#define ACP_DSP0_INTR_STAT__SMUMailboxWriteAck_MASK 0x100
+#define ACP_DSP0_INTR_STAT__SMUMailboxWriteAck__SHIFT 0x8
+#define ACP_DSP0_INTR_STAT__SMUStutterStatusStat_MASK 0x200
+#define ACP_DSP0_INTR_STAT__SMUStutterStatusStat__SHIFT 0x9
+#define ACP_DSP0_INTR_STAT__SMUStutterStatusAck_MASK 0x200
+#define ACP_DSP0_INTR_STAT__SMUStutterStatusAck__SHIFT 0x9
+#define ACP_DSP0_INTR_STAT__MCStutterStatusStat_MASK 0x400
+#define ACP_DSP0_INTR_STAT__MCStutterStatusStat__SHIFT 0xa
+#define ACP_DSP0_INTR_STAT__MCStutterStatusAck_MASK 0x400
+#define ACP_DSP0_INTR_STAT__MCStutterStatusAck__SHIFT 0xa
+#define ACP_DSP0_INTR_STAT__DSPExtTimerStat_MASK 0x800
+#define ACP_DSP0_INTR_STAT__DSPExtTimerStat__SHIFT 0xb
+#define ACP_DSP0_INTR_STAT__DSPExtTimerAck_MASK 0x800
+#define ACP_DSP0_INTR_STAT__DSPExtTimerAck__SHIFT 0xb
+#define ACP_DSP0_INTR_STAT__DSPSemRespStat_MASK 0x1000
+#define ACP_DSP0_INTR_STAT__DSPSemRespStat__SHIFT 0xc
+#define ACP_DSP0_INTR_STAT__DSPSemRespAck_MASK 0x1000
+#define ACP_DSP0_INTR_STAT__DSPSemRespAck__SHIFT 0xc
+#define ACP_DSP0_INTR_STAT__I2SBTDataEmptyStat_MASK 0x2000
+#define ACP_DSP0_INTR_STAT__I2SBTDataEmptyStat__SHIFT 0xd
+#define ACP_DSP0_INTR_STAT__I2SBTDataEmptyAck_MASK 0x2000
+#define ACP_DSP0_INTR_STAT__I2SBTDataEmptyAck__SHIFT 0xd
+#define ACP_DSP0_INTR_STAT__DMAIOCStat_MASK 0xffff0000
+#define ACP_DSP0_INTR_STAT__DMAIOCStat__SHIFT 0x10
+#define ACP_DSP0_INTR_STAT__DMAIOCAck_MASK 0xffff0000
+#define ACP_DSP0_INTR_STAT__DMAIOCAck__SHIFT 0x10
+#define ACP_DSP0_TIMEOUT_CNTL__DSP0TimeoutValue_MASK 0x3ffff
+#define ACP_DSP0_TIMEOUT_CNTL__DSP0TimeoutValue__SHIFT 0x0
+#define ACP_DSP0_TIMEOUT_CNTL__CntEn_MASK 0x80000000
+#define ACP_DSP0_TIMEOUT_CNTL__CntEn__SHIFT 0x1f
+#define ACP_DSP1_INTR_CNTL__ACPErrMask_MASK 0x1
+#define ACP_DSP1_INTR_CNTL__ACPErrMask__SHIFT 0x0
+#define ACP_DSP1_INTR_CNTL__I2SMicDataAvMask_MASK 0x2
+#define ACP_DSP1_INTR_CNTL__I2SMicDataAvMask__SHIFT 0x1
+#define ACP_DSP1_INTR_CNTL__I2SSpkr0DataEmptyMask_MASK 0x4
+#define ACP_DSP1_INTR_CNTL__I2SSpkr0DataEmptyMask__SHIFT 0x2
+#define ACP_DSP1_INTR_CNTL__I2SSpkr1DataEmptyMask_MASK 0x8
+#define ACP_DSP1_INTR_CNTL__I2SSpkr1DataEmptyMask__SHIFT 0x3
+#define ACP_DSP1_INTR_CNTL__I2SBTDataAvMask_MASK 0x10
+#define ACP_DSP1_INTR_CNTL__I2SBTDataAvMask__SHIFT 0x4
+#define ACP_DSP1_INTR_CNTL__AzaliaIntrMask_MASK 0x40
+#define ACP_DSP1_INTR_CNTL__AzaliaIntrMask__SHIFT 0x6
+#define ACP_DSP1_INTR_CNTL__SMUMailboxWriteMask_MASK 0x100
+#define ACP_DSP1_INTR_CNTL__SMUMailboxWriteMask__SHIFT 0x8
+#define ACP_DSP1_INTR_CNTL__SMUStutterStatusMask_MASK 0x200
+#define ACP_DSP1_INTR_CNTL__SMUStutterStatusMask__SHIFT 0x9
+#define ACP_DSP1_INTR_CNTL__MCStutterStatusMask_MASK 0x400
+#define ACP_DSP1_INTR_CNTL__MCStutterStatusMask__SHIFT 0xa
+#define ACP_DSP1_INTR_CNTL__DSPExtTimerMask_MASK 0x800
+#define ACP_DSP1_INTR_CNTL__DSPExtTimerMask__SHIFT 0xb
+#define ACP_DSP1_INTR_CNTL__DSPSemRespMask_MASK 0x1000
+#define ACP_DSP1_INTR_CNTL__DSPSemRespMask__SHIFT 0xc
+#define ACP_DSP1_INTR_CNTL__I2SBTDataEmptyMask_MASK 0x2000
+#define ACP_DSP1_INTR_CNTL__I2SBTDataEmptyMask__SHIFT 0xd
+#define ACP_DSP1_INTR_CNTL__DMAIOCMask_MASK 0xffff0000
+#define ACP_DSP1_INTR_CNTL__DMAIOCMask__SHIFT 0x10
+#define ACP_DSP1_INTR_STAT__ACPErrStat_MASK 0x1
+#define ACP_DSP1_INTR_STAT__ACPErrStat__SHIFT 0x0
+#define ACP_DSP1_INTR_STAT__ACPErrAck_MASK 0x1
+#define ACP_DSP1_INTR_STAT__ACPErrAck__SHIFT 0x0
+#define ACP_DSP1_INTR_STAT__I2SMicDataAvStat_MASK 0x2
+#define ACP_DSP1_INTR_STAT__I2SMicDataAvStat__SHIFT 0x1
+#define ACP_DSP1_INTR_STAT__I2SMicDataAvAck_MASK 0x2
+#define ACP_DSP1_INTR_STAT__I2SMicDataAvAck__SHIFT 0x1
+#define ACP_DSP1_INTR_STAT__I2SSpkr0DataEmptyStat_MASK 0x4
+#define ACP_DSP1_INTR_STAT__I2SSpkr0DataEmptyStat__SHIFT 0x2
+#define ACP_DSP1_INTR_STAT__I2SSpkr0DataEmptyAck_MASK 0x4
+#define ACP_DSP1_INTR_STAT__I2SSpkr0DataEmptyAck__SHIFT 0x2
+#define ACP_DSP1_INTR_STAT__I2SSpkr1DataEmptyStat_MASK 0x8
+#define ACP_DSP1_INTR_STAT__I2SSpkr1DataEmptyStat__SHIFT 0x3
+#define ACP_DSP1_INTR_STAT__I2SSpkr1DataEmptyAck_MASK 0x8
+#define ACP_DSP1_INTR_STAT__I2SSpkr1DataEmptyAck__SHIFT 0x3
+#define ACP_DSP1_INTR_STAT__I2SBTDataAvStat_MASK 0x10
+#define ACP_DSP1_INTR_STAT__I2SBTDataAvStat__SHIFT 0x4
+#define ACP_DSP1_INTR_STAT__I2SBTDataAvAck_MASK 0x10
+#define ACP_DSP1_INTR_STAT__I2SBTDataAvAck__SHIFT 0x4
+#define ACP_DSP1_INTR_STAT__AzaliaIntrStat_MASK 0x40
+#define ACP_DSP1_INTR_STAT__AzaliaIntrStat__SHIFT 0x6
+#define ACP_DSP1_INTR_STAT__AzaliaIntrAck_MASK 0x40
+#define ACP_DSP1_INTR_STAT__AzaliaIntrAck__SHIFT 0x6
+#define ACP_DSP1_INTR_STAT__SMUMailboxWriteStat_MASK 0x100
+#define ACP_DSP1_INTR_STAT__SMUMailboxWriteStat__SHIFT 0x8
+#define ACP_DSP1_INTR_STAT__SMUMailboxWriteAck_MASK 0x100
+#define ACP_DSP1_INTR_STAT__SMUMailboxWriteAck__SHIFT 0x8
+#define ACP_DSP1_INTR_STAT__SMUStutterStatusStat_MASK 0x200
+#define ACP_DSP1_INTR_STAT__SMUStutterStatusStat__SHIFT 0x9
+#define ACP_DSP1_INTR_STAT__SMUStutterStatusAck_MASK 0x200
+#define ACP_DSP1_INTR_STAT__SMUStutterStatusAck__SHIFT 0x9
+#define ACP_DSP1_INTR_STAT__MCStutterStatusStat_MASK 0x400
+#define ACP_DSP1_INTR_STAT__MCStutterStatusStat__SHIFT 0xa
+#define ACP_DSP1_INTR_STAT__MCStutterStatusAck_MASK 0x400
+#define ACP_DSP1_INTR_STAT__MCStutterStatusAck__SHIFT 0xa
+#define ACP_DSP1_INTR_STAT__DSPExtTimerStat_MASK 0x800
+#define ACP_DSP1_INTR_STAT__DSPExtTimerStat__SHIFT 0xb
+#define ACP_DSP1_INTR_STAT__DSPExtTimerAck_MASK 0x800
+#define ACP_DSP1_INTR_STAT__DSPExtTimerAck__SHIFT 0xb
+#define ACP_DSP1_INTR_STAT__DSPSemRespStat_MASK 0x1000
+#define ACP_DSP1_INTR_STAT__DSPSemRespStat__SHIFT 0xc
+#define ACP_DSP1_INTR_STAT__DSPSemRespAck_MASK 0x1000
+#define ACP_DSP1_INTR_STAT__DSPSemRespAck__SHIFT 0xc
+#define ACP_DSP1_INTR_STAT__I2SBTDataEmptyStat_MASK 0x2000
+#define ACP_DSP1_INTR_STAT__I2SBTDataEmptyStat__SHIFT 0xd
+#define ACP_DSP1_INTR_STAT__I2SBTDataEmptyAck_MASK 0x2000
+#define ACP_DSP1_INTR_STAT__I2SBTDataEmptyAck__SHIFT 0xd
+#define ACP_DSP1_INTR_STAT__DMAIOCStat_MASK 0xffff0000
+#define ACP_DSP1_INTR_STAT__DMAIOCStat__SHIFT 0x10
+#define ACP_DSP1_INTR_STAT__DMAIOCAck_MASK 0xffff0000
+#define ACP_DSP1_INTR_STAT__DMAIOCAck__SHIFT 0x10
+#define ACP_DSP1_TIMEOUT_CNTL__DSP1TimeoutValue_MASK 0x3ffff
+#define ACP_DSP1_TIMEOUT_CNTL__DSP1TimeoutValue__SHIFT 0x0
+#define ACP_DSP1_TIMEOUT_CNTL__CntEn_MASK 0x80000000
+#define ACP_DSP1_TIMEOUT_CNTL__CntEn__SHIFT 0x1f
+#define ACP_DSP2_INTR_CNTL__ACPErrMask_MASK 0x1
+#define ACP_DSP2_INTR_CNTL__ACPErrMask__SHIFT 0x0
+#define ACP_DSP2_INTR_CNTL__I2SMicDataAvMask_MASK 0x2
+#define ACP_DSP2_INTR_CNTL__I2SMicDataAvMask__SHIFT 0x1
+#define ACP_DSP2_INTR_CNTL__I2SSpkr0DataEmptyMask_MASK 0x4
+#define ACP_DSP2_INTR_CNTL__I2SSpkr0DataEmptyMask__SHIFT 0x2
+#define ACP_DSP2_INTR_CNTL__I2SSpkr1DataEmptyMask_MASK 0x8
+#define ACP_DSP2_INTR_CNTL__I2SSpkr1DataEmptyMask__SHIFT 0x3
+#define ACP_DSP2_INTR_CNTL__I2SBTDataAvMask_MASK 0x10
+#define ACP_DSP2_INTR_CNTL__I2SBTDataAvMask__SHIFT 0x4
+#define ACP_DSP2_INTR_CNTL__AzaliaIntrMask_MASK 0x40
+#define ACP_DSP2_INTR_CNTL__AzaliaIntrMask__SHIFT 0x6
+#define ACP_DSP2_INTR_CNTL__SMUMailboxWriteMask_MASK 0x100
+#define ACP_DSP2_INTR_CNTL__SMUMailboxWriteMask__SHIFT 0x8
+#define ACP_DSP2_INTR_CNTL__SMUStutterStatusMask_MASK 0x200
+#define ACP_DSP2_INTR_CNTL__SMUStutterStatusMask__SHIFT 0x9
+#define ACP_DSP2_INTR_CNTL__MCStutterStatusMask_MASK 0x400
+#define ACP_DSP2_INTR_CNTL__MCStutterStatusMask__SHIFT 0xa
+#define ACP_DSP2_INTR_CNTL__DSPExtTimerMask_MASK 0x800
+#define ACP_DSP2_INTR_CNTL__DSPExtTimerMask__SHIFT 0xb
+#define ACP_DSP2_INTR_CNTL__DSPSemRespMask_MASK 0x1000
+#define ACP_DSP2_INTR_CNTL__DSPSemRespMask__SHIFT 0xc
+#define ACP_DSP2_INTR_CNTL__I2SBTDataEmptyMask_MASK 0x2000
+#define ACP_DSP2_INTR_CNTL__I2SBTDataEmptyMask__SHIFT 0xd
+#define ACP_DSP2_INTR_CNTL__DMAIOCMask_MASK 0xffff0000
+#define ACP_DSP2_INTR_CNTL__DMAIOCMask__SHIFT 0x10
+#define ACP_DSP2_INTR_STAT__ACPErrStat_MASK 0x1
+#define ACP_DSP2_INTR_STAT__ACPErrStat__SHIFT 0x0
+#define ACP_DSP2_INTR_STAT__ACPErrAck_MASK 0x1
+#define ACP_DSP2_INTR_STAT__ACPErrAck__SHIFT 0x0
+#define ACP_DSP2_INTR_STAT__I2SMicDataAvStat_MASK 0x2
+#define ACP_DSP2_INTR_STAT__I2SMicDataAvStat__SHIFT 0x1
+#define ACP_DSP2_INTR_STAT__I2SMicDataAvAck_MASK 0x2
+#define ACP_DSP2_INTR_STAT__I2SMicDataAvAck__SHIFT 0x1
+#define ACP_DSP2_INTR_STAT__I2SSpkr0DataEmptyStat_MASK 0x4
+#define ACP_DSP2_INTR_STAT__I2SSpkr0DataEmptyStat__SHIFT 0x2
+#define ACP_DSP2_INTR_STAT__I2SSpkr0DataEmptyAck_MASK 0x4
+#define ACP_DSP2_INTR_STAT__I2SSpkr0DataEmptyAck__SHIFT 0x2
+#define ACP_DSP2_INTR_STAT__I2SSpkr1DataEmptyStat_MASK 0x8
+#define ACP_DSP2_INTR_STAT__I2SSpkr1DataEmptyStat__SHIFT 0x3
+#define ACP_DSP2_INTR_STAT__I2SSpkr1DataEmptyAck_MASK 0x8
+#define ACP_DSP2_INTR_STAT__I2SSpkr1DataEmptyAck__SHIFT 0x3
+#define ACP_DSP2_INTR_STAT__I2SBTDataAvStat_MASK 0x10
+#define ACP_DSP2_INTR_STAT__I2SBTDataAvStat__SHIFT 0x4
+#define ACP_DSP2_INTR_STAT__I2SBTDataAvAck_MASK 0x10
+#define ACP_DSP2_INTR_STAT__I2SBTDataAvAck__SHIFT 0x4
+#define ACP_DSP2_INTR_STAT__AzaliaIntrStat_MASK 0x40
+#define ACP_DSP2_INTR_STAT__AzaliaIntrStat__SHIFT 0x6
+#define ACP_DSP2_INTR_STAT__AzaliaIntrAck_MASK 0x40
+#define ACP_DSP2_INTR_STAT__AzaliaIntrAck__SHIFT 0x6
+#define ACP_DSP2_INTR_STAT__SMUMailboxWriteStat_MASK 0x100
+#define ACP_DSP2_INTR_STAT__SMUMailboxWriteStat__SHIFT 0x8
+#define ACP_DSP2_INTR_STAT__SMUMailboxWriteAck_MASK 0x100
+#define ACP_DSP2_INTR_STAT__SMUMailboxWriteAck__SHIFT 0x8
+#define ACP_DSP2_INTR_STAT__SMUStutterStatusStat_MASK 0x200
+#define ACP_DSP2_INTR_STAT__SMUStutterStatusStat__SHIFT 0x9
+#define ACP_DSP2_INTR_STAT__SMUStutterStatusAck_MASK 0x200
+#define ACP_DSP2_INTR_STAT__SMUStutterStatusAck__SHIFT 0x9
+#define ACP_DSP2_INTR_STAT__MCStutterStatusStat_MASK 0x400
+#define ACP_DSP2_INTR_STAT__MCStutterStatusStat__SHIFT 0xa
+#define ACP_DSP2_INTR_STAT__MCStutterStatusAck_MASK 0x400
+#define ACP_DSP2_INTR_STAT__MCStutterStatusAck__SHIFT 0xa
+#define ACP_DSP2_INTR_STAT__DSPExtTimerStat_MASK 0x800
+#define ACP_DSP2_INTR_STAT__DSPExtTimerStat__SHIFT 0xb
+#define ACP_DSP2_INTR_STAT__DSPExtTimerAck_MASK 0x800
+#define ACP_DSP2_INTR_STAT__DSPExtTimerAck__SHIFT 0xb
+#define ACP_DSP2_INTR_STAT__DSPSemRespStat_MASK 0x1000
+#define ACP_DSP2_INTR_STAT__DSPSemRespStat__SHIFT 0xc
+#define ACP_DSP2_INTR_STAT__DSPSemRespAck_MASK 0x1000
+#define ACP_DSP2_INTR_STAT__DSPSemRespAck__SHIFT 0xc
+#define ACP_DSP2_INTR_STAT__I2SBTDataEmptyStat_MASK 0x2000
+#define ACP_DSP2_INTR_STAT__I2SBTDataEmptyStat__SHIFT 0xd
+#define ACP_DSP2_INTR_STAT__I2SBTDataEmptyAck_MASK 0x2000
+#define ACP_DSP2_INTR_STAT__I2SBTDataEmptyAck__SHIFT 0xd
+#define ACP_DSP2_INTR_STAT__DMAIOCStat_MASK 0xffff0000
+#define ACP_DSP2_INTR_STAT__DMAIOCStat__SHIFT 0x10
+#define ACP_DSP2_INTR_STAT__DMAIOCAck_MASK 0xffff0000
+#define ACP_DSP2_INTR_STAT__DMAIOCAck__SHIFT 0x10
+#define ACP_DSP2_TIMEOUT_CNTL__DSP2TimeoutValue_MASK 0x3ffff
+#define ACP_DSP2_TIMEOUT_CNTL__DSP2TimeoutValue__SHIFT 0x0
+#define ACP_DSP2_TIMEOUT_CNTL__CntEn_MASK 0x80000000
+#define ACP_DSP2_TIMEOUT_CNTL__CntEn__SHIFT 0x1f
+#define ACP_DSP0_EXT_TIMER_CNTL__TimerCount_MASK 0xffffff
+#define ACP_DSP0_EXT_TIMER_CNTL__TimerCount__SHIFT 0x0
+#define ACP_DSP0_EXT_TIMER_CNTL__TimerCntl_MASK 0xc0000000
+#define ACP_DSP0_EXT_TIMER_CNTL__TimerCntl__SHIFT 0x1e
+#define ACP_DSP1_EXT_TIMER_CNTL__TimerCount_MASK 0xffffff
+#define ACP_DSP1_EXT_TIMER_CNTL__TimerCount__SHIFT 0x0
+#define ACP_DSP1_EXT_TIMER_CNTL__TimerCntl_MASK 0xc0000000
+#define ACP_DSP1_EXT_TIMER_CNTL__TimerCntl__SHIFT 0x1e
+#define ACP_DSP2_EXT_TIMER_CNTL__TimerCount_MASK 0xffffff
+#define ACP_DSP2_EXT_TIMER_CNTL__TimerCount__SHIFT 0x0
+#define ACP_DSP2_EXT_TIMER_CNTL__TimerCntl_MASK 0xc0000000
+#define ACP_DSP2_EXT_TIMER_CNTL__TimerCntl__SHIFT 0x1e
+#define ACP_AXI2DAGB_SEM_0__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_0__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_1__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_1__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_2__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_2__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_3__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_3__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_4__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_4__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_5__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_5__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_6__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_6__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_7__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_7__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_8__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_8__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_9__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_9__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_10__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_10__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_11__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_11__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_12__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_12__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_13__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_13__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_14__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_14__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_15__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_15__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_16__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_16__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_17__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_17__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_18__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_18__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_19__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_19__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_20__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_20__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_21__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_21__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_22__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_22__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_23__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_23__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_24__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_24__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_25__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_25__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_26__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_26__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_27__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_27__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_28__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_28__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_29__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_29__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_30__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_30__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_31__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_31__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_32__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_32__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_33__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_33__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_34__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_34__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_35__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_35__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_36__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_36__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_37__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_37__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_38__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_38__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_39__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_39__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_40__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_40__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_41__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_41__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_42__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_42__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_43__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_43__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_44__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_44__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_45__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_45__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_46__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_46__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_AXI2DAGB_SEM_47__AXI2DAGBGblSemReg_MASK 0x1
+#define ACP_AXI2DAGB_SEM_47__AXI2DAGBGblSemReg__SHIFT 0x0
+#define ACP_SRBM_Client_Base_Addr__SRBM_Client_base_addr_MASK 0xff
+#define ACP_SRBM_Client_Base_Addr__SRBM_Client_base_addr__SHIFT 0x0
+#define ACP_SRBM_Client_RDDATA__ReadData_MASK 0xffffffff
+#define ACP_SRBM_Client_RDDATA__ReadData__SHIFT 0x0
+#define ACP_SRBM_Cycle_Sts__SRBM_Client_Sts_MASK 0x1
+#define ACP_SRBM_Cycle_Sts__SRBM_Client_Sts__SHIFT 0x0
+#define ACP_SRBM_Targ_Idx_Addr__SRBM_Targ_Idx_addr_MASK 0x7ffffff
+#define ACP_SRBM_Targ_Idx_Addr__SRBM_Targ_Idx_addr__SHIFT 0x0
+#define ACP_SRBM_Targ_Idx_Data__SRBM_Targ_Idx_Data_MASK 0xffffffff
+#define ACP_SRBM_Targ_Idx_Data__SRBM_Targ_Idx_Data__SHIFT 0x0
+#define ACP_SEMA_ADDR_LOW__ADDR_9_3_MASK 0x7f
+#define ACP_SEMA_ADDR_LOW__ADDR_9_3__SHIFT 0x0
+#define ACP_SEMA_ADDR_HIGH__ADDR_39_10_MASK 0x3fffffff
+#define ACP_SEMA_ADDR_HIGH__ADDR_39_10__SHIFT 0x0
+#define ACP_SEMA_CMD__REQ_CMD_MASK 0xf
+#define ACP_SEMA_CMD__REQ_CMD__SHIFT 0x0
+#define ACP_SEMA_CMD__WR_PHASE_MASK 0x30
+#define ACP_SEMA_CMD__WR_PHASE__SHIFT 0x4
+#define ACP_SEMA_CMD__VMID_EN_MASK 0x80
+#define ACP_SEMA_CMD__VMID_EN__SHIFT 0x7
+#define ACP_SEMA_CMD__VMID_MASK 0xf00
+#define ACP_SEMA_CMD__VMID__SHIFT 0x8
+#define ACP_SEMA_CMD__ATC_MASK 0x1000
+#define ACP_SEMA_CMD__ATC__SHIFT 0xc
+#define ACP_SEMA_STS__REQ_STS_MASK 0x3
+#define ACP_SEMA_STS__REQ_STS__SHIFT 0x0
+#define ACP_SEMA_STS__REQ_RESP_AVAIL_MASK 0x100
+#define ACP_SEMA_STS__REQ_RESP_AVAIL__SHIFT 0x8
+#define ACP_SEMA_REQ__ISSUE_POLL_REQ_MASK 0x1
+#define ACP_SEMA_REQ__ISSUE_POLL_REQ__SHIFT 0x0
+#define ACP_FW_STATUS__RUN_MASK 0x1
+#define ACP_FW_STATUS__RUN__SHIFT 0x0
+#define ACP_FUTURE_REG_ACLK_0__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_ACLK_0__ACPFutureReg__SHIFT 0x0
+#define ACP_FUTURE_REG_ACLK_1__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_ACLK_1__ACPFutureReg__SHIFT 0x0
+#define ACP_FUTURE_REG_ACLK_2__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_ACLK_2__ACPFutureReg__SHIFT 0x0
+#define ACP_FUTURE_REG_ACLK_3__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_ACLK_3__ACPFutureReg__SHIFT 0x0
+#define ACP_FUTURE_REG_ACLK_4__ACPFutureReg_MASK 0xffffffff
+#define ACP_FUTURE_REG_ACLK_4__ACPFutureReg__SHIFT 0x0
+#define ACP_TIMER__ACP_Timer_count_MASK 0xffffffff
+#define ACP_TIMER__ACP_Timer_count__SHIFT 0x0
+#define ACP_TIMER_CNTL__ACP_Timer_control_MASK 0x1
+#define ACP_TIMER_CNTL__ACP_Timer_control__SHIFT 0x0
+#define ACP_DSP0_TIMER__ACP_DSP0_timer_MASK 0xffffff
+#define ACP_DSP0_TIMER__ACP_DSP0_timer__SHIFT 0x0
+#define ACP_DSP1_TIMER__ACP_DSP1_timer_MASK 0xffffff
+#define ACP_DSP1_TIMER__ACP_DSP1_timer__SHIFT 0x0
+#define ACP_DSP2_TIMER__ACP_DSP2_timer_MASK 0xffffff
+#define ACP_DSP2_TIMER__ACP_DSP2_timer__SHIFT 0x0
+#define ACP_I2S_TRANSMIT_BYTE_CNT_HIGH__i2s_sp_tx_byte_cnt_high_MASK 0xffffffff
+#define ACP_I2S_TRANSMIT_BYTE_CNT_HIGH__i2s_sp_tx_byte_cnt_high__SHIFT 0x0
+#define ACP_I2S_TRANSMIT_BYTE_CNT_LOW__i2s_sp_tx_byte_cnt_low_MASK 0xffffffff
+#define ACP_I2S_TRANSMIT_BYTE_CNT_LOW__i2s_sp_tx_byte_cnt_low__SHIFT 0x0
+#define ACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH__i2s_bt_tx_byte_cnt_high_MASK 0xffffffff
+#define ACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH__i2s_bt_tx_byte_cnt_high__SHIFT 0x0
+#define ACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW__i2s_bt_tx_byte_cnt_low_MASK 0xffffffff
+#define ACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW__i2s_bt_tx_byte_cnt_low__SHIFT 0x0
+#define ACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH__i2s_bt_rx_byte_cnt_high_MASK 0xffffffff
+#define ACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH__i2s_bt_rx_byte_cnt_high__SHIFT 0x0
+#define ACP_I2S_BT_RECEIVE_BYTE_CNT_LOW__i2s_bt_rx_byte_cnt_low_MASK 0xffffffff
+#define ACP_I2S_BT_RECEIVE_BYTE_CNT_LOW__i2s_bt_rx_byte_cnt_low__SHIFT 0x0
+#define ACP_DSP0_CS_STATE__DSP0_CS_state_MASK 0x1
+#define ACP_DSP0_CS_STATE__DSP0_CS_state__SHIFT 0x0
+#define ACP_DSP1_CS_STATE__DSP1_CS_state_MASK 0x1
+#define ACP_DSP1_CS_STATE__DSP1_CS_state__SHIFT 0x0
+#define ACP_DSP2_CS_STATE__DSP2_CS_state_MASK 0x1
+#define ACP_DSP2_CS_STATE__DSP2_CS_state__SHIFT 0x0
+#define ACP_SCRATCH_REG_BASE_ADDR__SCRATCH_REG_BASE_ADDR_MASK 0x7ffff
+#define ACP_SCRATCH_REG_BASE_ADDR__SCRATCH_REG_BASE_ADDR__SHIFT 0x0
+#define CC_ACP_EFUSE__DSP0_DISABLE_MASK 0x2
+#define CC_ACP_EFUSE__DSP0_DISABLE__SHIFT 0x1
+#define CC_ACP_EFUSE__DSP1_DISABLE_MASK 0x4
+#define CC_ACP_EFUSE__DSP1_DISABLE__SHIFT 0x2
+#define CC_ACP_EFUSE__DSP2_DISABLE_MASK 0x8
+#define CC_ACP_EFUSE__DSP2_DISABLE__SHIFT 0x3
+#define CC_ACP_EFUSE__ACP_DISABLE_MASK 0x10
+#define CC_ACP_EFUSE__ACP_DISABLE__SHIFT 0x4
+#define ACP_PGFSM_RETAIN_REG__ACP_P1_ON_OFF_MASK 0x1
+#define ACP_PGFSM_RETAIN_REG__ACP_P1_ON_OFF__SHIFT 0x0
+#define ACP_PGFSM_RETAIN_REG__ACP_P2_ON_OFF_MASK 0x2
+#define ACP_PGFSM_RETAIN_REG__ACP_P2_ON_OFF__SHIFT 0x1
+#define ACP_PGFSM_RETAIN_REG__ACP_DSP0_ON_OFF_MASK 0x4
+#define ACP_PGFSM_RETAIN_REG__ACP_DSP0_ON_OFF__SHIFT 0x2
+#define ACP_PGFSM_RETAIN_REG__ACP_DSP1_ON_OFF_MASK 0x8
+#define ACP_PGFSM_RETAIN_REG__ACP_DSP1_ON_OFF__SHIFT 0x3
+#define ACP_PGFSM_RETAIN_REG__ACP_DSP2_ON_OFF_MASK 0x10
+#define ACP_PGFSM_RETAIN_REG__ACP_DSP2_ON_OFF__SHIFT 0x4
+#define ACP_PGFSM_RETAIN_REG__ACP_AZ_ON_OFF_MASK 0x20
+#define ACP_PGFSM_RETAIN_REG__ACP_AZ_ON_OFF__SHIFT 0x5
+#define ACP_PGFSM_CONFIG_REG__FSM_ADDR_MASK 0xff
+#define ACP_PGFSM_CONFIG_REG__FSM_ADDR__SHIFT 0x0
+#define ACP_PGFSM_CONFIG_REG__Power_Down_MASK 0x100
+#define ACP_PGFSM_CONFIG_REG__Power_Down__SHIFT 0x8
+#define ACP_PGFSM_CONFIG_REG__Power_Up_MASK 0x200
+#define ACP_PGFSM_CONFIG_REG__Power_Up__SHIFT 0x9
+#define ACP_PGFSM_CONFIG_REG__P1_Select_MASK 0x400
+#define ACP_PGFSM_CONFIG_REG__P1_Select__SHIFT 0xa
+#define ACP_PGFSM_CONFIG_REG__P2_Select_MASK 0x800
+#define ACP_PGFSM_CONFIG_REG__P2_Select__SHIFT 0xb
+#define ACP_PGFSM_CONFIG_REG__Wr_MASK 0x1000
+#define ACP_PGFSM_CONFIG_REG__Wr__SHIFT 0xc
+#define ACP_PGFSM_CONFIG_REG__Rd_MASK 0x2000
+#define ACP_PGFSM_CONFIG_REG__Rd__SHIFT 0xd
+#define ACP_PGFSM_CONFIG_REG__RdData_Reset_MASK 0x4000
+#define ACP_PGFSM_CONFIG_REG__RdData_Reset__SHIFT 0xe
+#define ACP_PGFSM_CONFIG_REG__Short_Format_MASK 0x8000
+#define ACP_PGFSM_CONFIG_REG__Short_Format__SHIFT 0xf
+#define ACP_PGFSM_CONFIG_REG__BPM_CG_MG_FGCG_MASK 0x3ff0000
+#define ACP_PGFSM_CONFIG_REG__BPM_CG_MG_FGCG__SHIFT 0x10
+#define ACP_PGFSM_CONFIG_REG__SRBM_override_MASK 0x4000000
+#define ACP_PGFSM_CONFIG_REG__SRBM_override__SHIFT 0x1a
+#define ACP_PGFSM_CONFIG_REG__Rsvd_BPM_Addr_MASK 0x8000000
+#define ACP_PGFSM_CONFIG_REG__Rsvd_BPM_Addr__SHIFT 0x1b
+#define ACP_PGFSM_CONFIG_REG__REG_ADDR_MASK 0xf0000000
+#define ACP_PGFSM_CONFIG_REG__REG_ADDR__SHIFT 0x1c
+#define ACP_PGFSM_WRITE_REG__Write_value_MASK 0xffffffff
+#define ACP_PGFSM_WRITE_REG__Write_value__SHIFT 0x0
+#define ACP_PGFSM_READ_REG_0__Read_value_MASK 0xffffff
+#define ACP_PGFSM_READ_REG_0__Read_value__SHIFT 0x0
+#define ACP_PGFSM_READ_REG_1__Read_value_MASK 0xffffff
+#define ACP_PGFSM_READ_REG_1__Read_value__SHIFT 0x0
+#define ACP_PGFSM_READ_REG_2__Read_value_MASK 0xffffff
+#define ACP_PGFSM_READ_REG_2__Read_value__SHIFT 0x0
+#define ACP_PGFSM_READ_REG_3__Read_value_MASK 0xffffff
+#define ACP_PGFSM_READ_REG_3__Read_value__SHIFT 0x0
+#define ACP_PGFSM_READ_REG_4__Read_value_MASK 0xffffff
+#define ACP_PGFSM_READ_REG_4__Read_value__SHIFT 0x0
+#define ACP_PGFSM_READ_REG_5__Read_value_MASK 0xffffff
+#define ACP_PGFSM_READ_REG_5__Read_value__SHIFT 0x0
+#define ACP_IP_PGFSM_ENABLE__ACP_IP_ACCESS_MASK 0x1
+#define ACP_IP_PGFSM_ENABLE__ACP_IP_ACCESS__SHIFT 0x0
+#define ACP_I2S_PIN_CONFIG__ACP_I2S_PIN_CONFIG_MASK 0x3
+#define ACP_I2S_PIN_CONFIG__ACP_I2S_PIN_CONFIG__SHIFT 0x0
+#define ACP_AZALIA_I2S_SELECT__AZ_I2S_SELECT_MASK 0x1
+#define ACP_AZALIA_I2S_SELECT__AZ_I2S_SELECT__SHIFT 0x0
+#define ACP_CHIP_PKG_FOR_PAD_ISOLATION__external_fch_package_MASK 0x1
+#define ACP_CHIP_PKG_FOR_PAD_ISOLATION__external_fch_package__SHIFT 0x0
+#define ACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL__ACP_AUDIO_PAD_pullup_disable_MASK 0x7ff
+#define ACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL__ACP_AUDIO_PAD_pullup_disable__SHIFT 0x0
+#define ACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL__ACP_AUDIO_PAD_pulldown_enable_MASK 0x7ff0000
+#define ACP_AUDIO_PAD_PULLUP_PULLDOWN_CTRL__ACP_AUDIO_PAD_pulldown_enable__SHIFT 0x10
+#define ACP_BT_UART_PAD_SEL__ACP_BT_UART_PAD_SEL_MASK 0x1
+#define ACP_BT_UART_PAD_SEL__ACP_BT_UART_PAD_SEL__SHIFT 0x0
+#define ACP_SCRATCH_REG_0__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_0__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_1__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_1__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_2__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_2__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_3__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_3__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_4__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_4__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_5__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_5__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_6__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_6__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_7__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_7__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_8__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_8__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_9__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_9__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_10__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_10__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_11__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_11__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_12__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_12__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_13__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_13__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_14__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_14__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_15__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_15__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_16__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_16__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_17__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_17__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_18__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_18__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_19__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_19__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_20__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_20__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_21__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_21__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_22__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_22__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_23__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_23__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_24__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_24__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_25__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_25__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_26__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_26__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_27__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_27__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_28__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_28__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_29__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_29__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_30__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_30__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_31__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_31__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_32__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_32__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_33__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_33__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_34__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_34__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_35__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_35__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_36__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_36__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_37__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_37__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_38__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_38__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_39__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_39__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_40__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_40__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_41__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_41__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_42__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_42__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_43__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_43__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_44__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_44__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_45__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_45__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_46__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_46__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_SCRATCH_REG_47__ACP_SCRATCH_REG_MASK 0xffffffff
+#define ACP_SCRATCH_REG_47__ACP_SCRATCH_REG__SHIFT 0x0
+#define ACP_VOICE_WAKEUP_ENABLE__voice_wakeup_enable_MASK 0x1
+#define ACP_VOICE_WAKEUP_ENABLE__voice_wakeup_enable__SHIFT 0x0
+#define ACP_VOICE_WAKEUP_STATUS__voice_wakeup_status_MASK 0x1
+#define ACP_VOICE_WAKEUP_STATUS__voice_wakeup_status__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_LOWER_THRESHOLD__i2s_voice_wakeup_lower_threshold_MASK 0xffffffff
+#define I2S_VOICE_WAKEUP_LOWER_THRESHOLD__i2s_voice_wakeup_lower_threshold__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_HIGHER_THRESHOLD__i2s_voice_wakeup_higher_threshold_MASK 0xffffffff
+#define I2S_VOICE_WAKEUP_HIGHER_THRESHOLD__i2s_voice_wakeup_higher_threshold__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_NO_OF_SAMPLES__i2s_voice_wakeup_no_of_samples_MASK 0xffff
+#define I2S_VOICE_WAKEUP_NO_OF_SAMPLES__i2s_voice_wakeup_no_of_samples__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_NO_OF_PEAKS__i2s_voice_wakeup_no_of_peaks_MASK 0xffff
+#define I2S_VOICE_WAKEUP_NO_OF_PEAKS__i2s_voice_wakeup_no_of_peaks__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_DURATION_OF_N_PEAKS__i2s_voice_wakeup_duration_of_n_peaks_MASK 0xffffffff
+#define I2S_VOICE_WAKEUP_DURATION_OF_N_PEAKS__i2s_voice_wakeup_duration_of_n_peaks__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_BITCLK_TOGGLE_DETECTION__i2s_voice_wakeup_bitclk_toggle_wakeup_en_MASK 0x1
+#define I2S_VOICE_WAKEUP_BITCLK_TOGGLE_DETECTION__i2s_voice_wakeup_bitclk_toggle_wakeup_en__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_DATA_PATH_SWITCH__i2s_voice_wakeup_data_path_switch_req_MASK 0x1
+#define I2S_VOICE_WAKEUP_DATA_PATH_SWITCH__i2s_voice_wakeup_data_path_switch_req__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_DATA_PATH_SWITCH__i2s_voice_wakeup_data_path_switch_ack_MASK 0x2
+#define I2S_VOICE_WAKEUP_DATA_PATH_SWITCH__i2s_voice_wakeup_data_path_switch_ack__SHIFT 0x1
+#define I2S_VOICE_WAKEUP_DATA_POINTER__i2s_voice_wakeup_data_pointer_MASK 0xffffffff
+#define I2S_VOICE_WAKEUP_DATA_POINTER__i2s_voice_wakeup_data_pointer__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_AUTH_MATCH__i2s_voice_wakeup_authentication_valid_MASK 0x1
+#define I2S_VOICE_WAKEUP_AUTH_MATCH__i2s_voice_wakeup_authentication_valid__SHIFT 0x0
+#define I2S_VOICE_WAKEUP_AUTH_MATCH__i2s_voice_wakeup_authentication_match_MASK 0x2
+#define I2S_VOICE_WAKEUP_AUTH_MATCH__i2s_voice_wakeup_authentication_match__SHIFT 0x1
+#define I2S_VOICE_WAKEUP_8KB_WRAP__i2s_voice_wakeup_8kb_wrap_MASK 0x1
+#define I2S_VOICE_WAKEUP_8KB_WRAP__i2s_voice_wakeup_8kb_wrap__SHIFT 0x0
+#define ACP_I2S_RECEIVED_BYTE_CNT_HIGH__i2s_mic_rx_byte_cnt_high_MASK 0xffffffff
+#define ACP_I2S_RECEIVED_BYTE_CNT_HIGH__i2s_mic_rx_byte_cnt_high__SHIFT 0x0
+#define ACP_I2S_RECEIVED_BYTE_CNT_LOW__i2s_mic_rx_byte_cnt_low_MASK 0xffffffff
+#define ACP_I2S_RECEIVED_BYTE_CNT_LOW__i2s_mic_rx_byte_cnt_low__SHIFT 0x0
+#define ACP_I2S_MICSP_TRANSMIT_BYTE_CNT_HIGH__i2s_micsp_tx_byte_cnt_high_MASK 0xffffffff
+#define ACP_I2S_MICSP_TRANSMIT_BYTE_CNT_HIGH__i2s_micsp_tx_byte_cnt_high__SHIFT 0x0
+#define ACP_I2S_MICSP_TRANSMIT_BYTE_CNT_LOW__i2s_micsp_tx_byte_cnt_low_MASK 0xffffffff
+#define ACP_I2S_MICSP_TRANSMIT_BYTE_CNT_LOW__i2s_micsp_tx_byte_cnt_low__SHIFT 0x0
+#define ACP_MEM_SHUT_DOWN_REQ_LO__ACP_ShutDownReq_RAML_MASK 0xffffffff
+#define ACP_MEM_SHUT_DOWN_REQ_LO__ACP_ShutDownReq_RAML__SHIFT 0x0
+#define ACP_MEM_SHUT_DOWN_REQ_HI__ACP_ShutDownReq_RAMH_MASK 0xffff
+#define ACP_MEM_SHUT_DOWN_REQ_HI__ACP_ShutDownReq_RAMH__SHIFT 0x0
+#define ACP_MEM_SHUT_DOWN_STS_LO__ACP_ShutDownSts_RAML_MASK 0xffffffff
+#define ACP_MEM_SHUT_DOWN_STS_LO__ACP_ShutDownSts_RAML__SHIFT 0x0
+#define ACP_MEM_SHUT_DOWN_STS_HI__ACP_ShutDownSts_RAMH_MASK 0xffff
+#define ACP_MEM_SHUT_DOWN_STS_HI__ACP_ShutDownSts_RAMH__SHIFT 0x0
+#define ACP_MEM_DEEP_SLEEP_REQ_LO__ACP_DeepSleepReq_RAML_MASK 0xffffffff
+#define ACP_MEM_DEEP_SLEEP_REQ_LO__ACP_DeepSleepReq_RAML__SHIFT 0x0
+#define ACP_MEM_DEEP_SLEEP_REQ_HI__ACP_DeepSleepReq_RAMH_MASK 0xffff
+#define ACP_MEM_DEEP_SLEEP_REQ_HI__ACP_DeepSleepReq_RAMH__SHIFT 0x0
+#define ACP_MEM_DEEP_SLEEP_STS_LO__ACP_DeepSleepSts_RAML_MASK 0xffffffff
+#define ACP_MEM_DEEP_SLEEP_STS_LO__ACP_DeepSleepSts_RAML__SHIFT 0x0
+#define ACP_MEM_DEEP_SLEEP_STS_HI__ACP_DeepSleepSts_RAMH_MASK 0xffff
+#define ACP_MEM_DEEP_SLEEP_STS_HI__ACP_DeepSleepSts_RAMH__SHIFT 0x0
+#define ACP_MEM_WAKEUP_FROM_SHUT_DOWN_LO__acp_mem_wakeup_from_shut_down_lo_MASK 0xffffffff
+#define ACP_MEM_WAKEUP_FROM_SHUT_DOWN_LO__acp_mem_wakeup_from_shut_down_lo__SHIFT 0x0
+#define ACP_MEM_WAKEUP_FROM_SHUT_DOWN_HI__acp_mem_wakeup_from_shut_down_hi_MASK 0xffff
+#define ACP_MEM_WAKEUP_FROM_SHUT_DOWN_HI__acp_mem_wakeup_from_shut_down_hi__SHIFT 0x0
+#define ACP_MEM_WAKEUP_FROM_SLEEP_LO__acp_mem_wakeup_from_sleep_lo_MASK 0xffffffff
+#define ACP_MEM_WAKEUP_FROM_SLEEP_LO__acp_mem_wakeup_from_sleep_lo__SHIFT 0x0
+#define ACP_MEM_WAKEUP_FROM_SLEEP_HI__acp_mem_wakeup_from_sleep_hi_MASK 0xffff
+#define ACP_MEM_WAKEUP_FROM_SLEEP_HI__acp_mem_wakeup_from_sleep_hi__SHIFT 0x0
+#define ACP_I2SSP_IER__I2SSP_IEN_MASK 0x1
+#define ACP_I2SSP_IER__I2SSP_IEN__SHIFT 0x0
+#define ACP_I2SSP_IRER__I2SSP_RXEN_MASK 0x1
+#define ACP_I2SSP_IRER__I2SSP_RXEN__SHIFT 0x0
+#define ACP_I2SSP_ITER__I2SSP_TXEN_MASK 0x1
+#define ACP_I2SSP_ITER__I2SSP_TXEN__SHIFT 0x0
+#define ACP_I2SSP_CER__I2SSP_CLKEN_MASK 0x1
+#define ACP_I2SSP_CER__I2SSP_CLKEN__SHIFT 0x0
+#define ACP_I2SSP_CCR__I2SSP_SCLKG_MASK 0x7
+#define ACP_I2SSP_CCR__I2SSP_SCLKG__SHIFT 0x0
+#define ACP_I2SSP_CCR__I2SSP_WSS_MASK 0x18
+#define ACP_I2SSP_CCR__I2SSP_WSS__SHIFT 0x3
+#define ACP_I2SSP_RXFFR__I2SSP_RXFFR_MASK 0x1
+#define ACP_I2SSP_RXFFR__I2SSP_RXFFR__SHIFT 0x0
+#define ACP_I2SSP_TXFFR__I2SSP_TXFFR_MASK 0x1
+#define ACP_I2SSP_TXFFR__I2SSP_TXFFR__SHIFT 0x0
+#define ACP_I2SSP_LRBR0__I2SSP_LRBR0_MASK 0xffffffff
+#define ACP_I2SSP_LRBR0__I2SSP_LRBR0__SHIFT 0x0
+#define ACP_I2SSP_RRBR0__I2SSP_RRBR0_MASK 0xffffffff
+#define ACP_I2SSP_RRBR0__I2SSP_RRBR0__SHIFT 0x0
+#define ACP_I2SSP_RER0__I2SSP_RXCHEN0_MASK 0x1
+#define ACP_I2SSP_RER0__I2SSP_RXCHEN0__SHIFT 0x0
+#define ACP_I2SSP_TER0__I2SSP_TXCHEN0_MASK 0x1
+#define ACP_I2SSP_TER0__I2SSP_TXCHEN0__SHIFT 0x0
+#define ACP_I2SSP_RCR0__I2SSP_WLEN_MASK 0x7
+#define ACP_I2SSP_RCR0__I2SSP_WLEN__SHIFT 0x0
+#define ACP_I2SSP_TCR0__I2SSP_WLEN_MASK 0x7
+#define ACP_I2SSP_TCR0__I2SSP_WLEN__SHIFT 0x0
+#define ACP_I2SSP_ISR0__I2SSP_RXDA_MASK 0x1
+#define ACP_I2SSP_ISR0__I2SSP_RXDA__SHIFT 0x0
+#define ACP_I2SSP_ISR0__I2SSP_RXFO_MASK 0x2
+#define ACP_I2SSP_ISR0__I2SSP_RXFO__SHIFT 0x1
+#define ACP_I2SSP_ISR0__I2SSP_TXFE_MASK 0x10
+#define ACP_I2SSP_ISR0__I2SSP_TXFE__SHIFT 0x4
+#define ACP_I2SSP_ISR0__I2SSP_TXFO_MASK 0x20
+#define ACP_I2SSP_ISR0__I2SSP_TXFO__SHIFT 0x5
+#define ACP_I2SSP_IMR0__I2SSP_RXDAM_MASK 0x1
+#define ACP_I2SSP_IMR0__I2SSP_RXDAM__SHIFT 0x0
+#define ACP_I2SSP_IMR0__I2SSP_RXFOM_MASK 0x2
+#define ACP_I2SSP_IMR0__I2SSP_RXFOM__SHIFT 0x1
+#define ACP_I2SSP_IMR0__I2SSP_TXFEM_MASK 0x10
+#define ACP_I2SSP_IMR0__I2SSP_TXFEM__SHIFT 0x4
+#define ACP_I2SSP_IMR0__I2SSP_TXFOM_MASK 0x20
+#define ACP_I2SSP_IMR0__I2SSP_TXFOM__SHIFT 0x5
+#define ACP_I2SSP_ROR0__I2SSP_RXCHO_MASK 0x1
+#define ACP_I2SSP_ROR0__I2SSP_RXCHO__SHIFT 0x0
+#define ACP_I2SSP_TOR0__I2SSP_TXCHO_MASK 0x1
+#define ACP_I2SSP_TOR0__I2SSP_TXCHO__SHIFT 0x0
+#define ACP_I2SSP_RFCR0__I2SSP_RXCHDT_MASK 0xf
+#define ACP_I2SSP_RFCR0__I2SSP_RXCHDT__SHIFT 0x0
+#define ACP_I2SSP_TFCR0__I2SSP_TXCHET_MASK 0xf
+#define ACP_I2SSP_TFCR0__I2SSP_TXCHET__SHIFT 0x0
+#define ACP_I2SSP_RFF0__I2SSP_RXCHFR_MASK 0x1
+#define ACP_I2SSP_RFF0__I2SSP_RXCHFR__SHIFT 0x0
+#define ACP_I2SSP_TFF0__I2SSP_TXCHFR_MASK 0x1
+#define ACP_I2SSP_TFF0__I2SSP_TXCHFR__SHIFT 0x0
+#define ACP_I2SSP_RXDMA__I2SSP_RXDMA_MASK 0xffffffff
+#define ACP_I2SSP_RXDMA__I2SSP_RXDMA__SHIFT 0x0
+#define ACP_I2SSP_RRXDMA__I2SSP_RRXDMA_MASK 0x1
+#define ACP_I2SSP_RRXDMA__I2SSP_RRXDMA__SHIFT 0x0
+#define ACP_I2SSP_TXDMA__I2SSP_TXDMA_MASK 0xffffffff
+#define ACP_I2SSP_TXDMA__I2SSP_TXDMA__SHIFT 0x0
+#define ACP_I2SSP_RTXDMA__I2SSP_RTXDMA_MASK 0x1
+#define ACP_I2SSP_RTXDMA__I2SSP_RTXDMA__SHIFT 0x0
+#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_0_MASK 0x7
+#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_0__SHIFT 0x0
+#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_1_MASK 0x38
+#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_1__SHIFT 0x3
+#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_2_MASK 0x380
+#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_2__SHIFT 0x7
+#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_3_MASK 0x1c00
+#define ACP_I2SSP_COMP_PARAM_2__I2SSP_RX_WPRDSIZE_3__SHIFT 0xa
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_APB_DATA_WIDTH_MASK 0x3
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_APB_DATA_WIDTH__SHIFT 0x0
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_FIFO_DEPTH_GLOBAL_MASK 0xc
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_FIFO_DEPTH_GLOBAL__SHIFT 0x2
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_MODE_EN_MASK 0x10
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_MODE_EN__SHIFT 0x4
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TRANSMITTER_BLOCK_MASK 0x20
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TRANSMITTER_BLOCK__SHIFT 0x5
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_RECEIVER_BLOCK_MASK 0x40
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_RECEIVER_BLOCK__SHIFT 0x6
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_RX_CHANNLES_MASK 0x180
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_RX_CHANNLES__SHIFT 0x7
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_CHANNLES_MASK 0x600
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_CHANNLES__SHIFT 0x9
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_0_MASK 0x70000
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_0__SHIFT 0x10
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_1_MASK 0x380000
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_1__SHIFT 0x13
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_2_MASK 0x1c00000
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_2__SHIFT 0x16
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_3_MASK 0xe000000
+#define ACP_I2SSP_COMP_PARAM_1__I2SSP_TX_WORDSIZE_3__SHIFT 0x19
+#define ACP_I2SSP_COMP_VERSION__I2SSP_APB_DATA_WIDTH_MASK 0xffffffff
+#define ACP_I2SSP_COMP_VERSION__I2SSP_APB_DATA_WIDTH__SHIFT 0x0
+#define ACP_I2SSP_COMP_TYPE__I2SSP_COMP_TYPE_MASK 0xffffffff
+#define ACP_I2SSP_COMP_TYPE__I2SSP_COMP_TYPE__SHIFT 0x0
+#define ACP_I2SMICSP_IER__I2SMICSP_IEN_MASK 0x1
+#define ACP_I2SMICSP_IER__I2SMICSP_IEN__SHIFT 0x0
+#define ACP_I2SMICSP_IRER__I2SMICSP_RXEN_MASK 0x1
+#define ACP_I2SMICSP_IRER__I2SMICSP_RXEN__SHIFT 0x0
+#define ACP_I2SMICSP_ITER__I2SMICSP_TXEN_MASK 0x1
+#define ACP_I2SMICSP_ITER__I2SMICSP_TXEN__SHIFT 0x0
+#define ACP_I2SMICSP_CER__I2SMICSP_CLKEN_MASK 0x1
+#define ACP_I2SMICSP_CER__I2SMICSP_CLKEN__SHIFT 0x0
+#define ACP_I2SMICSP_CCR__I2SMICSP_SCLKG_MASK 0x7
+#define ACP_I2SMICSP_CCR__I2SMICSP_SCLKG__SHIFT 0x0
+#define ACP_I2SMICSP_CCR__I2SMICSP_WSS_MASK 0x18
+#define ACP_I2SMICSP_CCR__I2SMICSP_WSS__SHIFT 0x3
+#define ACP_I2SMICSP_RXFFR__I2SMICSP_RXFFR_MASK 0x1
+#define ACP_I2SMICSP_RXFFR__I2SMICSP_RXFFR__SHIFT 0x0
+#define ACP_I2SMICSP_TXFFR__I2SMICSP_TXFFR_MASK 0x1
+#define ACP_I2SMICSP_TXFFR__I2SMICSP_TXFFR__SHIFT 0x0
+#define ACP_I2SMICSP_LRBR0__I2SMICSP_LRBR0_MASK 0xffffffff
+#define ACP_I2SMICSP_LRBR0__I2SMICSP_LRBR0__SHIFT 0x0
+#define ACP_I2SMICSP_RRBR0__I2SMICSP_RRBR0_MASK 0xffffffff
+#define ACP_I2SMICSP_RRBR0__I2SMICSP_RRBR0__SHIFT 0x0
+#define ACP_I2SMICSP_RER0__I2SMICSP_RXCHEN0_MASK 0x1
+#define ACP_I2SMICSP_RER0__I2SMICSP_RXCHEN0__SHIFT 0x0
+#define ACP_I2SMICSP_TER0__I2SMICSP_TXCHEN0_MASK 0x1
+#define ACP_I2SMICSP_TER0__I2SMICSP_TXCHEN0__SHIFT 0x0
+#define ACP_I2SMICSP_RCR0__I2SMICSP_WLEN_MASK 0x7
+#define ACP_I2SMICSP_RCR0__I2SMICSP_WLEN__SHIFT 0x0
+#define ACP_I2SMICSP_TCR0__I2SMICSP_WLEN_MASK 0x7
+#define ACP_I2SMICSP_TCR0__I2SMICSP_WLEN__SHIFT 0x0
+#define ACP_I2SMICSP_ISR0__I2SMICSP_RXDA_MASK 0x1
+#define ACP_I2SMICSP_ISR0__I2SMICSP_RXDA__SHIFT 0x0
+#define ACP_I2SMICSP_ISR0__I2SMICSP_RXFO_MASK 0x2
+#define ACP_I2SMICSP_ISR0__I2SMICSP_RXFO__SHIFT 0x1
+#define ACP_I2SMICSP_ISR0__I2SMICSP_TXFE_MASK 0x10
+#define ACP_I2SMICSP_ISR0__I2SMICSP_TXFE__SHIFT 0x4
+#define ACP_I2SMICSP_ISR0__I2SMICSP_TXFO_MASK 0x20
+#define ACP_I2SMICSP_ISR0__I2SMICSP_TXFO__SHIFT 0x5
+#define ACP_I2SMICSP_IMR0__I2SMICSP_RXDAM_MASK 0x1
+#define ACP_I2SMICSP_IMR0__I2SMICSP_RXDAM__SHIFT 0x0
+#define ACP_I2SMICSP_IMR0__I2SMICSP_RXFOM_MASK 0x2
+#define ACP_I2SMICSP_IMR0__I2SMICSP_RXFOM__SHIFT 0x1
+#define ACP_I2SMICSP_IMR0__I2SMICSP_TXFEM_MASK 0x10
+#define ACP_I2SMICSP_IMR0__I2SMICSP_TXFEM__SHIFT 0x4
+#define ACP_I2SMICSP_IMR0__I2SMICSP_TXFOM_MASK 0x20
+#define ACP_I2SMICSP_IMR0__I2SMICSP_TXFOM__SHIFT 0x5
+#define ACP_I2SMICSP_ROR0__I2SMICSP_RXCHO_MASK 0x1
+#define ACP_I2SMICSP_ROR0__I2SMICSP_RXCHO__SHIFT 0x0
+#define ACP_I2SMICSP_TOR0__I2SMICSP_TXCHO_MASK 0x1
+#define ACP_I2SMICSP_TOR0__I2SMICSP_TXCHO__SHIFT 0x0
+#define ACP_I2SMICSP_RFCR0__I2SMICSP_RXCHDT_MASK 0xf
+#define ACP_I2SMICSP_RFCR0__I2SMICSP_RXCHDT__SHIFT 0x0
+#define ACP_I2SMICSP_TFCR0__I2SMICSP_TXCHET_MASK 0xf
+#define ACP_I2SMICSP_TFCR0__I2SMICSP_TXCHET__SHIFT 0x0
+#define ACP_I2SMICSP_RFF0__I2SMICSP_RXCHFR_MASK 0x1
+#define ACP_I2SMICSP_RFF0__I2SMICSP_RXCHFR__SHIFT 0x0
+#define ACP_I2SMICSP_TFF0__I2SMICSP_TXCHFR_MASK 0x1
+#define ACP_I2SMICSP_TFF0__I2SMICSP_TXCHFR__SHIFT 0x0
+#define ACP_I2SMICSP_LRBR1__I2SMICSP_LRBR1_MASK 0xffffffff
+#define ACP_I2SMICSP_LRBR1__I2SMICSP_LRBR1__SHIFT 0x0
+#define ACP_I2SMICSP_RRBR1__I2SMICSP_RRBR1_MASK 0xffffffff
+#define ACP_I2SMICSP_RRBR1__I2SMICSP_RRBR1__SHIFT 0x0
+#define ACP_I2SMICSP_RER1__I2SMICSP_RXCHEN1_MASK 0x1
+#define ACP_I2SMICSP_RER1__I2SMICSP_RXCHEN1__SHIFT 0x0
+#define ACP_I2SMICSP_TER1__I2SMICSP_TXCHEN1_MASK 0x1
+#define ACP_I2SMICSP_TER1__I2SMICSP_TXCHEN1__SHIFT 0x0
+#define ACP_I2SMICSP_RCR1__I2SMICSP_WLEN_MASK 0x7
+#define ACP_I2SMICSP_RCR1__I2SMICSP_WLEN__SHIFT 0x0
+#define ACP_I2SMICSP_TCR1__I2SMICSP_WLEN_MASK 0x7
+#define ACP_I2SMICSP_TCR1__I2SMICSP_WLEN__SHIFT 0x0
+#define ACP_I2SMICSP_ISR1__I2SMICSP_RXDA_MASK 0x1
+#define ACP_I2SMICSP_ISR1__I2SMICSP_RXDA__SHIFT 0x0
+#define ACP_I2SMICSP_ISR1__I2SMICSP_RXFO_MASK 0x2
+#define ACP_I2SMICSP_ISR1__I2SMICSP_RXFO__SHIFT 0x1
+#define ACP_I2SMICSP_ISR1__I2SMICSP_TXFE_MASK 0x10
+#define ACP_I2SMICSP_ISR1__I2SMICSP_TXFE__SHIFT 0x4
+#define ACP_I2SMICSP_ISR1__I2SMICSP_TXFO_MASK 0x20
+#define ACP_I2SMICSP_ISR1__I2SMICSP_TXFO__SHIFT 0x5
+#define ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK 0x1
+#define ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM__SHIFT 0x0
+#define ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK 0x2
+#define ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM__SHIFT 0x1
+#define ACP_I2SMICSP_IMR1__I2SMICSP_TXFEM_MASK 0x10
+#define ACP_I2SMICSP_IMR1__I2SMICSP_TXFEM__SHIFT 0x4
+#define ACP_I2SMICSP_IMR1__I2SMICSP_TXFOM_MASK 0x20
+#define ACP_I2SMICSP_IMR1__I2SMICSP_TXFOM__SHIFT 0x5
+#define ACP_I2SMICSP_ROR1__I2SMICSP_RXCHO_MASK 0x1
+#define ACP_I2SMICSP_ROR1__I2SMICSP_RXCHO__SHIFT 0x0
+#define ACP_I2SMICSP_TOR1__I2SMICSP_TXCHO_MASK 0x1
+#define ACP_I2SMICSP_TOR1__I2SMICSP_TXCHO__SHIFT 0x0
+#define ACP_I2SMICSP_RFCR1__I2SMICSP_RXCHDT_MASK 0xf
+#define ACP_I2SMICSP_RFCR1__I2SMICSP_RXCHDT__SHIFT 0x0
+#define ACP_I2SMICSP_TFCR1__I2SMICSP_TXCHET_MASK 0xf
+#define ACP_I2SMICSP_TFCR1__I2SMICSP_TXCHET__SHIFT 0x0
+#define ACP_I2SMICSP_RFF1__I2SMICSP_RXCHFR_MASK 0x1
+#define ACP_I2SMICSP_RFF1__I2SMICSP_RXCHFR__SHIFT 0x0
+#define ACP_I2SMICSP_TFF1__I2SMICSP_TXCHFR_MASK 0x1
+#define ACP_I2SMICSP_TFF1__I2SMICSP_TXCHFR__SHIFT 0x0
+#define ACP_I2SMICSP_RXDMA__I2SMICSP_RXDMA_MASK 0xffffffff
+#define ACP_I2SMICSP_RXDMA__I2SMICSP_RXDMA__SHIFT 0x0
+#define ACP_I2SMICSP_RRXDMA__I2SMICSP_RRXDMA_MASK 0x1
+#define ACP_I2SMICSP_RRXDMA__I2SMICSP_RRXDMA__SHIFT 0x0
+#define ACP_I2SMICSP_TXDMA__I2SMICSP_TXDMA_MASK 0xffffffff
+#define ACP_I2SMICSP_TXDMA__I2SMICSP_TXDMA__SHIFT 0x0
+#define ACP_I2SMICSP_RTXDMA__I2SMICSP_RTXDMA_MASK 0x1
+#define ACP_I2SMICSP_RTXDMA__I2SMICSP_RTXDMA__SHIFT 0x0
+#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_0_MASK 0x7
+#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_0__SHIFT 0x0
+#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_1_MASK 0x38
+#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_1__SHIFT 0x3
+#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_2_MASK 0x380
+#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_2__SHIFT 0x7
+#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_3_MASK 0x1c00
+#define ACP_I2SMICSP_COMP_PARAM_2__I2SMICSP_RX_WPRDSIZE_3__SHIFT 0xa
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_APB_DATA_WIDTH_MASK 0x3
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_APB_DATA_WIDTH__SHIFT 0x0
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_FIFO_DEPTH_GLOBAL_MASK 0xc
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_FIFO_DEPTH_GLOBAL__SHIFT 0x2
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_MODE_EN_MASK 0x10
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_MODE_EN__SHIFT 0x4
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TRANSMITTER_BLOCK_MASK 0x20
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TRANSMITTER_BLOCK__SHIFT 0x5
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_RECEIVER_BLOCK_MASK 0x40
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_RECEIVER_BLOCK__SHIFT 0x6
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_RX_CHANNLES_MASK 0x180
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_RX_CHANNLES__SHIFT 0x7
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_CHANNLES_MASK 0x600
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_CHANNLES__SHIFT 0x9
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_0_MASK 0x70000
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_0__SHIFT 0x10
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_1_MASK 0x380000
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_1__SHIFT 0x13
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_2_MASK 0x1c00000
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_2__SHIFT 0x16
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_3_MASK 0xe000000
+#define ACP_I2SMICSP_COMP_PARAM_1__I2SMICSP_TX_WORDSIZE_3__SHIFT 0x19
+#define ACP_I2SMICSP_COMP_VERSION__I2SMICSP_APB_DATA_WIDTH_MASK 0xffffffff
+#define ACP_I2SMICSP_COMP_VERSION__I2SMICSP_APB_DATA_WIDTH__SHIFT 0x0
+#define ACP_I2SMICSP_COMP_TYPE__I2SMICSP_COMP_TYPE_MASK 0xffffffff
+#define ACP_I2SMICSP_COMP_TYPE__I2SMICSP_COMP_TYPE__SHIFT 0x0
+#define ACP_I2SBT_IER__I2SBT_IEN_MASK 0x1
+#define ACP_I2SBT_IER__I2SBT_IEN__SHIFT 0x0
+#define ACP_I2SBT_IRER__I2SBT_RXEN_MASK 0x1
+#define ACP_I2SBT_IRER__I2SBT_RXEN__SHIFT 0x0
+#define ACP_I2SBT_ITER__I2SBT_TXEN_MASK 0x1
+#define ACP_I2SBT_ITER__I2SBT_TXEN__SHIFT 0x0
+#define ACP_I2SBT_CER__I2SBT_CLKEN_MASK 0x1
+#define ACP_I2SBT_CER__I2SBT_CLKEN__SHIFT 0x0
+#define ACP_I2SBT_CCR__I2SBT_SCLKG_MASK 0x7
+#define ACP_I2SBT_CCR__I2SBT_SCLKG__SHIFT 0x0
+#define ACP_I2SBT_CCR__I2SBT_WSS_MASK 0x18
+#define ACP_I2SBT_CCR__I2SBT_WSS__SHIFT 0x3
+#define ACP_I2SBT_RXFFR__I2SBT_RXFFR_MASK 0x1
+#define ACP_I2SBT_RXFFR__I2SBT_RXFFR__SHIFT 0x0
+#define ACP_I2SBT_TXFFR__I2SBT_TXFFR_MASK 0x1
+#define ACP_I2SBT_TXFFR__I2SBT_TXFFR__SHIFT 0x0
+#define ACP_I2SBT_LRBR0__I2SBT_LRBR0_MASK 0xffffffff
+#define ACP_I2SBT_LRBR0__I2SBT_LRBR0__SHIFT 0x0
+#define ACP_I2SBT_RRBR0__I2SBT_RRBR0_MASK 0xffffffff
+#define ACP_I2SBT_RRBR0__I2SBT_RRBR0__SHIFT 0x0
+#define ACP_I2SBT_RER0__I2SBT_RXCHEN0_MASK 0x1
+#define ACP_I2SBT_RER0__I2SBT_RXCHEN0__SHIFT 0x0
+#define ACP_I2SBT_TER0__I2SBT_TXCHEN0_MASK 0x1
+#define ACP_I2SBT_TER0__I2SBT_TXCHEN0__SHIFT 0x0
+#define ACP_I2SBT_RCR0__I2SBT_WLEN_MASK 0x7
+#define ACP_I2SBT_RCR0__I2SBT_WLEN__SHIFT 0x0
+#define ACP_I2SBT_TCR0__I2SBT_WLEN_MASK 0x7
+#define ACP_I2SBT_TCR0__I2SBT_WLEN__SHIFT 0x0
+#define ACP_I2SBT_ISR0__I2SBT_RXDA_MASK 0x1
+#define ACP_I2SBT_ISR0__I2SBT_RXDA__SHIFT 0x0
+#define ACP_I2SBT_ISR0__I2SBT_RXFO_MASK 0x2
+#define ACP_I2SBT_ISR0__I2SBT_RXFO__SHIFT 0x1
+#define ACP_I2SBT_ISR0__I2SBT_TXFE_MASK 0x10
+#define ACP_I2SBT_ISR0__I2SBT_TXFE__SHIFT 0x4
+#define ACP_I2SBT_ISR0__I2SBT_TXFO_MASK 0x20
+#define ACP_I2SBT_ISR0__I2SBT_TXFO__SHIFT 0x5
+#define ACP_I2SBT_IMR0__I2SBT_RXDAM_MASK 0x1
+#define ACP_I2SBT_IMR0__I2SBT_RXDAM__SHIFT 0x0
+#define ACP_I2SBT_IMR0__I2SBT_RXFOM_MASK 0x2
+#define ACP_I2SBT_IMR0__I2SBT_RXFOM__SHIFT 0x1
+#define ACP_I2SBT_IMR0__I2SBT_TXFEM_MASK 0x10
+#define ACP_I2SBT_IMR0__I2SBT_TXFEM__SHIFT 0x4
+#define ACP_I2SBT_IMR0__I2SBT_TXFOM_MASK 0x20
+#define ACP_I2SBT_IMR0__I2SBT_TXFOM__SHIFT 0x5
+#define ACP_I2SBT_ROR0__I2SBT_RXCHO_MASK 0x1
+#define ACP_I2SBT_ROR0__I2SBT_RXCHO__SHIFT 0x0
+#define ACP_I2SBT_TOR0__I2SBT_TXCHO_MASK 0x1
+#define ACP_I2SBT_TOR0__I2SBT_TXCHO__SHIFT 0x0
+#define ACP_I2SBT_RFCR0__I2SBT_RXCHDT_MASK 0xf
+#define ACP_I2SBT_RFCR0__I2SBT_RXCHDT__SHIFT 0x0
+#define ACP_I2SBT_TFCR0__I2SBT_TXCHET_MASK 0xf
+#define ACP_I2SBT_TFCR0__I2SBT_TXCHET__SHIFT 0x0
+#define ACP_I2SBT_RFF0__I2SBT_RXCHFR_MASK 0x1
+#define ACP_I2SBT_RFF0__I2SBT_RXCHFR__SHIFT 0x0
+#define ACP_I2SBT_TFF0__I2SBT_TXCHFR_MASK 0x1
+#define ACP_I2SBT_TFF0__I2SBT_TXCHFR__SHIFT 0x0
+#define ACP_I2SBT_LRBR1__I2SBT_LRBR1_MASK 0xffffffff
+#define ACP_I2SBT_LRBR1__I2SBT_LRBR1__SHIFT 0x0
+#define ACP_I2SBT_RRBR1__I2SBT_RRBR1_MASK 0xffffffff
+#define ACP_I2SBT_RRBR1__I2SBT_RRBR1__SHIFT 0x0
+#define ACP_I2SBT_RER1__I2SBT_RXCHEN1_MASK 0x1
+#define ACP_I2SBT_RER1__I2SBT_RXCHEN1__SHIFT 0x0
+#define ACP_I2SBT_TER1__I2SBT_TXCHEN1_MASK 0x1
+#define ACP_I2SBT_TER1__I2SBT_TXCHEN1__SHIFT 0x0
+#define ACP_I2SBT_RCR1__I2SBT_WLEN_MASK 0x7
+#define ACP_I2SBT_RCR1__I2SBT_WLEN__SHIFT 0x0
+#define ACP_I2SBT_TCR1__I2SBT_WLEN_MASK 0x7
+#define ACP_I2SBT_TCR1__I2SBT_WLEN__SHIFT 0x0
+#define ACP_I2SBT_ISR1__I2SBT_RXDA_MASK 0x1
+#define ACP_I2SBT_ISR1__I2SBT_RXDA__SHIFT 0x0
+#define ACP_I2SBT_ISR1__I2SBT_RXFO_MASK 0x2
+#define ACP_I2SBT_ISR1__I2SBT_RXFO__SHIFT 0x1
+#define ACP_I2SBT_ISR1__I2SBT_TXFE_MASK 0x10
+#define ACP_I2SBT_ISR1__I2SBT_TXFE__SHIFT 0x4
+#define ACP_I2SBT_ISR1__I2SBT_TXFO_MASK 0x20
+#define ACP_I2SBT_ISR1__I2SBT_TXFO__SHIFT 0x5
+#define ACP_I2SBT_IMR1__I2SBT_RXDAM_MASK 0x1
+#define ACP_I2SBT_IMR1__I2SBT_RXDAM__SHIFT 0x0
+#define ACP_I2SBT_IMR1__I2SBT_RXFOM_MASK 0x2
+#define ACP_I2SBT_IMR1__I2SBT_RXFOM__SHIFT 0x1
+#define ACP_I2SBT_IMR1__I2SBT_TXFEM_MASK 0x10
+#define ACP_I2SBT_IMR1__I2SBT_TXFEM__SHIFT 0x4
+#define ACP_I2SBT_IMR1__I2SBT_TXFOM_MASK 0x20
+#define ACP_I2SBT_IMR1__I2SBT_TXFOM__SHIFT 0x5
+#define ACP_I2SBT_ROR1__I2SBT_RXCHO_MASK 0x1
+#define ACP_I2SBT_ROR1__I2SBT_RXCHO__SHIFT 0x0
+#define ACP_I2SBT_TOR1__I2SBT_TXCHO_MASK 0x1
+#define ACP_I2SBT_TOR1__I2SBT_TXCHO__SHIFT 0x0
+#define ACP_I2SBT_RFCR1__I2SBT_RXCHDT_MASK 0xf
+#define ACP_I2SBT_RFCR1__I2SBT_RXCHDT__SHIFT 0x0
+#define ACP_I2SBT_TFCR1__I2SBT_TXCHET_MASK 0xf
+#define ACP_I2SBT_TFCR1__I2SBT_TXCHET__SHIFT 0x0
+#define ACP_I2SBT_RFF1__I2SBT_RXCHFR_MASK 0x1
+#define ACP_I2SBT_RFF1__I2SBT_RXCHFR__SHIFT 0x0
+#define ACP_I2SBT_TFF1__I2SBT_TXCHFR_MASK 0x1
+#define ACP_I2SBT_TFF1__I2SBT_TXCHFR__SHIFT 0x0
+#define ACP_I2SBT_RXDMA__I2SBT_RXDMA_MASK 0xffffffff
+#define ACP_I2SBT_RXDMA__I2SBT_RXDMA__SHIFT 0x0
+#define ACP_I2SBT_RRXDMA__I2SBT_RRXDMA_MASK 0x1
+#define ACP_I2SBT_RRXDMA__I2SBT_RRXDMA__SHIFT 0x0
+#define ACP_I2SBT_TXDMA__I2SBT_TXDMA_MASK 0xffffffff
+#define ACP_I2SBT_TXDMA__I2SBT_TXDMA__SHIFT 0x0
+#define ACP_I2SBT_RTXDMA__I2SBT_RTXDMA_MASK 0x1
+#define ACP_I2SBT_RTXDMA__I2SBT_RTXDMA__SHIFT 0x0
+#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_0_MASK 0x7
+#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_0__SHIFT 0x0
+#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_1_MASK 0x38
+#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_1__SHIFT 0x3
+#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_2_MASK 0x380
+#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_2__SHIFT 0x7
+#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_3_MASK 0x1c00
+#define ACP_I2SBT_COMP_PARAM_2__I2SBT_RX_WPRDSIZE_3__SHIFT 0xa
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_APB_DATA_WIDTH_MASK 0x3
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_APB_DATA_WIDTH__SHIFT 0x0
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_FIFO_DEPTH_GLOBAL_MASK 0xc
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_FIFO_DEPTH_GLOBAL__SHIFT 0x2
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_MODE_EN_MASK 0x10
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_MODE_EN__SHIFT 0x4
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TRANSMITTER_BLOCK_MASK 0x20
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TRANSMITTER_BLOCK__SHIFT 0x5
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_RECEIVER_BLOCK_MASK 0x40
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_RECEIVER_BLOCK__SHIFT 0x6
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_RX_CHANNLES_MASK 0x180
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_RX_CHANNLES__SHIFT 0x7
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_CHANNLES_MASK 0x600
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_CHANNLES__SHIFT 0x9
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_0_MASK 0x70000
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_0__SHIFT 0x10
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_1_MASK 0x380000
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_1__SHIFT 0x13
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_2_MASK 0x1c00000
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_2__SHIFT 0x16
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_3_MASK 0xe000000
+#define ACP_I2SBT_COMP_PARAM_1__I2SBT_TX_WORDSIZE_3__SHIFT 0x19
+#define ACP_I2SBT_COMP_VERSION__I2SBT_APB_DATA_WIDTH_MASK 0xffffffff
+#define ACP_I2SBT_COMP_VERSION__I2SBT_APB_DATA_WIDTH__SHIFT 0x0
+#define ACP_I2SBT_COMP_TYPE__I2SBT_COMP_TYPE_MASK 0xffffffff
+#define ACP_I2SBT_COMP_TYPE__I2SBT_COMP_TYPE__SHIFT 0x0
+
+#endif /* ACP_2_2_SH_MASK_H */
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 2d30464b81ce..06e099e802df 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -68,4 +68,13 @@ config SND_ATMEL_SOC_CLASSD
help
Say Y if you want to add support for Atmel ASoC driver for boards using
CLASSD.
+
+config SND_ATMEL_SOC_PDMIC
+ tristate "Atmel ASoC driver for boards using PDMIC"
+ depends on OF && (ARCH_AT91 || COMPILE_TEST)
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+ select REGMAP_MMIO
+ help
+ Say Y if you want to add support for Atmel ASoC driver for boards using
+ PDMIC.
endif
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index f6f7db428216..a2b127bd9c87 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -12,8 +12,10 @@ snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
snd-atmel-soc-wm8904-objs := atmel_wm8904.o
snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o
snd-atmel-soc-classd-objs := atmel-classd.o
+snd-atmel-soc-pdmic-objs := atmel-pdmic.o
obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o
obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o
obj-$(CONFIG_SND_ATMEL_SOC_CLASSD) += snd-atmel-soc-classd.o
+obj-$(CONFIG_SND_ATMEL_SOC_PDMIC) += snd-atmel-soc-pdmic.o
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
index 8276675730ef..6107de9c538b 100644
--- a/sound/soc/atmel/atmel-classd.c
+++ b/sound/soc/atmel/atmel-classd.c
@@ -106,7 +106,7 @@ static const struct snd_pcm_hardware atmel_classd_hw = {
.rates = ATMEL_CLASSD_RATES,
.rate_min = 8000,
.rate_max = 96000,
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.buffer_bytes_max = 64 * 1024,
.period_bytes_min = 256,
@@ -145,7 +145,7 @@ static const struct snd_soc_dai_ops atmel_classd_cpu_dai_ops = {
static struct snd_soc_dai_driver atmel_classd_cpu_dai = {
.playback = {
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = ATMEL_CLASSD_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
@@ -171,9 +171,13 @@ atmel_classd_platform_configure_dma(struct snd_pcm_substream *substream,
return -EINVAL;
}
+ if (params_channels(params) == 1)
+ slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ else
+ slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
slave_config->direction = DMA_MEM_TO_DEV;
slave_config->dst_addr = dd->phy_base + CLASSD_THR;
- slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slave_config->dst_maxburst = 1;
slave_config->src_maxburst = 1;
slave_config->device_fc = false;
@@ -486,7 +490,7 @@ static struct snd_soc_dai_driver atmel_classd_codec_dai = {
.name = ATMEL_CLASSD_CODEC_DAI_NAME,
.playback = {
.stream_name = "Playback",
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = ATMEL_CLASSD_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
@@ -636,8 +640,10 @@ static int atmel_classd_probe(struct platform_device *pdev)
/* register sound card */
card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
- if (!card)
- return -ENOMEM;
+ if (!card) {
+ ret = -ENOMEM;
+ goto unregister_codec;
+ }
snd_soc_card_set_drvdata(card, dd);
platform_set_drvdata(pdev, card);
@@ -645,16 +651,20 @@ static int atmel_classd_probe(struct platform_device *pdev)
ret = atmel_classd_asoc_card_init(dev, card);
if (ret) {
dev_err(dev, "failed to init sound card\n");
- return ret;
+ goto unregister_codec;
}
ret = devm_snd_soc_register_card(dev, card);
if (ret) {
dev_err(dev, "failed to register sound card: %d\n", ret);
- return ret;
+ goto unregister_codec;
}
return 0;
+
+unregister_codec:
+ snd_soc_unregister_codec(dev);
+ return ret;
}
static int atmel_classd_remove(struct platform_device *pdev)
diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c
new file mode 100644
index 000000000000..aee4787a0b89
--- /dev/null
+++ b/sound/soc/atmel/atmel-pdmic.c
@@ -0,0 +1,738 @@
+/* Atmel PDMIC driver
+ *
+ * Copyright (C) 2015 Atmel
+ *
+ * Author: Songjun Wu <songjun.wu@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or later
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include "atmel-pdmic.h"
+
+struct atmel_pdmic_pdata {
+ u32 mic_min_freq;
+ u32 mic_max_freq;
+ s32 mic_offset;
+ const char *card_name;
+};
+
+struct atmel_pdmic {
+ dma_addr_t phy_base;
+ struct regmap *regmap;
+ struct clk *pclk;
+ struct clk *gclk;
+ int irq;
+ struct snd_pcm_substream *substream;
+ const struct atmel_pdmic_pdata *pdata;
+};
+
+static const struct of_device_id atmel_pdmic_of_match[] = {
+ {
+ .compatible = "atmel,sama5d2-pdmic",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, atmel_pdmic_of_match);
+
+#define PDMIC_OFFSET_MAX_VAL S16_MAX
+#define PDMIC_OFFSET_MIN_VAL S16_MIN
+
+static struct atmel_pdmic_pdata *atmel_pdmic_dt_init(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct atmel_pdmic_pdata *pdata;
+
+ if (!np) {
+ dev_err(dev, "device node not found\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ if (of_property_read_string(np, "atmel,model", &pdata->card_name))
+ pdata->card_name = "PDMIC";
+
+ if (of_property_read_u32(np, "atmel,mic-min-freq",
+ &pdata->mic_min_freq)) {
+ dev_err(dev, "failed to get mic-min-freq\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(np, "atmel,mic-max-freq",
+ &pdata->mic_max_freq)) {
+ dev_err(dev, "failed to get mic-max-freq\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (pdata->mic_max_freq < pdata->mic_min_freq) {
+ dev_err(dev,
+ "mic-max-freq should not less than mic-min-freq\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_s32(np, "atmel,mic-offset", &pdata->mic_offset))
+ pdata->mic_offset = 0;
+
+ if (pdata->mic_offset > PDMIC_OFFSET_MAX_VAL) {
+ dev_warn(dev,
+ "mic-offset value %d is larger than the max value %d, the max value is specified\n",
+ pdata->mic_offset, PDMIC_OFFSET_MAX_VAL);
+ pdata->mic_offset = PDMIC_OFFSET_MAX_VAL;
+ } else if (pdata->mic_offset < PDMIC_OFFSET_MIN_VAL) {
+ dev_warn(dev,
+ "mic-offset value %d is less than the min value %d, the min value is specified\n",
+ pdata->mic_offset, PDMIC_OFFSET_MIN_VAL);
+ pdata->mic_offset = PDMIC_OFFSET_MIN_VAL;
+ }
+
+ return pdata;
+}
+
+/* cpu dai component */
+static int atmel_pdmic_cpu_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card);
+ int ret;
+
+ ret = clk_prepare_enable(dd->gclk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(dd->pclk);
+ if (ret)
+ return ret;
+
+ /* Clear all bits in the Control Register(PDMIC_CR) */
+ regmap_write(dd->regmap, PDMIC_CR, 0);
+
+ dd->substream = substream;
+
+ /* Enable the overrun error interrupt */
+ regmap_write(dd->regmap, PDMIC_IER, PDMIC_IER_OVRE);
+
+ return 0;
+}
+
+static void atmel_pdmic_cpu_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card);
+
+ /* Disable the overrun error interrupt */
+ regmap_write(dd->regmap, PDMIC_IDR, PDMIC_IDR_OVRE);
+
+ clk_disable_unprepare(dd->gclk);
+ clk_disable_unprepare(dd->pclk);
+}
+
+static int atmel_pdmic_cpu_dai_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card);
+ u32 val;
+
+ /* Clean the PDMIC Converted Data Register */
+ return regmap_read(dd->regmap, PDMIC_CDR, &val);
+}
+
+static const struct snd_soc_dai_ops atmel_pdmic_cpu_dai_ops = {
+ .startup = atmel_pdmic_cpu_dai_startup,
+ .shutdown = atmel_pdmic_cpu_dai_shutdown,
+ .prepare = atmel_pdmic_cpu_dai_prepare,
+};
+
+#define ATMEL_PDMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver atmel_pdmic_cpu_dai = {
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = ATMEL_PDMIC_FORMATS,},
+ .ops = &atmel_pdmic_cpu_dai_ops,
+};
+
+static const struct snd_soc_component_driver atmel_pdmic_cpu_dai_component = {
+ .name = "atmel-pdmic",
+};
+
+/* platform */
+#define ATMEL_PDMIC_MAX_BUF_SIZE (64 * 1024)
+#define ATMEL_PDMIC_PREALLOC_BUF_SIZE ATMEL_PDMIC_MAX_BUF_SIZE
+
+static const struct snd_pcm_hardware atmel_pdmic_hw = {
+ .info = SNDRV_PCM_INFO_MMAP
+ | SNDRV_PCM_INFO_MMAP_VALID
+ | SNDRV_PCM_INFO_INTERLEAVED
+ | SNDRV_PCM_INFO_RESUME
+ | SNDRV_PCM_INFO_PAUSE,
+ .formats = ATMEL_PDMIC_FORMATS,
+ .buffer_bytes_max = ATMEL_PDMIC_MAX_BUF_SIZE,
+ .period_bytes_min = 256,
+ .period_bytes_max = 32 * 1024,
+ .periods_min = 2,
+ .periods_max = 256,
+};
+
+static int
+atmel_pdmic_platform_configure_dma(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct dma_slave_config *slave_config)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card);
+ int ret;
+
+ ret = snd_hwparams_to_dma_slave_config(substream, params,
+ slave_config);
+ if (ret) {
+ dev_err(rtd->platform->dev,
+ "hw params to dma slave configure failed\n");
+ return ret;
+ }
+
+ slave_config->src_addr = dd->phy_base + PDMIC_CDR;
+ slave_config->src_maxburst = 1;
+ slave_config->dst_maxburst = 1;
+
+ return 0;
+}
+
+static const struct snd_dmaengine_pcm_config
+atmel_pdmic_dmaengine_pcm_config = {
+ .prepare_slave_config = atmel_pdmic_platform_configure_dma,
+ .pcm_hardware = &atmel_pdmic_hw,
+ .prealloc_buffer_size = ATMEL_PDMIC_PREALLOC_BUF_SIZE,
+};
+
+/* codec */
+/* Mic Gain = dgain * 2^(-scale) */
+struct mic_gain {
+ unsigned int dgain;
+ unsigned int scale;
+};
+
+/* range from -90 dB to 90 dB */
+static const struct mic_gain mic_gain_table[] = {
+{ 1, 15}, { 1, 14}, /* -90, -84 dB */
+{ 3, 15}, { 1, 13}, { 3, 14}, { 1, 12}, /* -81, -78, -75, -72 dB */
+{ 5, 14}, { 13, 15}, /* -70, -68 dB */
+{ 9, 14}, { 21, 15}, { 23, 15}, { 13, 14}, /* -65 ~ -62 dB */
+{ 29, 15}, { 33, 15}, { 37, 15}, { 41, 15}, /* -61 ~ -58 dB */
+{ 23, 14}, { 13, 13}, { 58, 15}, { 65, 15}, /* -57 ~ -54 dB */
+{ 73, 15}, { 41, 14}, { 23, 13}, { 13, 12}, /* -53 ~ -50 dB */
+{ 29, 13}, { 65, 14}, { 73, 14}, { 41, 13}, /* -49 ~ -46 dB */
+{ 23, 12}, { 207, 15}, { 29, 12}, { 65, 13}, /* -45 ~ -42 dB */
+{ 73, 13}, { 41, 12}, { 23, 11}, { 413, 15}, /* -41 ~ -38 dB */
+{ 463, 15}, { 519, 15}, { 583, 15}, { 327, 14}, /* -37 ~ -34 dB */
+{ 367, 14}, { 823, 15}, { 231, 13}, { 1036, 15}, /* -33 ~ -30 dB */
+{ 1163, 15}, { 1305, 15}, { 183, 12}, { 1642, 15}, /* -29 ~ -26 dB */
+{ 1843, 15}, { 2068, 15}, { 145, 11}, { 2603, 15}, /* -25 ~ -22 dB */
+{ 365, 12}, { 3277, 15}, { 3677, 15}, { 4125, 15}, /* -21 ~ -18 dB */
+{ 4629, 15}, { 5193, 15}, { 5827, 15}, { 3269, 14}, /* -17 ~ -14 dB */
+{ 917, 12}, { 8231, 15}, { 9235, 15}, { 5181, 14}, /* -13 ~ -10 dB */
+{11627, 15}, {13045, 15}, {14637, 15}, {16423, 15}, /* -9 ~ -6 dB */
+{18427, 15}, {20675, 15}, { 5799, 13}, {26029, 15}, /* -5 ~ -2 dB */
+{ 7301, 13}, { 1, 0}, {18383, 14}, {10313, 13}, /* -1 ~ 2 dB */
+{23143, 14}, {25967, 14}, {29135, 14}, {16345, 13}, /* 3 ~ 6 dB */
+{ 4585, 11}, {20577, 13}, { 1443, 9}, {25905, 13}, /* 7 ~ 10 dB */
+{14533, 12}, { 8153, 11}, { 2287, 9}, {20529, 12}, /* 11 ~ 14 dB */
+{11517, 11}, { 6461, 10}, {28997, 12}, { 4067, 9}, /* 15 ~ 18 dB */
+{18253, 11}, { 10, 0}, {22979, 11}, {25783, 11}, /* 19 ~ 22 dB */
+{28929, 11}, {32459, 11}, { 9105, 9}, {20431, 10}, /* 23 ~ 26 dB */
+{22925, 10}, {12861, 9}, { 7215, 8}, {16191, 9}, /* 27 ~ 30 dB */
+{ 9083, 8}, {20383, 9}, {11435, 8}, { 6145, 7}, /* 31 ~ 34 dB */
+{ 3599, 6}, {32305, 9}, {18123, 8}, {20335, 8}, /* 35 ~ 38 dB */
+{ 713, 3}, { 100, 0}, { 7181, 6}, { 8057, 6}, /* 39 ~ 42 dB */
+{ 565, 2}, {20287, 7}, {11381, 6}, {25539, 7}, /* 43 ~ 46 dB */
+{ 1791, 3}, { 4019, 4}, { 9019, 5}, {20239, 6}, /* 47 ~ 50 dB */
+{ 5677, 4}, {25479, 6}, { 7147, 4}, { 8019, 4}, /* 51 ~ 54 dB */
+{17995, 5}, {20191, 5}, {11327, 4}, {12709, 4}, /* 55 ~ 58 dB */
+{ 3565, 2}, { 1000, 0}, { 1122, 0}, { 1259, 0}, /* 59 ~ 62 dB */
+{ 2825, 1}, {12679, 3}, { 7113, 2}, { 7981, 2}, /* 63 ~ 66 dB */
+{ 8955, 2}, {20095, 3}, {22547, 3}, {12649, 2}, /* 67 ~ 70 dB */
+{28385, 3}, { 3981, 0}, {17867, 2}, {20047, 2}, /* 71 ~ 74 dB */
+{11247, 1}, {12619, 1}, {14159, 1}, {31773, 2}, /* 75 ~ 78 dB */
+{17825, 1}, {10000, 0}, {11220, 0}, {12589, 0}, /* 79 ~ 82 dB */
+{28251, 1}, {15849, 0}, {17783, 0}, {19953, 0}, /* 83 ~ 86 dB */
+{22387, 0}, {25119, 0}, {28184, 0}, {31623, 0}, /* 87 ~ 90 dB */
+};
+
+static const DECLARE_TLV_DB_RANGE(mic_gain_tlv,
+ 0, 1, TLV_DB_SCALE_ITEM(-9000, 600, 0),
+ 2, 5, TLV_DB_SCALE_ITEM(-8100, 300, 0),
+ 6, 7, TLV_DB_SCALE_ITEM(-7000, 200, 0),
+ 8, ARRAY_SIZE(mic_gain_table)-1, TLV_DB_SCALE_ITEM(-6500, 100, 0),
+);
+
+int pdmic_get_mic_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ unsigned int dgain_val, scale_val;
+ int i;
+
+ dgain_val = (snd_soc_read(codec, PDMIC_DSPR1) & PDMIC_DSPR1_DGAIN_MASK)
+ >> PDMIC_DSPR1_DGAIN_SHIFT;
+
+ scale_val = (snd_soc_read(codec, PDMIC_DSPR0) & PDMIC_DSPR0_SCALE_MASK)
+ >> PDMIC_DSPR0_SCALE_SHIFT;
+
+ for (i = 0; i < ARRAY_SIZE(mic_gain_table); i++) {
+ if ((mic_gain_table[i].dgain == dgain_val) &&
+ (mic_gain_table[i].scale == scale_val))
+ ucontrol->value.integer.value[0] = i;
+ }
+
+ return 0;
+}
+
+static int pdmic_put_mic_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int max = mc->max;
+ unsigned int val;
+ int ret;
+
+ val = ucontrol->value.integer.value[0];
+
+ if (val > max)
+ return -EINVAL;
+
+ ret = snd_soc_update_bits(codec, PDMIC_DSPR1, PDMIC_DSPR1_DGAIN_MASK,
+ mic_gain_table[val].dgain << PDMIC_DSPR1_DGAIN_SHIFT);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_update_bits(codec, PDMIC_DSPR0, PDMIC_DSPR0_SCALE_MASK,
+ mic_gain_table[val].scale << PDMIC_DSPR0_SCALE_SHIFT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new atmel_pdmic_snd_controls[] = {
+SOC_SINGLE_EXT_TLV("Mic Capture Volume", PDMIC_DSPR1, PDMIC_DSPR1_DGAIN_SHIFT,
+ ARRAY_SIZE(mic_gain_table)-1, 0,
+ pdmic_get_mic_volsw, pdmic_put_mic_volsw, mic_gain_tlv),
+
+SOC_SINGLE("High Pass Filter Switch", PDMIC_DSPR0,
+ PDMIC_DSPR0_HPFBYP_SHIFT, 1, 1),
+
+SOC_SINGLE("SINCC Filter Switch", PDMIC_DSPR0, PDMIC_DSPR0_SINBYP_SHIFT, 1, 1),
+};
+
+static int atmel_pdmic_codec_probe(struct snd_soc_codec *codec)
+{
+ struct snd_soc_card *card = snd_soc_codec_get_drvdata(codec);
+ struct atmel_pdmic *dd = snd_soc_card_get_drvdata(card);
+
+ snd_soc_update_bits(codec, PDMIC_DSPR1, PDMIC_DSPR1_OFFSET_MASK,
+ (u32)(dd->pdata->mic_offset << PDMIC_DSPR1_OFFSET_SHIFT));
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_pdmic = {
+ .probe = atmel_pdmic_codec_probe,
+ .controls = atmel_pdmic_snd_controls,
+ .num_controls = ARRAY_SIZE(atmel_pdmic_snd_controls),
+};
+
+/* codec dai component */
+#define PDMIC_MR_PRESCAL_MAX_VAL 127
+
+static int
+atmel_pdmic_codec_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct atmel_pdmic *dd = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_codec *codec = codec_dai->codec;
+ unsigned int rate_min = substream->runtime->hw.rate_min;
+ unsigned int rate_max = substream->runtime->hw.rate_max;
+ int fs = params_rate(params);
+ int bits = params_width(params);
+ unsigned long pclk_rate, gclk_rate;
+ unsigned int f_pdmic;
+ u32 mr_val, dspr0_val, pclk_prescal, gclk_prescal;
+
+ if (params_channels(params) != 1) {
+ dev_err(codec->dev,
+ "only supports one channel\n");
+ return -EINVAL;
+ }
+
+ if ((fs < rate_min) || (fs > rate_max)) {
+ dev_err(codec->dev,
+ "sample rate is %dHz, min rate is %dHz, max rate is %dHz\n",
+ fs, rate_min, rate_max);
+
+ return -EINVAL;
+ }
+
+ switch (bits) {
+ case 16:
+ dspr0_val = (PDMIC_DSPR0_SIZE_16_BITS
+ << PDMIC_DSPR0_SIZE_SHIFT);
+ break;
+ case 32:
+ dspr0_val = (PDMIC_DSPR0_SIZE_32_BITS
+ << PDMIC_DSPR0_SIZE_SHIFT);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((fs << 7) > (rate_max << 6)) {
+ f_pdmic = fs << 6;
+ dspr0_val |= PDMIC_DSPR0_OSR_64 << PDMIC_DSPR0_OSR_SHIFT;
+ } else {
+ f_pdmic = fs << 7;
+ dspr0_val |= PDMIC_DSPR0_OSR_128 << PDMIC_DSPR0_OSR_SHIFT;
+ }
+
+ pclk_rate = clk_get_rate(dd->pclk);
+ gclk_rate = clk_get_rate(dd->gclk);
+
+ /* PRESCAL = SELCK/(2*f_pdmic) - 1*/
+ pclk_prescal = (u32)(pclk_rate/(f_pdmic << 1)) - 1;
+ gclk_prescal = (u32)(gclk_rate/(f_pdmic << 1)) - 1;
+
+ if ((pclk_prescal > PDMIC_MR_PRESCAL_MAX_VAL) ||
+ (gclk_rate/((gclk_prescal + 1) << 1) <
+ pclk_rate/((pclk_prescal + 1) << 1))) {
+ mr_val = gclk_prescal << PDMIC_MR_PRESCAL_SHIFT;
+ mr_val |= PDMIC_MR_CLKS_GCK << PDMIC_MR_CLKS_SHIFT;
+ } else {
+ mr_val = pclk_prescal << PDMIC_MR_PRESCAL_SHIFT;
+ mr_val |= PDMIC_MR_CLKS_PCK << PDMIC_MR_CLKS_SHIFT;
+ }
+
+ snd_soc_update_bits(codec, PDMIC_MR,
+ PDMIC_MR_PRESCAL_MASK | PDMIC_MR_CLKS_MASK, mr_val);
+
+ snd_soc_update_bits(codec, PDMIC_DSPR0,
+ PDMIC_DSPR0_OSR_MASK | PDMIC_DSPR0_SIZE_MASK, dspr0_val);
+
+ return 0;
+}
+
+static int atmel_pdmic_codec_dai_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+
+ snd_soc_update_bits(codec, PDMIC_CR, PDMIC_CR_ENPDM_MASK,
+ PDMIC_CR_ENPDM_DIS << PDMIC_CR_ENPDM_SHIFT);
+
+ return 0;
+}
+
+static int atmel_pdmic_codec_dai_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u32 val;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ val = PDMIC_CR_ENPDM_EN << PDMIC_CR_ENPDM_SHIFT;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ val = PDMIC_CR_ENPDM_DIS << PDMIC_CR_ENPDM_SHIFT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, PDMIC_CR, PDMIC_CR_ENPDM_MASK, val);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops atmel_pdmic_codec_dai_ops = {
+ .hw_params = atmel_pdmic_codec_dai_hw_params,
+ .prepare = atmel_pdmic_codec_dai_prepare,
+ .trigger = atmel_pdmic_codec_dai_trigger,
+};
+
+#define ATMEL_PDMIC_CODEC_DAI_NAME "atmel-pdmic-hifi"
+
+static struct snd_soc_dai_driver atmel_pdmic_codec_dai = {
+ .name = ATMEL_PDMIC_CODEC_DAI_NAME,
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = SNDRV_PCM_RATE_KNOT,
+ .formats = ATMEL_PDMIC_FORMATS,
+ },
+ .ops = &atmel_pdmic_codec_dai_ops,
+};
+
+/* ASoC sound card */
+static int atmel_pdmic_asoc_card_init(struct device *dev,
+ struct snd_soc_card *card)
+{
+ struct snd_soc_dai_link *dai_link;
+ struct atmel_pdmic *dd = snd_soc_card_get_drvdata(card);
+
+ dai_link = devm_kzalloc(dev, sizeof(*dai_link), GFP_KERNEL);
+ if (!dai_link)
+ return -ENOMEM;
+
+ dai_link->name = "PDMIC";
+ dai_link->stream_name = "PDMIC PCM";
+ dai_link->codec_dai_name = ATMEL_PDMIC_CODEC_DAI_NAME;
+ dai_link->cpu_dai_name = dev_name(dev);
+ dai_link->codec_name = dev_name(dev);
+ dai_link->platform_name = dev_name(dev);
+
+ card->dai_link = dai_link;
+ card->num_links = 1;
+ card->name = dd->pdata->card_name;
+ card->dev = dev;
+
+ return 0;
+}
+
+static void atmel_pdmic_get_sample_rate(struct atmel_pdmic *dd,
+ unsigned int *rate_min, unsigned int *rate_max)
+{
+ u32 mic_min_freq = dd->pdata->mic_min_freq;
+ u32 mic_max_freq = dd->pdata->mic_max_freq;
+ u32 clk_max_rate = (u32)(clk_get_rate(dd->pclk) >> 1);
+ u32 clk_min_rate = (u32)(clk_get_rate(dd->gclk) >> 8);
+
+ if (mic_max_freq > clk_max_rate)
+ mic_max_freq = clk_max_rate;
+
+ if (mic_min_freq < clk_min_rate)
+ mic_min_freq = clk_min_rate;
+
+ *rate_min = DIV_ROUND_CLOSEST(mic_min_freq, 128);
+ *rate_max = mic_max_freq >> 6;
+}
+
+/* PDMIC interrupt handler */
+static irqreturn_t atmel_pdmic_interrupt(int irq, void *dev_id)
+{
+ struct atmel_pdmic *dd = (struct atmel_pdmic *)dev_id;
+ u32 pdmic_isr;
+ irqreturn_t ret = IRQ_NONE;
+
+ regmap_read(dd->regmap, PDMIC_ISR, &pdmic_isr);
+
+ if (pdmic_isr & PDMIC_ISR_OVRE) {
+ regmap_update_bits(dd->regmap, PDMIC_CR, PDMIC_CR_ENPDM_MASK,
+ PDMIC_CR_ENPDM_DIS << PDMIC_CR_ENPDM_SHIFT);
+
+ snd_pcm_stop_xrun(dd->substream);
+
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+/* regmap configuration */
+#define ATMEL_PDMIC_REG_MAX 0x124
+static const struct regmap_config atmel_pdmic_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = ATMEL_PDMIC_REG_MAX,
+};
+
+static int atmel_pdmic_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct atmel_pdmic *dd;
+ struct resource *res;
+ void __iomem *io_base;
+ const struct atmel_pdmic_pdata *pdata;
+ struct snd_soc_card *card;
+ unsigned int rate_min, rate_max;
+ int ret;
+
+ pdata = atmel_pdmic_dt_init(dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+
+ dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL);
+ if (!dd)
+ return -ENOMEM;
+
+ dd->pdata = pdata;
+
+ dd->irq = platform_get_irq(pdev, 0);
+ if (dd->irq < 0) {
+ ret = dd->irq;
+ dev_err(dev, "failed to could not get irq: %d\n", ret);
+ return ret;
+ }
+
+ dd->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(dd->pclk)) {
+ ret = PTR_ERR(dd->pclk);
+ dev_err(dev, "failed to get peripheral clock: %d\n", ret);
+ return ret;
+ }
+
+ dd->gclk = devm_clk_get(dev, "gclk");
+ if (IS_ERR(dd->gclk)) {
+ ret = PTR_ERR(dd->gclk);
+ dev_err(dev, "failed to get GCK: %d\n", ret);
+ return ret;
+ }
+
+ /* The gclk clock frequency must always be tree times
+ * lower than the pclk clock frequency
+ */
+ ret = clk_set_rate(dd->gclk, clk_get_rate(dd->pclk)/3);
+ if (ret) {
+ dev_err(dev, "failed to set GCK clock rate: %d\n", ret);
+ return ret;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "no memory resource\n");
+ return -ENXIO;
+ }
+
+ io_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(io_base)) {
+ ret = PTR_ERR(io_base);
+ dev_err(dev, "failed to remap register memory: %d\n", ret);
+ return ret;
+ }
+
+ dd->phy_base = res->start;
+
+ dd->regmap = devm_regmap_init_mmio(dev, io_base,
+ &atmel_pdmic_regmap_config);
+ if (IS_ERR(dd->regmap)) {
+ ret = PTR_ERR(dd->regmap);
+ dev_err(dev, "failed to init register map: %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_request_irq(dev, dd->irq, atmel_pdmic_interrupt, 0,
+ "PDMIC", (void *)dd);
+ if (ret < 0) {
+ dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
+ dd->irq, ret);
+ return ret;
+ }
+
+ /* Get the minimal and maximal sample rate that micphone supports */
+ atmel_pdmic_get_sample_rate(dd, &rate_min, &rate_max);
+
+ /* register cpu dai */
+ atmel_pdmic_cpu_dai.capture.rate_min = rate_min;
+ atmel_pdmic_cpu_dai.capture.rate_max = rate_max;
+ ret = devm_snd_soc_register_component(dev,
+ &atmel_pdmic_cpu_dai_component,
+ &atmel_pdmic_cpu_dai, 1);
+ if (ret) {
+ dev_err(dev, "could not register CPU DAI: %d\n", ret);
+ return ret;
+ }
+
+ /* register platform */
+ ret = devm_snd_dmaengine_pcm_register(dev,
+ &atmel_pdmic_dmaengine_pcm_config,
+ 0);
+ if (ret) {
+ dev_err(dev, "could not register platform: %d\n", ret);
+ return ret;
+ }
+
+ /* register codec and codec dai */
+ atmel_pdmic_codec_dai.capture.rate_min = rate_min;
+ atmel_pdmic_codec_dai.capture.rate_max = rate_max;
+ ret = snd_soc_register_codec(dev, &soc_codec_dev_pdmic,
+ &atmel_pdmic_codec_dai, 1);
+ if (ret) {
+ dev_err(dev, "could not register codec: %d\n", ret);
+ return ret;
+ }
+
+ /* register sound card */
+ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+ if (!card) {
+ ret = -ENOMEM;
+ goto unregister_codec;
+ }
+
+ snd_soc_card_set_drvdata(card, dd);
+ platform_set_drvdata(pdev, card);
+
+ ret = atmel_pdmic_asoc_card_init(dev, card);
+ if (ret) {
+ dev_err(dev, "failed to init sound card: %d\n", ret);
+ goto unregister_codec;
+ }
+
+ ret = devm_snd_soc_register_card(dev, card);
+ if (ret) {
+ dev_err(dev, "failed to register sound card: %d\n", ret);
+ goto unregister_codec;
+ }
+
+ return 0;
+
+unregister_codec:
+ snd_soc_unregister_codec(dev);
+ return ret;
+}
+
+static int atmel_pdmic_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver atmel_pdmic_driver = {
+ .driver = {
+ .name = "atmel-pdmic",
+ .of_match_table = of_match_ptr(atmel_pdmic_of_match),
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = atmel_pdmic_probe,
+ .remove = atmel_pdmic_remove,
+};
+module_platform_driver(atmel_pdmic_driver);
+
+MODULE_DESCRIPTION("Atmel PDMIC driver under ALSA SoC architecture");
+MODULE_AUTHOR("Songjun Wu <songjun.wu@atmel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/atmel/atmel-pdmic.h b/sound/soc/atmel/atmel-pdmic.h
new file mode 100644
index 000000000000..4527ac741919
--- /dev/null
+++ b/sound/soc/atmel/atmel-pdmic.h
@@ -0,0 +1,80 @@
+#ifndef __ATMEL_PDMIC_H_
+#define __ATMEL_PDMIC_H_
+
+#include <linux/bitops.h>
+
+#define PDMIC_CR 0x00000000
+
+#define PDMIC_CR_SWRST 0x1
+#define PDMIC_CR_SWRST_MASK BIT(0)
+#define PDMIC_CR_SWRST_SHIFT (0)
+
+#define PDMIC_CR_ENPDM_DIS 0x0
+#define PDMIC_CR_ENPDM_EN 0x1
+#define PDMIC_CR_ENPDM_MASK BIT(4)
+#define PDMIC_CR_ENPDM_SHIFT (4)
+
+#define PDMIC_MR 0x00000004
+
+#define PDMIC_MR_CLKS_PCK 0x0
+#define PDMIC_MR_CLKS_GCK 0x1
+#define PDMIC_MR_CLKS_MASK BIT(4)
+#define PDMIC_MR_CLKS_SHIFT (4)
+
+#define PDMIC_MR_PRESCAL_MASK GENMASK(14, 8)
+#define PDMIC_MR_PRESCAL_SHIFT (8)
+
+#define PDMIC_CDR 0x00000014
+
+#define PDMIC_IER 0x00000018
+#define PDMIC_IER_OVRE BIT(25)
+
+#define PDMIC_IDR 0x0000001c
+#define PDMIC_IDR_OVRE BIT(25)
+
+#define PDMIC_IMR 0x00000020
+
+#define PDMIC_ISR 0x00000024
+#define PDMIC_ISR_OVRE BIT(25)
+
+#define PDMIC_DSPR0 0x00000058
+
+#define PDMIC_DSPR0_HPFBYP_DIS 0x1
+#define PDMIC_DSPR0_HPFBYP_EN 0x0
+#define PDMIC_DSPR0_HPFBYP_MASK BIT(1)
+#define PDMIC_DSPR0_HPFBYP_SHIFT (1)
+
+#define PDMIC_DSPR0_SINBYP_DIS 0x1
+#define PDMIC_DSPR0_SINBYP_EN 0x0
+#define PDMIC_DSPR0_SINBYP_MASK BIT(2)
+#define PDMIC_DSPR0_SINBYP_SHIFT (2)
+
+#define PDMIC_DSPR0_SIZE_16_BITS 0x0
+#define PDMIC_DSPR0_SIZE_32_BITS 0x1
+#define PDMIC_DSPR0_SIZE_MASK BIT(3)
+#define PDMIC_DSPR0_SIZE_SHIFT (3)
+
+#define PDMIC_DSPR0_OSR_128 0x0
+#define PDMIC_DSPR0_OSR_64 0x1
+#define PDMIC_DSPR0_OSR_MASK GENMASK(6, 4)
+#define PDMIC_DSPR0_OSR_SHIFT (4)
+
+#define PDMIC_DSPR0_SCALE_MASK GENMASK(11, 8)
+#define PDMIC_DSPR0_SCALE_SHIFT (8)
+
+#define PDMIC_DSPR0_SHIFT_MASK GENMASK(15, 12)
+#define PDMIC_DSPR0_SHIFT_SHIFT (12)
+
+#define PDMIC_DSPR1 0x0000005c
+
+#define PDMIC_DSPR1_DGAIN_MASK GENMASK(14, 0)
+#define PDMIC_DSPR1_DGAIN_SHIFT (0)
+
+#define PDMIC_DSPR1_OFFSET_MASK GENMASK(31, 16)
+#define PDMIC_DSPR1_OFFSET_SHIFT (16)
+
+#define PDMIC_WPMR 0x000000e4
+
+#define PDMIC_WPSR 0x000000e8
+
+#endif
diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c
index 1933bcd46cca..fdd28ed3e0b9 100644
--- a/sound/soc/atmel/atmel_wm8904.c
+++ b/sound/soc/atmel/atmel_wm8904.c
@@ -183,6 +183,7 @@ static struct platform_driver atmel_asoc_wm8904_driver = {
.driver = {
.name = "atmel-wm8904-audio",
.of_match_table = of_match_ptr(atmel_asoc_wm8904_dt_ids),
+ .pm = &snd_soc_pm_ops,
},
.probe = atmel_asoc_wm8904_probe,
.remove = atmel_asoc_wm8904_remove,
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c
index 8c435beb263d..3303d5f58082 100644
--- a/sound/soc/bcm/bcm2835-i2s.c
+++ b/sound/soc/bcm/bcm2835-i2s.c
@@ -31,20 +31,20 @@
* General Public License for more details.
*/
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/module.h>
-#include <linux/device.h>
#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clk.h>
#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
-#include <sound/initval.h>
#include <sound/soc.h>
-#include <sound/dmaengine_pcm.h>
/* Clock registers */
#define BCM2835_CLK_PCMCTL_REG 0x00
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index cfdafc4c11ea..50693c867e71 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -55,9 +55,11 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CS4271_SPI if SPI_MASTER
select SND_SOC_CS42XX8_I2C if I2C
select SND_SOC_CS4349 if I2C
+ select SND_SOC_CS47L24 if MFD_CS47L24
select SND_SOC_CX20442 if TTY
select SND_SOC_DA7210 if SND_SOC_I2C_AND_SPI
select SND_SOC_DA7213 if I2C
+ select SND_SOC_DA7218 if I2C
select SND_SOC_DA7219 if I2C
select SND_SOC_DA732X if I2C
select SND_SOC_DA9055 if I2C
@@ -66,7 +68,9 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ES8328_SPI if SPI_MASTER
select SND_SOC_ES8328_I2C if I2C
select SND_SOC_GTM601
+ select SND_SOC_HDAC_HDMI
select SND_SOC_ICS43432
+ select SND_SOC_INNO_RK3036
select SND_SOC_ISABELLE if I2C
select SND_SOC_JZ4740_CODEC
select SND_SOC_LM4857 if I2C
@@ -83,16 +87,20 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ML26124 if I2C
select SND_SOC_NAU8825 if I2C
select SND_SOC_PCM1681 if I2C
- select SND_SOC_PCM1792A if SPI_MASTER
+ select SND_SOC_PCM179X if SPI_MASTER
select SND_SOC_PCM3008
+ select SND_SOC_PCM3168A_I2C if I2C
+ select SND_SOC_PCM3168A_SPI if SPI_MASTER
select SND_SOC_PCM512x_I2C if I2C
select SND_SOC_PCM512x_SPI if SPI_MASTER
select SND_SOC_RT286 if I2C
select SND_SOC_RT298 if I2C
+ select SND_SOC_RT5616 if I2C
select SND_SOC_RT5631 if I2C
select SND_SOC_RT5640 if I2C
select SND_SOC_RT5645 if I2C
select SND_SOC_RT5651 if I2C
+ select SND_SOC_RT5659 if I2C
select SND_SOC_RT5670 if I2C
select SND_SOC_RT5677 if I2C && SPI_MASTER
select SND_SOC_SGTL5000 if I2C
@@ -195,10 +203,12 @@ config SND_SOC_88PM860X
config SND_SOC_ARIZONA
tristate
+ default y if SND_SOC_CS47L24=y
default y if SND_SOC_WM5102=y
default y if SND_SOC_WM5110=y
default y if SND_SOC_WM8997=y
default y if SND_SOC_WM8998=y
+ default m if SND_SOC_CS47L24=m
default m if SND_SOC_WM5102=m
default m if SND_SOC_WM5110=m
default m if SND_SOC_WM8997=m
@@ -211,9 +221,12 @@ config SND_SOC_WM_HUBS
config SND_SOC_WM_ADSP
tristate
+ select SND_SOC_COMPRESS
+ default y if SND_SOC_CS47L24=y
default y if SND_SOC_WM5102=y
default y if SND_SOC_WM5110=y
default y if SND_SOC_WM2200=y
+ default m if SND_SOC_CS47L24=m
default m if SND_SOC_WM5102=m
default m if SND_SOC_WM5110=m
default m if SND_SOC_WM2200=m
@@ -422,6 +435,9 @@ config SND_SOC_CS4349
tristate "Cirrus Logic CS4349 CODEC"
depends on I2C
+config SND_SOC_CS47L24
+ tristate
+
config SND_SOC_CX20442
tristate
depends on TTY
@@ -439,6 +455,9 @@ config SND_SOC_DA7210
config SND_SOC_DA7213
tristate
+config SND_SOC_DA7218
+ tristate
+
config SND_SOC_DA7219
tristate
@@ -468,9 +487,17 @@ config SND_SOC_ES8328_SPI
config SND_SOC_GTM601
tristate 'GTM601 UMTS modem audio codec'
+config SND_SOC_HDAC_HDMI
+ tristate
+ select SND_HDA_EXT_CORE
+ select HDMI
+
config SND_SOC_ICS43432
tristate
+config SND_SOC_INNO_RK3036
+ tristate "Inno codec driver for RK3036 SoC"
+
config SND_SOC_ISABELLE
tristate
@@ -499,13 +526,28 @@ config SND_SOC_PCM1681
tristate "Texas Instruments PCM1681 CODEC"
depends on I2C
-config SND_SOC_PCM1792A
- tristate "Texas Instruments PCM1792A CODEC"
+config SND_SOC_PCM179X
+ tristate "Texas Instruments PCM179X CODEC"
depends on SPI_MASTER
config SND_SOC_PCM3008
tristate
+config SND_SOC_PCM3168A
+ tristate
+
+config SND_SOC_PCM3168A_I2C
+ tristate "Texas Instruments PCM3168A CODEC - I2C"
+ depends on I2C
+ select SND_SOC_PCM3168A
+ select REGMAP_I2C
+
+config SND_SOC_PCM3168A_SPI
+ tristate "Texas Instruments PCM3168A CODEC - SPI"
+ depends on SPI_MASTER
+ select SND_SOC_PCM3168A
+ select REGMAP_SPI
+
config SND_SOC_PCM512x
tristate
@@ -523,14 +565,18 @@ config SND_SOC_PCM512x_SPI
config SND_SOC_RL6231
tristate
+ default y if SND_SOC_RT5616=y
default y if SND_SOC_RT5640=y
default y if SND_SOC_RT5645=y
default y if SND_SOC_RT5651=y
+ default y if SND_SOC_RT5659=y
default y if SND_SOC_RT5670=y
default y if SND_SOC_RT5677=y
+ default m if SND_SOC_RT5616=m
default m if SND_SOC_RT5640=m
default m if SND_SOC_RT5645=m
default m if SND_SOC_RT5651=m
+ default m if SND_SOC_RT5659=m
default m if SND_SOC_RT5670=m
default m if SND_SOC_RT5677=m
@@ -549,6 +595,9 @@ config SND_SOC_RT298
tristate
depends on I2C
+config SND_SOC_RT5616
+ tristate
+
config SND_SOC_RT5631
tristate "Realtek ALC5631/RT5631 CODEC"
depends on I2C
@@ -562,6 +611,9 @@ config SND_SOC_RT5645
config SND_SOC_RT5651
tristate
+config SND_SOC_RT5659
+ tristate
+
config SND_SOC_RT5670
tristate
@@ -838,7 +890,8 @@ config SND_SOC_WM8971
tristate
config SND_SOC_WM8974
- tristate
+ tristate "Wolfson Microelectronics WM8974 codec"
+ depends on I2C
config SND_SOC_WM8978
tristate "Wolfson Microelectronics WM8978 codec"
@@ -891,6 +944,7 @@ config SND_SOC_WM9712
config SND_SOC_WM9713
tristate
+ select REGMAP_AC97
# Amp
config SND_SOC_LM4857
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index f632fc42f59f..d44f7d347183 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -47,9 +47,11 @@ snd-soc-cs4271-spi-objs := cs4271-spi.o
snd-soc-cs42xx8-objs := cs42xx8.o
snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o
snd-soc-cs4349-objs := cs4349.o
+snd-soc-cs47l24-objs := cs47l24.o
snd-soc-cx20442-objs := cx20442.o
snd-soc-da7210-objs := da7210.o
snd-soc-da7213-objs := da7213.o
+snd-soc-da7218-objs := da7218.o
snd-soc-da7219-objs := da7219.o da7219-aad.o
snd-soc-da732x-objs := da732x.o
snd-soc-da9055-objs := da9055.o
@@ -59,7 +61,9 @@ snd-soc-es8328-objs := es8328.o
snd-soc-es8328-i2c-objs := es8328-i2c.o
snd-soc-es8328-spi-objs := es8328-spi.o
snd-soc-gtm601-objs := gtm601.o
+snd-soc-hdac-hdmi-objs := hdac_hdmi.o
snd-soc-ics43432-objs := ics43432.o
+snd-soc-inno-rk3036-objs := inno_rk3036.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-l3-objs := l3.o
@@ -76,8 +80,11 @@ snd-soc-mc13783-objs := mc13783.o
snd-soc-ml26124-objs := ml26124.o
snd-soc-nau8825-objs := nau8825.o
snd-soc-pcm1681-objs := pcm1681.o
-snd-soc-pcm1792a-codec-objs := pcm1792a.o
+snd-soc-pcm179x-codec-objs := pcm179x.o
snd-soc-pcm3008-objs := pcm3008.o
+snd-soc-pcm3168a-objs := pcm3168a.o
+snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o
+snd-soc-pcm3168a-spi-objs := pcm3168a-spi.o
snd-soc-pcm512x-objs := pcm512x.o
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
@@ -85,10 +92,12 @@ snd-soc-rl6231-objs := rl6231.o
snd-soc-rl6347a-objs := rl6347a.o
snd-soc-rt286-objs := rt286.o
snd-soc-rt298-objs := rt298.o
+snd-soc-rt5616-objs := rt5616.o
snd-soc-rt5631-objs := rt5631.o
snd-soc-rt5640-objs := rt5640.o
snd-soc-rt5645-objs := rt5645.o
snd-soc-rt5651-objs := rt5651.o
+snd-soc-rt5659-objs := rt5659.o
snd-soc-rt5670-objs := rt5670.o
snd-soc-rt5677-objs := rt5677.o
snd-soc-rt5677-spi-objs := rt5677-spi.o
@@ -242,9 +251,11 @@ obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o
obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o
obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o
obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o
+obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
+obj-$(CONFIG_SND_SOC_DA7218) += snd-soc-da7218.o
obj-$(CONFIG_SND_SOC_DA7219) += snd-soc-da7219.o
obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
@@ -254,7 +265,9 @@ obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o
+obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o
obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
+obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
@@ -271,8 +284,11 @@ obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o
obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o
-obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o
+obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
+obj-$(CONFIG_SND_SOC_PCM3168A) += snd-soc-pcm3168a.o
+obj-$(CONFIG_SND_SOC_PCM3168A_I2C) += snd-soc-pcm3168a-i2c.o
+obj-$(CONFIG_SND_SOC_PCM3168A_SPI) += snd-soc-pcm3168a-spi.o
obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
@@ -280,10 +296,12 @@ obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o
obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o
+obj-$(CONFIG_SND_SOC_RT5616) += snd-soc-rt5616.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o
+obj-$(CONFIG_SND_SOC_RT5659) += snd-soc-rt5659.o
obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index 07a266460ec3..647f69de6baa 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -70,18 +70,11 @@
#define FMT_MASK (0xf8)
/* CTRL2 */
+#define DFS_MASK (3 << 2)
#define DFS_NORMAL_SPEED (0 << 2)
#define DFS_DOUBLE_SPEED (1 << 2)
#define DFS_QUAD_SPEED (2 << 2)
-struct ak4613_priv {
- struct mutex lock;
-
- unsigned int fmt;
- u8 fmt_ctrl;
- int cnt;
-};
-
struct ak4613_formats {
unsigned int width;
unsigned int fmt;
@@ -92,6 +85,16 @@ struct ak4613_interface {
struct ak4613_formats playback;
};
+struct ak4613_priv {
+ struct mutex lock;
+ const struct ak4613_interface *iface;
+
+ unsigned int fmt;
+ u8 oc;
+ u8 ic;
+ int cnt;
+};
+
/*
* Playback Volume
*
@@ -126,7 +129,7 @@ static const struct reg_default ak4613_reg[] = {
{ 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0x00 },
};
-#define AUDIO_IFACE_IDX_TO_VAL(i) (i << 3)
+#define AUDIO_IFACE_TO_VAL(fmts) ((fmts - ak4613_iface) << 3)
#define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt }
static const struct ak4613_interface ak4613_iface[] = {
/* capture */ /* playback */
@@ -240,7 +243,7 @@ static void ak4613_dai_shutdown(struct snd_pcm_substream *substream,
priv->cnt = 0;
}
if (!priv->cnt)
- priv->fmt_ctrl = NO_FMT;
+ priv->iface = NULL;
mutex_unlock(&priv->lock);
}
@@ -265,13 +268,35 @@ static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0;
}
+static bool ak4613_dai_fmt_matching(const struct ak4613_interface *iface,
+ int is_play,
+ unsigned int fmt, unsigned int width)
+{
+ const struct ak4613_formats *fmts;
+
+ fmts = (is_play) ? &iface->playback : &iface->capture;
+
+ if (fmts->fmt != fmt)
+ return false;
+
+ if (fmt == SND_SOC_DAIFMT_RIGHT_J) {
+ if (fmts->width != width)
+ return false;
+ } else {
+ if (fmts->width < width)
+ return false;
+ }
+
+ return true;
+}
+
static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec);
- const struct ak4613_formats *fmts;
+ const struct ak4613_interface *iface;
struct device *dev = codec->dev;
unsigned int width = params_width(params);
unsigned int fmt = priv->fmt;
@@ -305,33 +330,27 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
* It doesn't support TDM at this point
*/
fmt_ctrl = NO_FMT;
- for (i = 0; i < ARRAY_SIZE(ak4613_iface); i++) {
- fmts = (is_play) ? &ak4613_iface[i].playback :
- &ak4613_iface[i].capture;
-
- if (fmts->fmt != fmt)
- continue;
+ ret = -EINVAL;
+ iface = NULL;
- if (fmt == SND_SOC_DAIFMT_RIGHT_J) {
- if (fmts->width != width)
- continue;
- } else {
- if (fmts->width < width)
+ mutex_lock(&priv->lock);
+ if (priv->iface) {
+ if (ak4613_dai_fmt_matching(priv->iface, is_play, fmt, width))
+ iface = priv->iface;
+ } else {
+ for (i = ARRAY_SIZE(ak4613_iface); i >= 0; i--) {
+ if (!ak4613_dai_fmt_matching(ak4613_iface + i,
+ is_play,
+ fmt, width))
continue;
+ iface = ak4613_iface + i;
+ break;
}
-
- fmt_ctrl = AUDIO_IFACE_IDX_TO_VAL(i);
- break;
}
- ret = -EINVAL;
- if (fmt_ctrl == NO_FMT)
- goto hw_params_end;
-
- mutex_lock(&priv->lock);
- if ((priv->fmt_ctrl == NO_FMT) ||
- (priv->fmt_ctrl == fmt_ctrl)) {
- priv->fmt_ctrl = fmt_ctrl;
+ if ((priv->iface == NULL) ||
+ (priv->iface == iface)) {
+ priv->iface = iface;
priv->cnt++;
ret = 0;
}
@@ -340,8 +359,13 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
goto hw_params_end;
+ fmt_ctrl = AUDIO_IFACE_TO_VAL(iface);
+
snd_soc_update_bits(codec, CTRL1, FMT_MASK, fmt_ctrl);
- snd_soc_write(codec, CTRL2, ctrl2);
+ snd_soc_update_bits(codec, CTRL2, DFS_MASK, ctrl2);
+
+ snd_soc_write(codec, ICTRL, priv->ic);
+ snd_soc_write(codec, OCTRL, priv->oc);
hw_params_end:
if (ret < 0)
@@ -431,6 +455,28 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4613 = {
.num_dapm_routes = ARRAY_SIZE(ak4613_intercon),
};
+static void ak4613_parse_of(struct ak4613_priv *priv,
+ struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ char prop[32];
+ int i;
+
+ /* Input 1 - 2 */
+ for (i = 0; i < 2; i++) {
+ snprintf(prop, sizeof(prop), "asahi-kasei,in%d-single-end", i + 1);
+ if (!of_get_property(np, prop, NULL))
+ priv->ic |= 1 << i;
+ }
+
+ /* Output 1 - 6 */
+ for (i = 0; i < 6; i++) {
+ snprintf(prop, sizeof(prop), "asahi-kasei,out%d-single-end", i + 1);
+ if (!of_get_property(np, prop, NULL))
+ priv->oc |= 1 << i;
+ }
+}
+
static int ak4613_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -458,7 +504,9 @@ static int ak4613_i2c_probe(struct i2c_client *i2c,
if (!priv)
return -ENOMEM;
- priv->fmt_ctrl = NO_FMT;
+ ak4613_parse_of(priv, dev);
+
+ priv->iface = NULL;
priv->cnt = 0;
mutex_init(&priv->lock);
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 93b400800905..33143fe1de0b 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -310,7 +310,7 @@ int arizona_init_gpio(struct snd_soc_codec *codec)
}
EXPORT_SYMBOL_GPL(arizona_init_gpio);
-const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
+const char * const arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
"None",
"Tone Generator 1",
"Tone Generator 2",
@@ -418,7 +418,7 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
};
EXPORT_SYMBOL_GPL(arizona_mixer_texts);
-int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
+unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
0x00, /* None */
0x04, /* Tone */
0x05,
@@ -555,12 +555,12 @@ const char *arizona_sample_rate_val_to_name(unsigned int rate_val)
}
EXPORT_SYMBOL_GPL(arizona_sample_rate_val_to_name);
-const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
+const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
"SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate",
};
EXPORT_SYMBOL_GPL(arizona_rate_text);
-const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
+const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
0, 1, 2, 8,
};
EXPORT_SYMBOL_GPL(arizona_rate_val);
@@ -702,6 +702,100 @@ const struct soc_enum arizona_in_dmic_osr[] = {
};
EXPORT_SYMBOL_GPL(arizona_in_dmic_osr);
+static const char * const arizona_anc_input_src_text[] = {
+ "None", "IN1", "IN2", "IN3", "IN4",
+};
+
+static const char * const arizona_anc_channel_src_text[] = {
+ "None", "Left", "Right", "Combine",
+};
+
+const struct soc_enum arizona_anc_input_src[] = {
+ SOC_ENUM_SINGLE(ARIZONA_ANC_SRC,
+ ARIZONA_IN_RXANCL_SEL_SHIFT,
+ ARRAY_SIZE(arizona_anc_input_src_text),
+ arizona_anc_input_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_FCL_ADC_REFORMATTER_CONTROL,
+ ARIZONA_FCL_MIC_MODE_SEL,
+ ARRAY_SIZE(arizona_anc_channel_src_text),
+ arizona_anc_channel_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_ANC_SRC,
+ ARIZONA_IN_RXANCR_SEL_SHIFT,
+ ARRAY_SIZE(arizona_anc_input_src_text),
+ arizona_anc_input_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_FCR_ADC_REFORMATTER_CONTROL,
+ ARIZONA_FCR_MIC_MODE_SEL,
+ ARRAY_SIZE(arizona_anc_channel_src_text),
+ arizona_anc_channel_src_text),
+};
+EXPORT_SYMBOL_GPL(arizona_anc_input_src);
+
+static const char * const arizona_anc_ng_texts[] = {
+ "None",
+ "Internal",
+ "External",
+};
+
+SOC_ENUM_SINGLE_DECL(arizona_anc_ng_enum, SND_SOC_NOPM, 0,
+ arizona_anc_ng_texts);
+EXPORT_SYMBOL_GPL(arizona_anc_ng_enum);
+
+static const char * const arizona_output_anc_src_text[] = {
+ "None", "RXANCL", "RXANCR",
+};
+
+const struct soc_enum arizona_output_anc_src[] = {
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
+ ARIZONA_OUT1L_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1R,
+ ARIZONA_OUT1R_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L,
+ ARIZONA_OUT2L_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2R,
+ ARIZONA_OUT2R_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
+ ARIZONA_OUT3L_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_DAC_VOLUME_LIMIT_3R,
+ ARIZONA_OUT3R_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4L,
+ ARIZONA_OUT4L_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4R,
+ ARIZONA_OUT4R_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5L,
+ ARIZONA_OUT5L_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5R,
+ ARIZONA_OUT5R_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6L,
+ ARIZONA_OUT6L_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+ SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6R,
+ ARIZONA_OUT6R_ANC_SRC_SHIFT,
+ ARRAY_SIZE(arizona_output_anc_src_text),
+ arizona_output_anc_src_text),
+};
+EXPORT_SYMBOL_GPL(arizona_output_anc_src);
+
static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
@@ -1023,6 +1117,31 @@ void arizona_init_dvfs(struct arizona_priv *priv)
}
EXPORT_SYMBOL_GPL(arizona_init_dvfs);
+int arizona_anc_ev(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ unsigned int mask = 0x3 << w->shift;
+ unsigned int val;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ val = 1 << w->shift;
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ val = 1 << (w->shift + 1);
+ break;
+ default:
+ return 0;
+ }
+
+ snd_soc_update_bits(codec, ARIZONA_CLOCK_CONTROL, mask, val);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_anc_ev);
+
static unsigned int arizona_opclk_ref_48k_rates[] = {
6144000,
12288000,
@@ -1095,7 +1214,7 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
unsigned int reg;
unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
- unsigned int *clk;
+ int *clk;
switch (clk_id) {
case ARIZONA_CLK_SYSCLK:
@@ -1375,6 +1494,9 @@ static int arizona_startup(struct snd_pcm_substream *substream,
const struct snd_pcm_hw_constraint_list *constraint;
unsigned int base_rate;
+ if (!substream->runtime)
+ return 0;
+
switch (dai_priv->clk) {
case ARIZONA_CLK_SYSCLK:
base_rate = priv->sysclk;
@@ -1901,18 +2023,18 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
}
switch (fll->arizona->type) {
+ case WM5102:
+ case WM8997:
+ return init_ratio;
case WM5110:
case WM8280:
if (fll->arizona->rev < 3 || sync)
return init_ratio;
break;
- case WM8998:
- case WM1814:
+ default:
if (sync)
return init_ratio;
break;
- default:
- return init_ratio;
}
cfg->fratio = init_ratio - 1;
@@ -2093,9 +2215,9 @@ static int arizona_enable_fll(struct arizona_fll *fll)
/* Facilitate smooth refclk across the transition */
regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
ARIZONA_FLL1_GAIN_MASK, 0);
- regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
- ARIZONA_FLL1_FREERUN,
- ARIZONA_FLL1_FREERUN);
+ regmap_update_bits(fll->arizona->regmap, fll->base + 1,
+ ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
+ udelay(32);
}
/*
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index fea8b8ae8e1a..8b6adb5419bb 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -57,7 +57,7 @@
#define ARIZONA_CLK_98MHZ 5
#define ARIZONA_CLK_147MHZ 6
-#define ARIZONA_MAX_DAI 6
+#define ARIZONA_MAX_DAI 8
#define ARIZONA_MAX_ADSP 4
#define ARIZONA_DVFS_SR1_RQ 0x001
@@ -96,8 +96,8 @@ struct arizona_priv {
#define ARIZONA_NUM_MIXER_INPUTS 104
extern const unsigned int arizona_mixer_tlv[];
-extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS];
-extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
+extern const char * const arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS];
+extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
#define ARIZONA_GAINMUX_CONTROLS(name, base) \
SOC_SINGLE_RANGE_TLV(name " Input Volume", base + 1, \
@@ -216,8 +216,8 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
#define ARIZONA_RATE_ENUM_SIZE 4
#define ARIZONA_SAMPLE_RATE_ENUM_SIZE 14
-extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
-extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];
+extern const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
+extern const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];
extern const char * const arizona_sample_rate_text[ARIZONA_SAMPLE_RATE_ENUM_SIZE];
extern const unsigned int arizona_sample_rate_val[ARIZONA_SAMPLE_RATE_ENUM_SIZE];
@@ -242,6 +242,10 @@ extern const struct soc_enum arizona_in_dmic_osr[];
extern const struct snd_kcontrol_new arizona_adsp2_rate_controls[];
+extern const struct soc_enum arizona_anc_input_src[];
+extern const struct soc_enum arizona_anc_ng_enum;
+extern const struct soc_enum arizona_output_anc_src[];
+
extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
@@ -251,6 +255,9 @@ extern int arizona_out_ev(struct snd_soc_dapm_widget *w,
extern int arizona_hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
+extern int arizona_anc_ev(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event);
extern int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c
new file mode 100644
index 000000000000..dc5ae7f7a1bd
--- /dev/null
+++ b/sound/soc/codecs/cs47l24.c
@@ -0,0 +1,1148 @@
+/*
+ * cs47l24.h -- ALSA SoC Audio driver for Cirrus Logic CS47L24
+ *
+ * Copyright 2015 Cirrus Logic Inc.
+ *
+ * Author: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/registers.h>
+
+#include "arizona.h"
+#include "wm_adsp.h"
+#include "cs47l24.h"
+
+struct cs47l24_priv {
+ struct arizona_priv core;
+ struct arizona_fll fll[2];
+};
+
+static const struct wm_adsp_region cs47l24_dsp2_regions[] = {
+ { .type = WMFW_ADSP2_PM, .base = 0x200000 },
+ { .type = WMFW_ADSP2_ZM, .base = 0x280000 },
+ { .type = WMFW_ADSP2_XM, .base = 0x290000 },
+ { .type = WMFW_ADSP2_YM, .base = 0x2a8000 },
+};
+
+static const struct wm_adsp_region cs47l24_dsp3_regions[] = {
+ { .type = WMFW_ADSP2_PM, .base = 0x300000 },
+ { .type = WMFW_ADSP2_ZM, .base = 0x380000 },
+ { .type = WMFW_ADSP2_XM, .base = 0x390000 },
+ { .type = WMFW_ADSP2_YM, .base = 0x3a8000 },
+};
+
+static const struct wm_adsp_region *cs47l24_dsp_regions[] = {
+ cs47l24_dsp2_regions,
+ cs47l24_dsp3_regions,
+};
+
+static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0);
+static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
+
+#define CS47L24_NG_SRC(name, base) \
+ SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \
+ SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \
+ SOC_SINGLE(name " NG SPKOUT Switch", base, 6, 1, 0)
+
+static const struct snd_kcontrol_new cs47l24_snd_controls[] = {
+SOC_ENUM("IN1 OSR", arizona_in_dmic_osr[0]),
+SOC_ENUM("IN2 OSR", arizona_in_dmic_osr[1]),
+
+SOC_ENUM("IN HPF Cutoff Frequency", arizona_in_hpf_cut_enum),
+
+SOC_SINGLE("IN1L HPF Switch", ARIZONA_IN1L_CONTROL,
+ ARIZONA_IN1L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN1R HPF Switch", ARIZONA_IN1R_CONTROL,
+ ARIZONA_IN1R_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN2L HPF Switch", ARIZONA_IN2L_CONTROL,
+ ARIZONA_IN2L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN2R HPF Switch", ARIZONA_IN2R_CONTROL,
+ ARIZONA_IN2R_HPF_SHIFT, 1, 0),
+
+SOC_SINGLE_TLV("IN1L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L,
+ ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
+SOC_SINGLE_TLV("IN1R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1R,
+ ARIZONA_IN1R_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
+SOC_SINGLE_TLV("IN2L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L,
+ ARIZONA_IN2L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
+SOC_SINGLE_TLV("IN2R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2R,
+ ARIZONA_IN2R_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
+
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
+ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
+
+ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
+SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+
+ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
+SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+
+ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE),
+
+SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5,
+ ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA),
+SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5,
+ ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA),
+
+ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
+
+ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
+ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
+ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
+ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
+
+SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
+SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
+SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
+SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
+
+SOC_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+SOC_ENUM("ISRC3 FSL", arizona_isrc_fsl[2]),
+SOC_ENUM("ISRC1 FSH", arizona_isrc_fsh[0]),
+SOC_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]),
+SOC_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]),
+SOC_ENUM("ASRC RATE 1", arizona_asrc_rate1),
+
+ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP2R", ARIZONA_DSP2RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP3L", ARIZONA_DSP3LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP3R", ARIZONA_DSP3RMIX_INPUT_1_SOURCE),
+
+SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR,
+ ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv),
+
+ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("SPKOUT", ARIZONA_OUT4LMIX_INPUT_1_SOURCE),
+
+SOC_SINGLE("HPOUT1 SC Protect Switch", ARIZONA_HP1_SHORT_CIRCUIT_CTRL,
+ ARIZONA_HP1_SC_ENA_SHIFT, 1, 0),
+
+SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
+ ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_SINGLE("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L,
+ ARIZONA_OUT4L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
+ ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+SOC_SINGLE_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L,
+ ARIZONA_OUT4L_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
+
+SOC_SINGLE("Noise Gate Switch", ARIZONA_NOISE_GATE_CONTROL,
+ ARIZONA_NGATE_ENA_SHIFT, 1, 0),
+SOC_SINGLE_TLV("Noise Gate Threshold Volume", ARIZONA_NOISE_GATE_CONTROL,
+ ARIZONA_NGATE_THR_SHIFT, 7, 1, ng_tlv),
+SOC_ENUM("Noise Gate Hold", arizona_ng_hold),
+
+CS47L24_NG_SRC("HPOUT1L", ARIZONA_NOISE_GATE_SELECT_1L),
+CS47L24_NG_SRC("HPOUT1R", ARIZONA_NOISE_GATE_SELECT_1R),
+CS47L24_NG_SRC("SPKOUT", ARIZONA_NOISE_GATE_SELECT_4L),
+
+ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE),
+
+ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX3", ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX4", ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX5", ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX6", ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE),
+
+ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
+};
+
+ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP2L, ARIZONA_DSP2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP2R, ARIZONA_DSP2RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP2, ARIZONA_DSP2AUX1MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP3L, ARIZONA_DSP3LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP3R, ARIZONA_DSP3RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP3, ARIZONA_DSP3AUX1MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(SPKOUT, ARIZONA_OUT4LMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX3, ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX4, ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX5, ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX6, ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC1INT1, ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1INT2, ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1INT3, ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1INT4, ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC1DEC1, ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1DEC2, ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1DEC3, ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1DEC4, ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC2INT1, ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2INT2, ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2INT3, ARIZONA_ISRC2INT3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2INT4, ARIZONA_ISRC2INT4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC2DEC1, ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2DEC2, ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2DEC3, ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2DEC4, ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC3INT1, ARIZONA_ISRC3INT1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3INT2, ARIZONA_ISRC3INT2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3INT3, ARIZONA_ISRC3INT3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3INT4, ARIZONA_ISRC3INT4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC3DEC1, ARIZONA_ISRC3DEC1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3DEC2, ARIZONA_ISRC3DEC2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3DEC3, ARIZONA_ISRC3DEC3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3DEC4, ARIZONA_ISRC3DEC4MIX_INPUT_1_SOURCE);
+
+static const char * const cs47l24_aec_loopback_texts[] = {
+ "HPOUT1L", "HPOUT1R", "SPKOUT",
+};
+
+static const unsigned int cs47l24_aec_loopback_values[] = {
+ 0, 1, 6,
+};
+
+static const struct soc_enum cs47l24_aec_loopback =
+ SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1,
+ ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
+ ARRAY_SIZE(cs47l24_aec_loopback_texts),
+ cs47l24_aec_loopback_texts,
+ cs47l24_aec_loopback_values);
+
+static const struct snd_kcontrol_new cs47l24_aec_loopback_mux =
+ SOC_DAPM_ENUM("AEC Loopback", cs47l24_aec_loopback);
+
+static const struct snd_soc_dapm_widget cs47l24_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1,
+ ARIZONA_SYSCLK_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
+ ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
+ ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK,
+ ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS),
+SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDD", 0, 0),
+
+SND_SOC_DAPM_SIGGEN("TONE"),
+SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+
+SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"),
+SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
+
+SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
+ 0, NULL, 0, arizona_in_ev,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
+ 0, NULL, 0, arizona_in_ev,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
+ 0, NULL, 0, arizona_in_ev,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
+ 0, NULL, 0, arizona_in_ev,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
+ ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
+ ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
+ ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1,
+ ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1,
+ ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0,
+ NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0,
+ NULL, 0),
+
+SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT,
+ 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
+ NULL, 0),
+
+WM_ADSP2("DSP2", 1),
+WM_ADSP2("DSP3", 2),
+
+SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
+ ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1INT2", ARIZONA_ISRC_1_CTRL_3,
+ ARIZONA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1INT3", ARIZONA_ISRC_1_CTRL_3,
+ ARIZONA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1INT4", ARIZONA_ISRC_1_CTRL_3,
+ ARIZONA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC1DEC1", ARIZONA_ISRC_1_CTRL_3,
+ ARIZONA_ISRC1_DEC0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1DEC2", ARIZONA_ISRC_1_CTRL_3,
+ ARIZONA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1DEC3", ARIZONA_ISRC_1_CTRL_3,
+ ARIZONA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1DEC4", ARIZONA_ISRC_1_CTRL_3,
+ ARIZONA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC2INT1", ARIZONA_ISRC_2_CTRL_3,
+ ARIZONA_ISRC2_INT0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2INT2", ARIZONA_ISRC_2_CTRL_3,
+ ARIZONA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2INT3", ARIZONA_ISRC_2_CTRL_3,
+ ARIZONA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2INT4", ARIZONA_ISRC_2_CTRL_3,
+ ARIZONA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC2DEC1", ARIZONA_ISRC_2_CTRL_3,
+ ARIZONA_ISRC2_DEC0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3,
+ ARIZONA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2DEC3", ARIZONA_ISRC_2_CTRL_3,
+ ARIZONA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2DEC4", ARIZONA_ISRC_2_CTRL_3,
+ ARIZONA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC3INT1", ARIZONA_ISRC_3_CTRL_3,
+ ARIZONA_ISRC3_INT0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3INT2", ARIZONA_ISRC_3_CTRL_3,
+ ARIZONA_ISRC3_INT1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3INT3", ARIZONA_ISRC_3_CTRL_3,
+ ARIZONA_ISRC3_INT2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3INT4", ARIZONA_ISRC_3_CTRL_3,
+ ARIZONA_ISRC3_INT3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC3DEC1", ARIZONA_ISRC_3_CTRL_3,
+ ARIZONA_ISRC3_DEC0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3DEC2", ARIZONA_ISRC_3_CTRL_3,
+ ARIZONA_ISRC3_DEC1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3DEC3", ARIZONA_ISRC_3_CTRL_3,
+ ARIZONA_ISRC3_DEC2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3DEC4", ARIZONA_ISRC_3_CTRL_3,
+ ARIZONA_ISRC3_DEC3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
+ ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
+ &cs47l24_aec_loopback_mux),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
+ ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
+ ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
+ ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
+ ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
+ ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
+ ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
+ ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
+ ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
+ ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
+ ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
+ ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
+ ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
+ ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
+ ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
+ ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
+ ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
+ ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
+ ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0,
+ ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0,
+ ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0,
+ ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0,
+ ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
+ ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
+ ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0,
+ ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0,
+ ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0,
+ ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0,
+ ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
+ ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
+ ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
+ ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
+ ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
+ ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
+ ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+
+ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"),
+ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"),
+
+ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"),
+ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"),
+ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"),
+ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"),
+
+ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"),
+ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"),
+ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"),
+ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"),
+
+ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"),
+ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"),
+
+ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"),
+ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"),
+ARIZONA_MIXER_WIDGETS(SPKOUT, "SPKOUT"),
+
+ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
+ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
+
+ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
+ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
+ARIZONA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"),
+ARIZONA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"),
+ARIZONA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"),
+ARIZONA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"),
+
+ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
+ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
+
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
+
+ARIZONA_DSP_WIDGETS(DSP2, "DSP2"),
+ARIZONA_DSP_WIDGETS(DSP3, "DSP3"),
+
+ARIZONA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"),
+ARIZONA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"),
+ARIZONA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"),
+ARIZONA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"),
+
+ARIZONA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"),
+ARIZONA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"),
+ARIZONA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"),
+ARIZONA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"),
+
+ARIZONA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"),
+ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
+ARIZONA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"),
+ARIZONA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"),
+
+ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
+ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
+ARIZONA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"),
+ARIZONA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"),
+
+ARIZONA_MUX_WIDGETS(ISRC3DEC1, "ISRC3DEC1"),
+ARIZONA_MUX_WIDGETS(ISRC3DEC2, "ISRC3DEC2"),
+ARIZONA_MUX_WIDGETS(ISRC3DEC3, "ISRC3DEC3"),
+ARIZONA_MUX_WIDGETS(ISRC3DEC4, "ISRC3DEC4"),
+
+ARIZONA_MUX_WIDGETS(ISRC3INT1, "ISRC3INT1"),
+ARIZONA_MUX_WIDGETS(ISRC3INT2, "ISRC3INT2"),
+ARIZONA_MUX_WIDGETS(ISRC3INT3, "ISRC3INT3"),
+ARIZONA_MUX_WIDGETS(ISRC3INT4, "ISRC3INT4"),
+
+SND_SOC_DAPM_OUTPUT("HPOUT1L"),
+SND_SOC_DAPM_OUTPUT("HPOUT1R"),
+SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+SND_SOC_DAPM_OUTPUT("SPKOUTP"),
+
+SND_SOC_DAPM_OUTPUT("MICSUPP"),
+};
+
+#define ARIZONA_MIXER_INPUT_ROUTES(name) \
+ { name, "Noise Generator", "Noise Generator" }, \
+ { name, "Tone Generator 1", "Tone Generator 1" }, \
+ { name, "Tone Generator 2", "Tone Generator 2" }, \
+ { name, "Haptics", "HAPTICS" }, \
+ { name, "AEC", "AEC Loopback" }, \
+ { name, "IN1L", "IN1L PGA" }, \
+ { name, "IN1R", "IN1R PGA" }, \
+ { name, "IN2L", "IN2L PGA" }, \
+ { name, "IN2R", "IN2R PGA" }, \
+ { name, "AIF1RX1", "AIF1RX1" }, \
+ { name, "AIF1RX2", "AIF1RX2" }, \
+ { name, "AIF1RX3", "AIF1RX3" }, \
+ { name, "AIF1RX4", "AIF1RX4" }, \
+ { name, "AIF1RX5", "AIF1RX5" }, \
+ { name, "AIF1RX6", "AIF1RX6" }, \
+ { name, "AIF1RX7", "AIF1RX7" }, \
+ { name, "AIF1RX8", "AIF1RX8" }, \
+ { name, "AIF2RX1", "AIF2RX1" }, \
+ { name, "AIF2RX2", "AIF2RX2" }, \
+ { name, "AIF2RX3", "AIF2RX3" }, \
+ { name, "AIF2RX4", "AIF2RX4" }, \
+ { name, "AIF2RX5", "AIF2RX5" }, \
+ { name, "AIF2RX6", "AIF2RX6" }, \
+ { name, "AIF3RX1", "AIF3RX1" }, \
+ { name, "AIF3RX2", "AIF3RX2" }, \
+ { name, "EQ1", "EQ1" }, \
+ { name, "EQ2", "EQ2" }, \
+ { name, "DRC1L", "DRC1L" }, \
+ { name, "DRC1R", "DRC1R" }, \
+ { name, "DRC2L", "DRC2L" }, \
+ { name, "DRC2R", "DRC2R" }, \
+ { name, "LHPF1", "LHPF1" }, \
+ { name, "LHPF2", "LHPF2" }, \
+ { name, "LHPF3", "LHPF3" }, \
+ { name, "LHPF4", "LHPF4" }, \
+ { name, "ASRC1L", "ASRC1L" }, \
+ { name, "ASRC1R", "ASRC1R" }, \
+ { name, "ASRC2L", "ASRC2L" }, \
+ { name, "ASRC2R", "ASRC2R" }, \
+ { name, "ISRC1DEC1", "ISRC1DEC1" }, \
+ { name, "ISRC1DEC2", "ISRC1DEC2" }, \
+ { name, "ISRC1DEC3", "ISRC1DEC3" }, \
+ { name, "ISRC1DEC4", "ISRC1DEC4" }, \
+ { name, "ISRC1INT1", "ISRC1INT1" }, \
+ { name, "ISRC1INT2", "ISRC1INT2" }, \
+ { name, "ISRC1INT3", "ISRC1INT3" }, \
+ { name, "ISRC1INT4", "ISRC1INT4" }, \
+ { name, "ISRC2DEC1", "ISRC2DEC1" }, \
+ { name, "ISRC2DEC2", "ISRC2DEC2" }, \
+ { name, "ISRC2DEC3", "ISRC2DEC3" }, \
+ { name, "ISRC2DEC4", "ISRC2DEC4" }, \
+ { name, "ISRC2INT1", "ISRC2INT1" }, \
+ { name, "ISRC2INT2", "ISRC2INT2" }, \
+ { name, "ISRC2INT3", "ISRC2INT3" }, \
+ { name, "ISRC2INT4", "ISRC2INT4" }, \
+ { name, "ISRC3DEC1", "ISRC3DEC1" }, \
+ { name, "ISRC3DEC2", "ISRC3DEC2" }, \
+ { name, "ISRC3DEC3", "ISRC3DEC3" }, \
+ { name, "ISRC3DEC4", "ISRC3DEC4" }, \
+ { name, "ISRC3INT1", "ISRC3INT1" }, \
+ { name, "ISRC3INT2", "ISRC3INT2" }, \
+ { name, "ISRC3INT3", "ISRC3INT3" }, \
+ { name, "ISRC3INT4", "ISRC3INT4" }, \
+ { name, "DSP2.1", "DSP2" }, \
+ { name, "DSP2.2", "DSP2" }, \
+ { name, "DSP2.3", "DSP2" }, \
+ { name, "DSP2.4", "DSP2" }, \
+ { name, "DSP2.5", "DSP2" }, \
+ { name, "DSP2.6", "DSP2" }, \
+ { name, "DSP3.1", "DSP3" }, \
+ { name, "DSP3.2", "DSP3" }, \
+ { name, "DSP3.3", "DSP3" }, \
+ { name, "DSP3.4", "DSP3" }, \
+ { name, "DSP3.5", "DSP3" }, \
+ { name, "DSP3.6", "DSP3" }
+
+static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = {
+ { "OUT1L", NULL, "CPVDD" },
+ { "OUT1R", NULL, "CPVDD" },
+
+ { "OUT4L", NULL, "SPKVDD" },
+
+ { "OUT1L", NULL, "SYSCLK" },
+ { "OUT1R", NULL, "SYSCLK" },
+ { "OUT4L", NULL, "SYSCLK" },
+
+ { "IN1L", NULL, "SYSCLK" },
+ { "IN1R", NULL, "SYSCLK" },
+ { "IN2L", NULL, "SYSCLK" },
+ { "IN2R", NULL, "SYSCLK" },
+
+ { "MICBIAS1", NULL, "MICVDD" },
+ { "MICBIAS2", NULL, "MICVDD" },
+
+ { "Noise Generator", NULL, "SYSCLK" },
+ { "Tone Generator 1", NULL, "SYSCLK" },
+ { "Tone Generator 2", NULL, "SYSCLK" },
+
+ { "Noise Generator", NULL, "NOISE" },
+ { "Tone Generator 1", NULL, "TONE" },
+ { "Tone Generator 2", NULL, "TONE" },
+
+ { "AIF1 Capture", NULL, "AIF1TX1" },
+ { "AIF1 Capture", NULL, "AIF1TX2" },
+ { "AIF1 Capture", NULL, "AIF1TX3" },
+ { "AIF1 Capture", NULL, "AIF1TX4" },
+ { "AIF1 Capture", NULL, "AIF1TX5" },
+ { "AIF1 Capture", NULL, "AIF1TX6" },
+ { "AIF1 Capture", NULL, "AIF1TX7" },
+ { "AIF1 Capture", NULL, "AIF1TX8" },
+
+ { "AIF1RX1", NULL, "AIF1 Playback" },
+ { "AIF1RX2", NULL, "AIF1 Playback" },
+ { "AIF1RX3", NULL, "AIF1 Playback" },
+ { "AIF1RX4", NULL, "AIF1 Playback" },
+ { "AIF1RX5", NULL, "AIF1 Playback" },
+ { "AIF1RX6", NULL, "AIF1 Playback" },
+ { "AIF1RX7", NULL, "AIF1 Playback" },
+ { "AIF1RX8", NULL, "AIF1 Playback" },
+
+ { "AIF2 Capture", NULL, "AIF2TX1" },
+ { "AIF2 Capture", NULL, "AIF2TX2" },
+ { "AIF2 Capture", NULL, "AIF2TX3" },
+ { "AIF2 Capture", NULL, "AIF2TX4" },
+ { "AIF2 Capture", NULL, "AIF2TX5" },
+ { "AIF2 Capture", NULL, "AIF2TX6" },
+
+ { "AIF2RX1", NULL, "AIF2 Playback" },
+ { "AIF2RX2", NULL, "AIF2 Playback" },
+ { "AIF2RX3", NULL, "AIF2 Playback" },
+ { "AIF2RX4", NULL, "AIF2 Playback" },
+ { "AIF2RX5", NULL, "AIF2 Playback" },
+ { "AIF2RX6", NULL, "AIF2 Playback" },
+
+ { "AIF3 Capture", NULL, "AIF3TX1" },
+ { "AIF3 Capture", NULL, "AIF3TX2" },
+
+ { "AIF3RX1", NULL, "AIF3 Playback" },
+ { "AIF3RX2", NULL, "AIF3 Playback" },
+
+ { "AIF1 Playback", NULL, "SYSCLK" },
+ { "AIF2 Playback", NULL, "SYSCLK" },
+ { "AIF3 Playback", NULL, "SYSCLK" },
+
+ { "AIF1 Capture", NULL, "SYSCLK" },
+ { "AIF2 Capture", NULL, "SYSCLK" },
+ { "AIF3 Capture", NULL, "SYSCLK" },
+
+ { "IN1L PGA", NULL, "IN1L" },
+ { "IN1R PGA", NULL, "IN1R" },
+
+ { "IN2L PGA", NULL, "IN2L" },
+ { "IN2R PGA", NULL, "IN2R" },
+
+ ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
+ ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
+
+ ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUT"),
+
+ ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"),
+ ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"),
+
+ ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+ ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+ ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+ ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+ ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+ ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+ ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
+ ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
+
+ ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
+ ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
+ ARIZONA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"),
+ ARIZONA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"),
+ ARIZONA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"),
+ ARIZONA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"),
+
+ ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
+ ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
+
+ ARIZONA_MIXER_ROUTES("EQ1", "EQ1"),
+ ARIZONA_MIXER_ROUTES("EQ2", "EQ2"),
+
+ ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"),
+ ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"),
+ ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"),
+ ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"),
+
+ ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"),
+ ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"),
+ ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
+ ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
+
+ ARIZONA_MUX_ROUTES("ASRC1L", "ASRC1L"),
+ ARIZONA_MUX_ROUTES("ASRC1R", "ASRC1R"),
+ ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"),
+ ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"),
+
+ ARIZONA_DSP_ROUTES("DSP2"),
+ ARIZONA_DSP_ROUTES("DSP3"),
+
+ ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"),
+ ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"),
+ ARIZONA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"),
+ ARIZONA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"),
+
+ ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"),
+ ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"),
+ ARIZONA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"),
+ ARIZONA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"),
+
+ ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"),
+ ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"),
+ ARIZONA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"),
+ ARIZONA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"),
+
+ ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"),
+ ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"),
+ ARIZONA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"),
+ ARIZONA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"),
+
+ ARIZONA_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"),
+ ARIZONA_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"),
+ ARIZONA_MUX_ROUTES("ISRC3INT3", "ISRC3INT3"),
+ ARIZONA_MUX_ROUTES("ISRC3INT4", "ISRC3INT4"),
+
+ ARIZONA_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"),
+ ARIZONA_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"),
+ ARIZONA_MUX_ROUTES("ISRC3DEC3", "ISRC3DEC3"),
+ ARIZONA_MUX_ROUTES("ISRC3DEC4", "ISRC3DEC4"),
+
+ { "AEC Loopback", "HPOUT1L", "OUT1L" },
+ { "AEC Loopback", "HPOUT1R", "OUT1R" },
+ { "HPOUT1L", NULL, "OUT1L" },
+ { "HPOUT1R", NULL, "OUT1R" },
+
+ { "AEC Loopback", "SPKOUT", "OUT4L" },
+ { "SPKOUTN", NULL, "OUT4L" },
+ { "SPKOUTP", NULL, "OUT4L" },
+
+ { "MICSUPP", NULL, "SYSCLK" },
+
+ { "DRC1 Signal Activity", NULL, "DRC1L" },
+ { "DRC1 Signal Activity", NULL, "DRC1R" },
+ { "DRC2 Signal Activity", NULL, "DRC2L" },
+ { "DRC2 Signal Activity", NULL, "DRC2R" },
+};
+
+static int cs47l24_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+ unsigned int Fref, unsigned int Fout)
+{
+ struct cs47l24_priv *cs47l24 = snd_soc_codec_get_drvdata(codec);
+
+ switch (fll_id) {
+ case CS47L24_FLL1:
+ return arizona_set_fll(&cs47l24->fll[0], source, Fref, Fout);
+ case CS47L24_FLL2:
+ return arizona_set_fll(&cs47l24->fll[1], source, Fref, Fout);
+ case CS47L24_FLL1_REFCLK:
+ return arizona_set_fll_refclk(&cs47l24->fll[0], source, Fref,
+ Fout);
+ case CS47L24_FLL2_REFCLK:
+ return arizona_set_fll_refclk(&cs47l24->fll[1], source, Fref,
+ Fout);
+ default:
+ return -EINVAL;
+ }
+}
+
+#define CS47L24_RATES SNDRV_PCM_RATE_8000_192000
+
+#define CS47L24_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver cs47l24_dai[] = {
+ {
+ .name = "cs47l24-aif1",
+ .id = 1,
+ .base = ARIZONA_AIF1_BCLK_CTRL,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = CS47L24_RATES,
+ .formats = CS47L24_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = CS47L24_RATES,
+ .formats = CS47L24_FORMATS,
+ },
+ .ops = &arizona_dai_ops,
+ .symmetric_rates = 1,
+ .symmetric_samplebits = 1,
+ },
+ {
+ .name = "cs47l24-aif2",
+ .id = 2,
+ .base = ARIZONA_AIF2_BCLK_CTRL,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .channels_min = 1,
+ .channels_max = 6,
+ .rates = CS47L24_RATES,
+ .formats = CS47L24_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 6,
+ .rates = CS47L24_RATES,
+ .formats = CS47L24_FORMATS,
+ },
+ .ops = &arizona_dai_ops,
+ .symmetric_rates = 1,
+ .symmetric_samplebits = 1,
+ },
+ {
+ .name = "cs47l24-aif3",
+ .id = 3,
+ .base = ARIZONA_AIF3_BCLK_CTRL,
+ .playback = {
+ .stream_name = "AIF3 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS47L24_RATES,
+ .formats = CS47L24_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF3 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS47L24_RATES,
+ .formats = CS47L24_FORMATS,
+ },
+ .ops = &arizona_dai_ops,
+ .symmetric_rates = 1,
+ .symmetric_samplebits = 1,
+ },
+};
+
+static int cs47l24_codec_probe(struct snd_soc_codec *codec)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+ struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ priv->core.arizona->dapm = dapm;
+
+ arizona_init_spk(codec);
+ arizona_init_gpio(codec);
+ arizona_init_mono(codec);
+
+ ret = wm_adsp2_codec_probe(&priv->core.adsp[1], codec);
+ if (ret)
+ goto err_adsp2_codec_probe;
+
+ ret = wm_adsp2_codec_probe(&priv->core.adsp[2], codec);
+ if (ret)
+ goto err_adsp2_codec_probe;
+
+ ret = snd_soc_add_codec_controls(codec,
+ &arizona_adsp2_rate_controls[1], 2);
+ if (ret)
+ goto err_adsp2_codec_probe;
+
+ snd_soc_dapm_disable_pin(dapm, "HAPTICS");
+
+ return 0;
+
+err_adsp2_codec_probe:
+ wm_adsp2_codec_remove(&priv->core.adsp[1], codec);
+ wm_adsp2_codec_remove(&priv->core.adsp[2], codec);
+
+ return ret;
+}
+
+static int cs47l24_codec_remove(struct snd_soc_codec *codec)
+{
+ struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+
+ wm_adsp2_codec_remove(&priv->core.adsp[1], codec);
+ wm_adsp2_codec_remove(&priv->core.adsp[2], codec);
+
+ priv->core.arizona->dapm = NULL;
+
+ return 0;
+}
+
+#define CS47L24_DIG_VU 0x0200
+
+static unsigned int cs47l24_digital_vu[] = {
+ ARIZONA_DAC_DIGITAL_VOLUME_1L,
+ ARIZONA_DAC_DIGITAL_VOLUME_1R,
+ ARIZONA_DAC_DIGITAL_VOLUME_4L,
+};
+
+static struct regmap *cs47l24_get_regmap(struct device *dev)
+{
+ struct cs47l24_priv *priv = dev_get_drvdata(dev);
+
+ return priv->core.arizona->regmap;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_cs47l24 = {
+ .probe = cs47l24_codec_probe,
+ .remove = cs47l24_codec_remove,
+ .get_regmap = cs47l24_get_regmap,
+
+ .idle_bias_off = true,
+
+ .set_sysclk = arizona_set_sysclk,
+ .set_pll = cs47l24_set_fll,
+
+ .controls = cs47l24_snd_controls,
+ .num_controls = ARRAY_SIZE(cs47l24_snd_controls),
+ .dapm_widgets = cs47l24_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(cs47l24_dapm_widgets),
+ .dapm_routes = cs47l24_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(cs47l24_dapm_routes),
+};
+
+static int cs47l24_probe(struct platform_device *pdev)
+{
+ struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+ struct cs47l24_priv *cs47l24;
+ int i, ret;
+
+ BUILD_BUG_ON(ARRAY_SIZE(cs47l24_dai) > ARIZONA_MAX_DAI);
+
+ cs47l24 = devm_kzalloc(&pdev->dev, sizeof(struct cs47l24_priv),
+ GFP_KERNEL);
+ if (!cs47l24)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, cs47l24);
+
+ cs47l24->core.arizona = arizona;
+ cs47l24->core.num_inputs = 4;
+
+ for (i = 1; i <= 2; i++) {
+ cs47l24->core.adsp[i].part = "cs47l24";
+ cs47l24->core.adsp[i].num = i + 1;
+ cs47l24->core.adsp[i].type = WMFW_ADSP2;
+ cs47l24->core.adsp[i].dev = arizona->dev;
+ cs47l24->core.adsp[i].regmap = arizona->regmap;
+
+ cs47l24->core.adsp[i].base = ARIZONA_DSP1_CONTROL_1 +
+ (0x100 * i);
+ cs47l24->core.adsp[i].mem = cs47l24_dsp_regions[i - 1];
+ cs47l24->core.adsp[i].num_mems =
+ ARRAY_SIZE(cs47l24_dsp2_regions);
+
+ ret = wm_adsp2_init(&cs47l24->core.adsp[i]);
+ if (ret != 0)
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cs47l24->fll); i++)
+ cs47l24->fll[i].vco_mult = 3;
+
+ arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1,
+ ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK,
+ &cs47l24->fll[0]);
+ arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1,
+ ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
+ &cs47l24->fll[1]);
+
+ /* SR2 fixed at 8kHz, SR3 fixed at 16kHz */
+ regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2,
+ ARIZONA_SAMPLE_RATE_2_MASK, 0x11);
+ regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3,
+ ARIZONA_SAMPLE_RATE_3_MASK, 0x12);
+
+ for (i = 0; i < ARRAY_SIZE(cs47l24_dai); i++)
+ arizona_init_dai(&cs47l24->core, i);
+
+ /* Latch volume update bits */
+ for (i = 0; i < ARRAY_SIZE(cs47l24_digital_vu); i++)
+ regmap_update_bits(arizona->regmap, cs47l24_digital_vu[i],
+ CS47L24_DIG_VU, CS47L24_DIG_VU);
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_idle(&pdev->dev);
+
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_cs47l24,
+ cs47l24_dai, ARRAY_SIZE(cs47l24_dai));
+}
+
+static int cs47l24_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static struct platform_driver cs47l24_codec_driver = {
+ .driver = {
+ .name = "cs47l24-codec",
+ },
+ .probe = cs47l24_probe,
+ .remove = cs47l24_remove,
+};
+
+module_platform_driver(cs47l24_codec_driver);
+
+MODULE_DESCRIPTION("ASoC CS47L24 driver");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:cs47l24-codec");
diff --git a/sound/soc/codecs/cs47l24.h b/sound/soc/codecs/cs47l24.h
new file mode 100644
index 000000000000..77ab2b77b2e6
--- /dev/null
+++ b/sound/soc/codecs/cs47l24.h
@@ -0,0 +1,23 @@
+/*
+ * cs47l24.h -- ALSA SoC Audio driver for Cirrus Logic CS47L24
+ *
+ * Copyright 2015 Cirrus Logic Inc.
+ *
+ * Author: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _CS47L24_H
+#define _CS47L24_H
+
+#include "arizona.h"
+
+#define CS47L24_FLL1 1
+#define CS47L24_FLL2 2
+#define CS47L24_FLL1_REFCLK 3
+#define CS47L24_FLL2_REFCLK 4
+
+#endif
diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c
new file mode 100644
index 000000000000..93575f251866
--- /dev/null
+++ b/sound/soc/codecs/da7218.c
@@ -0,0 +1,3341 @@
+/*
+ * da7218.c - DA7218 ALSA SoC Codec Driver
+ *
+ * Copyright (c) 2015 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.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; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <asm/div64.h>
+
+#include <sound/da7218.h>
+#include "da7218.h"
+
+
+/*
+ * TLVs and Enums
+ */
+
+/* Input TLVs */
+static const DECLARE_TLV_DB_SCALE(da7218_mic_gain_tlv, -600, 600, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_mixin_gain_tlv, -450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_in_dig_gain_tlv, -8325, 75, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_ags_trigger_tlv, -9000, 600, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_ags_att_max_tlv, 0, 600, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_alc_threshold_tlv, -9450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_alc_gain_tlv, 0, 600, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_alc_ana_gain_tlv, 0, 600, 0);
+
+/* Input/Output TLVs */
+static const DECLARE_TLV_DB_SCALE(da7218_dmix_gain_tlv, -4200, 150, 0);
+
+/* Output TLVs */
+static const DECLARE_TLV_DB_SCALE(da7218_dgs_trigger_tlv, -9450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_dgs_anticlip_tlv, -4200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_dgs_signal_tlv, -9000, 600, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_out_eq_band_tlv, -1050, 150, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_out_dig_gain_tlv, -8325, 75, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_dac_ng_threshold_tlv, -10200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_mixout_gain_tlv, -100, 50, 0);
+static const DECLARE_TLV_DB_SCALE(da7218_hp_gain_tlv, -5700, 150, 0);
+
+/* Input Enums */
+static const char * const da7218_alc_attack_rate_txt[] = {
+ "7.33/fs", "14.66/fs", "29.32/fs", "58.64/fs", "117.3/fs", "234.6/fs",
+ "469.1/fs", "938.2/fs", "1876/fs", "3753/fs", "7506/fs", "15012/fs",
+ "30024/fs",
+};
+
+static const struct soc_enum da7218_alc_attack_rate =
+ SOC_ENUM_SINGLE(DA7218_ALC_CTRL2, DA7218_ALC_ATTACK_SHIFT,
+ DA7218_ALC_ATTACK_MAX, da7218_alc_attack_rate_txt);
+
+static const char * const da7218_alc_release_rate_txt[] = {
+ "28.66/fs", "57.33/fs", "114.6/fs", "229.3/fs", "458.6/fs", "917.1/fs",
+ "1834/fs", "3668/fs", "7337/fs", "14674/fs", "29348/fs",
+};
+
+static const struct soc_enum da7218_alc_release_rate =
+ SOC_ENUM_SINGLE(DA7218_ALC_CTRL2, DA7218_ALC_RELEASE_SHIFT,
+ DA7218_ALC_RELEASE_MAX, da7218_alc_release_rate_txt);
+
+static const char * const da7218_alc_hold_time_txt[] = {
+ "62/fs", "124/fs", "248/fs", "496/fs", "992/fs", "1984/fs", "3968/fs",
+ "7936/fs", "15872/fs", "31744/fs", "63488/fs", "126976/fs",
+ "253952/fs", "507904/fs", "1015808/fs", "2031616/fs"
+};
+
+static const struct soc_enum da7218_alc_hold_time =
+ SOC_ENUM_SINGLE(DA7218_ALC_CTRL3, DA7218_ALC_HOLD_SHIFT,
+ DA7218_ALC_HOLD_MAX, da7218_alc_hold_time_txt);
+
+static const char * const da7218_alc_anticlip_step_txt[] = {
+ "0.034dB/fs", "0.068dB/fs", "0.136dB/fs", "0.272dB/fs",
+};
+
+static const struct soc_enum da7218_alc_anticlip_step =
+ SOC_ENUM_SINGLE(DA7218_ALC_ANTICLIP_CTRL,
+ DA7218_ALC_ANTICLIP_STEP_SHIFT,
+ DA7218_ALC_ANTICLIP_STEP_MAX,
+ da7218_alc_anticlip_step_txt);
+
+static const char * const da7218_integ_rate_txt[] = {
+ "1/4", "1/16", "1/256", "1/65536"
+};
+
+static const struct soc_enum da7218_integ_attack_rate =
+ SOC_ENUM_SINGLE(DA7218_ENV_TRACK_CTRL, DA7218_INTEG_ATTACK_SHIFT,
+ DA7218_INTEG_MAX, da7218_integ_rate_txt);
+
+static const struct soc_enum da7218_integ_release_rate =
+ SOC_ENUM_SINGLE(DA7218_ENV_TRACK_CTRL, DA7218_INTEG_RELEASE_SHIFT,
+ DA7218_INTEG_MAX, da7218_integ_rate_txt);
+
+/* Input/Output Enums */
+static const char * const da7218_gain_ramp_rate_txt[] = {
+ "Nominal Rate * 8", "Nominal Rate", "Nominal Rate / 8",
+ "Nominal Rate / 16",
+};
+
+static const struct soc_enum da7218_gain_ramp_rate =
+ SOC_ENUM_SINGLE(DA7218_GAIN_RAMP_CTRL, DA7218_GAIN_RAMP_RATE_SHIFT,
+ DA7218_GAIN_RAMP_RATE_MAX, da7218_gain_ramp_rate_txt);
+
+static const char * const da7218_hpf_mode_txt[] = {
+ "Disabled", "Audio", "Voice",
+};
+
+static const unsigned int da7218_hpf_mode_val[] = {
+ DA7218_HPF_DISABLED, DA7218_HPF_AUDIO_EN, DA7218_HPF_VOICE_EN,
+};
+
+static const struct soc_enum da7218_in1_hpf_mode =
+ SOC_VALUE_ENUM_SINGLE(DA7218_IN_1_HPF_FILTER_CTRL,
+ DA7218_HPF_MODE_SHIFT, DA7218_HPF_MODE_MASK,
+ DA7218_HPF_MODE_MAX, da7218_hpf_mode_txt,
+ da7218_hpf_mode_val);
+
+static const struct soc_enum da7218_in2_hpf_mode =
+ SOC_VALUE_ENUM_SINGLE(DA7218_IN_2_HPF_FILTER_CTRL,
+ DA7218_HPF_MODE_SHIFT, DA7218_HPF_MODE_MASK,
+ DA7218_HPF_MODE_MAX, da7218_hpf_mode_txt,
+ da7218_hpf_mode_val);
+
+static const struct soc_enum da7218_out1_hpf_mode =
+ SOC_VALUE_ENUM_SINGLE(DA7218_OUT_1_HPF_FILTER_CTRL,
+ DA7218_HPF_MODE_SHIFT, DA7218_HPF_MODE_MASK,
+ DA7218_HPF_MODE_MAX, da7218_hpf_mode_txt,
+ da7218_hpf_mode_val);
+
+static const char * const da7218_audio_hpf_corner_txt[] = {
+ "2Hz", "4Hz", "8Hz", "16Hz",
+};
+
+static const struct soc_enum da7218_in1_audio_hpf_corner =
+ SOC_ENUM_SINGLE(DA7218_IN_1_HPF_FILTER_CTRL,
+ DA7218_IN_1_AUDIO_HPF_CORNER_SHIFT,
+ DA7218_AUDIO_HPF_CORNER_MAX,
+ da7218_audio_hpf_corner_txt);
+
+static const struct soc_enum da7218_in2_audio_hpf_corner =
+ SOC_ENUM_SINGLE(DA7218_IN_2_HPF_FILTER_CTRL,
+ DA7218_IN_2_AUDIO_HPF_CORNER_SHIFT,
+ DA7218_AUDIO_HPF_CORNER_MAX,
+ da7218_audio_hpf_corner_txt);
+
+static const struct soc_enum da7218_out1_audio_hpf_corner =
+ SOC_ENUM_SINGLE(DA7218_OUT_1_HPF_FILTER_CTRL,
+ DA7218_OUT_1_AUDIO_HPF_CORNER_SHIFT,
+ DA7218_AUDIO_HPF_CORNER_MAX,
+ da7218_audio_hpf_corner_txt);
+
+static const char * const da7218_voice_hpf_corner_txt[] = {
+ "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz",
+};
+
+static const struct soc_enum da7218_in1_voice_hpf_corner =
+ SOC_ENUM_SINGLE(DA7218_IN_1_HPF_FILTER_CTRL,
+ DA7218_IN_1_VOICE_HPF_CORNER_SHIFT,
+ DA7218_VOICE_HPF_CORNER_MAX,
+ da7218_voice_hpf_corner_txt);
+
+static const struct soc_enum da7218_in2_voice_hpf_corner =
+ SOC_ENUM_SINGLE(DA7218_IN_2_HPF_FILTER_CTRL,
+ DA7218_IN_2_VOICE_HPF_CORNER_SHIFT,
+ DA7218_VOICE_HPF_CORNER_MAX,
+ da7218_voice_hpf_corner_txt);
+
+static const struct soc_enum da7218_out1_voice_hpf_corner =
+ SOC_ENUM_SINGLE(DA7218_OUT_1_HPF_FILTER_CTRL,
+ DA7218_OUT_1_VOICE_HPF_CORNER_SHIFT,
+ DA7218_VOICE_HPF_CORNER_MAX,
+ da7218_voice_hpf_corner_txt);
+
+static const char * const da7218_tonegen_dtmf_key_txt[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D",
+ "*", "#"
+};
+
+static const struct soc_enum da7218_tonegen_dtmf_key =
+ SOC_ENUM_SINGLE(DA7218_TONE_GEN_CFG1, DA7218_DTMF_REG_SHIFT,
+ DA7218_DTMF_REG_MAX, da7218_tonegen_dtmf_key_txt);
+
+static const char * const da7218_tonegen_swg_sel_txt[] = {
+ "Sum", "SWG1", "SWG2", "SWG1_1-Cos"
+};
+
+static const struct soc_enum da7218_tonegen_swg_sel =
+ SOC_ENUM_SINGLE(DA7218_TONE_GEN_CFG2, DA7218_SWG_SEL_SHIFT,
+ DA7218_SWG_SEL_MAX, da7218_tonegen_swg_sel_txt);
+
+/* Output Enums */
+static const char * const da7218_dgs_rise_coeff_txt[] = {
+ "1/1", "1/16", "1/64", "1/256", "1/1024", "1/4096", "1/16384",
+};
+
+static const struct soc_enum da7218_dgs_rise_coeff =
+ SOC_ENUM_SINGLE(DA7218_DGS_RISE_FALL, DA7218_DGS_RISE_COEFF_SHIFT,
+ DA7218_DGS_RISE_COEFF_MAX, da7218_dgs_rise_coeff_txt);
+
+static const char * const da7218_dgs_fall_coeff_txt[] = {
+ "1/4", "1/16", "1/64", "1/256", "1/1024", "1/4096", "1/16384", "1/65536",
+};
+
+static const struct soc_enum da7218_dgs_fall_coeff =
+ SOC_ENUM_SINGLE(DA7218_DGS_RISE_FALL, DA7218_DGS_FALL_COEFF_SHIFT,
+ DA7218_DGS_FALL_COEFF_MAX, da7218_dgs_fall_coeff_txt);
+
+static const char * const da7218_dac_ng_setup_time_txt[] = {
+ "256 Samples", "512 Samples", "1024 Samples", "2048 Samples"
+};
+
+static const struct soc_enum da7218_dac_ng_setup_time =
+ SOC_ENUM_SINGLE(DA7218_DAC_NG_SETUP_TIME,
+ DA7218_DAC_NG_SETUP_TIME_SHIFT,
+ DA7218_DAC_NG_SETUP_TIME_MAX,
+ da7218_dac_ng_setup_time_txt);
+
+static const char * const da7218_dac_ng_rampup_txt[] = {
+ "0.22ms/dB", "0.0138ms/dB"
+};
+
+static const struct soc_enum da7218_dac_ng_rampup_rate =
+ SOC_ENUM_SINGLE(DA7218_DAC_NG_SETUP_TIME,
+ DA7218_DAC_NG_RAMPUP_RATE_SHIFT,
+ DA7218_DAC_NG_RAMPUP_RATE_MAX,
+ da7218_dac_ng_rampup_txt);
+
+static const char * const da7218_dac_ng_rampdown_txt[] = {
+ "0.88ms/dB", "14.08ms/dB"
+};
+
+static const struct soc_enum da7218_dac_ng_rampdown_rate =
+ SOC_ENUM_SINGLE(DA7218_DAC_NG_SETUP_TIME,
+ DA7218_DAC_NG_RAMPDN_RATE_SHIFT,
+ DA7218_DAC_NG_RAMPDN_RATE_MAX,
+ da7218_dac_ng_rampdown_txt);
+
+static const char * const da7218_cp_mchange_txt[] = {
+ "Largest Volume", "DAC Volume", "Signal Magnitude"
+};
+
+static const unsigned int da7218_cp_mchange_val[] = {
+ DA7218_CP_MCHANGE_LARGEST_VOL, DA7218_CP_MCHANGE_DAC_VOL,
+ DA7218_CP_MCHANGE_SIG_MAG
+};
+
+static const struct soc_enum da7218_cp_mchange =
+ SOC_VALUE_ENUM_SINGLE(DA7218_CP_CTRL, DA7218_CP_MCHANGE_SHIFT,
+ DA7218_CP_MCHANGE_REL_MASK, DA7218_CP_MCHANGE_MAX,
+ da7218_cp_mchange_txt, da7218_cp_mchange_val);
+
+static const char * const da7218_cp_fcontrol_txt[] = {
+ "1MHz", "500KHz", "250KHz", "125KHz", "63KHz", "0KHz"
+};
+
+static const struct soc_enum da7218_cp_fcontrol =
+ SOC_ENUM_SINGLE(DA7218_CP_DELAY, DA7218_CP_FCONTROL_SHIFT,
+ DA7218_CP_FCONTROL_MAX, da7218_cp_fcontrol_txt);
+
+static const char * const da7218_cp_tau_delay_txt[] = {
+ "0ms", "2ms", "4ms", "16ms", "64ms", "128ms", "256ms", "512ms"
+};
+
+static const struct soc_enum da7218_cp_tau_delay =
+ SOC_ENUM_SINGLE(DA7218_CP_DELAY, DA7218_CP_TAU_DELAY_SHIFT,
+ DA7218_CP_TAU_DELAY_MAX, da7218_cp_tau_delay_txt);
+
+/*
+ * Control Functions
+ */
+
+/* ALC */
+static void da7218_alc_calib(struct snd_soc_codec *codec)
+{
+ u8 mic_1_ctrl, mic_2_ctrl;
+ u8 mixin_1_ctrl, mixin_2_ctrl;
+ u8 in_1l_filt_ctrl, in_1r_filt_ctrl, in_2l_filt_ctrl, in_2r_filt_ctrl;
+ u8 in_1_hpf_ctrl, in_2_hpf_ctrl;
+ u8 calib_ctrl;
+ int i = 0;
+ bool calibrated = false;
+
+ /* Save current state of MIC control registers */
+ mic_1_ctrl = snd_soc_read(codec, DA7218_MIC_1_CTRL);
+ mic_2_ctrl = snd_soc_read(codec, DA7218_MIC_2_CTRL);
+
+ /* Save current state of input mixer control registers */
+ mixin_1_ctrl = snd_soc_read(codec, DA7218_MIXIN_1_CTRL);
+ mixin_2_ctrl = snd_soc_read(codec, DA7218_MIXIN_2_CTRL);
+
+ /* Save current state of input filter control registers */
+ in_1l_filt_ctrl = snd_soc_read(codec, DA7218_IN_1L_FILTER_CTRL);
+ in_1r_filt_ctrl = snd_soc_read(codec, DA7218_IN_1R_FILTER_CTRL);
+ in_2l_filt_ctrl = snd_soc_read(codec, DA7218_IN_2L_FILTER_CTRL);
+ in_2r_filt_ctrl = snd_soc_read(codec, DA7218_IN_2R_FILTER_CTRL);
+
+ /* Save current state of input HPF control registers */
+ in_1_hpf_ctrl = snd_soc_read(codec, DA7218_IN_1_HPF_FILTER_CTRL);
+ in_2_hpf_ctrl = snd_soc_read(codec, DA7218_IN_2_HPF_FILTER_CTRL);
+
+ /* Enable then Mute MIC PGAs */
+ snd_soc_update_bits(codec, DA7218_MIC_1_CTRL, DA7218_MIC_1_AMP_EN_MASK,
+ DA7218_MIC_1_AMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_MIC_2_CTRL, DA7218_MIC_2_AMP_EN_MASK,
+ DA7218_MIC_2_AMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_MIC_1_CTRL,
+ DA7218_MIC_1_AMP_MUTE_EN_MASK,
+ DA7218_MIC_1_AMP_MUTE_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_MIC_2_CTRL,
+ DA7218_MIC_2_AMP_MUTE_EN_MASK,
+ DA7218_MIC_2_AMP_MUTE_EN_MASK);
+
+ /* Enable input mixers unmuted */
+ snd_soc_update_bits(codec, DA7218_MIXIN_1_CTRL,
+ DA7218_MIXIN_1_AMP_EN_MASK |
+ DA7218_MIXIN_1_AMP_MUTE_EN_MASK,
+ DA7218_MIXIN_1_AMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_MIXIN_2_CTRL,
+ DA7218_MIXIN_2_AMP_EN_MASK |
+ DA7218_MIXIN_2_AMP_MUTE_EN_MASK,
+ DA7218_MIXIN_2_AMP_EN_MASK);
+
+ /* Enable input filters unmuted */
+ snd_soc_update_bits(codec, DA7218_IN_1L_FILTER_CTRL,
+ DA7218_IN_1L_FILTER_EN_MASK |
+ DA7218_IN_1L_MUTE_EN_MASK,
+ DA7218_IN_1L_FILTER_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_IN_1R_FILTER_CTRL,
+ DA7218_IN_1R_FILTER_EN_MASK |
+ DA7218_IN_1R_MUTE_EN_MASK,
+ DA7218_IN_1R_FILTER_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_IN_2L_FILTER_CTRL,
+ DA7218_IN_2L_FILTER_EN_MASK |
+ DA7218_IN_2L_MUTE_EN_MASK,
+ DA7218_IN_2L_FILTER_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_IN_2R_FILTER_CTRL,
+ DA7218_IN_2R_FILTER_EN_MASK |
+ DA7218_IN_2R_MUTE_EN_MASK,
+ DA7218_IN_2R_FILTER_EN_MASK);
+
+ /*
+ * Make sure input HPFs voice mode is disabled, otherwise for sampling
+ * rates above 32KHz the ADC signals will be stopped and will cause
+ * calibration to lock up.
+ */
+ snd_soc_update_bits(codec, DA7218_IN_1_HPF_FILTER_CTRL,
+ DA7218_IN_1_VOICE_EN_MASK, 0);
+ snd_soc_update_bits(codec, DA7218_IN_2_HPF_FILTER_CTRL,
+ DA7218_IN_2_VOICE_EN_MASK, 0);
+
+ /* Perform auto calibration */
+ snd_soc_update_bits(codec, DA7218_CALIB_CTRL, DA7218_CALIB_AUTO_EN_MASK,
+ DA7218_CALIB_AUTO_EN_MASK);
+ do {
+ calib_ctrl = snd_soc_read(codec, DA7218_CALIB_CTRL);
+ if (calib_ctrl & DA7218_CALIB_AUTO_EN_MASK) {
+ ++i;
+ usleep_range(DA7218_ALC_CALIB_DELAY_MIN,
+ DA7218_ALC_CALIB_DELAY_MAX);
+ } else {
+ calibrated = true;
+ }
+
+ } while ((i < DA7218_ALC_CALIB_MAX_TRIES) && (!calibrated));
+
+ /* If auto calibration fails, disable DC offset, hybrid ALC */
+ if ((!calibrated) || (calib_ctrl & DA7218_CALIB_OVERFLOW_MASK)) {
+ dev_warn(codec->dev,
+ "ALC auto calibration failed - %s\n",
+ (calibrated) ? "overflow" : "timeout");
+ snd_soc_update_bits(codec, DA7218_CALIB_CTRL,
+ DA7218_CALIB_OFFSET_EN_MASK, 0);
+ snd_soc_update_bits(codec, DA7218_ALC_CTRL1,
+ DA7218_ALC_SYNC_MODE_MASK, 0);
+
+ } else {
+ /* Enable DC offset cancellation */
+ snd_soc_update_bits(codec, DA7218_CALIB_CTRL,
+ DA7218_CALIB_OFFSET_EN_MASK,
+ DA7218_CALIB_OFFSET_EN_MASK);
+
+ /* Enable ALC hybrid mode */
+ snd_soc_update_bits(codec, DA7218_ALC_CTRL1,
+ DA7218_ALC_SYNC_MODE_MASK,
+ DA7218_ALC_SYNC_MODE_CH1 |
+ DA7218_ALC_SYNC_MODE_CH2);
+ }
+
+ /* Restore input HPF control registers to original states */
+ snd_soc_write(codec, DA7218_IN_1_HPF_FILTER_CTRL, in_1_hpf_ctrl);
+ snd_soc_write(codec, DA7218_IN_2_HPF_FILTER_CTRL, in_2_hpf_ctrl);
+
+ /* Restore input filter control registers to original states */
+ snd_soc_write(codec, DA7218_IN_1L_FILTER_CTRL, in_1l_filt_ctrl);
+ snd_soc_write(codec, DA7218_IN_1R_FILTER_CTRL, in_1r_filt_ctrl);
+ snd_soc_write(codec, DA7218_IN_2L_FILTER_CTRL, in_2l_filt_ctrl);
+ snd_soc_write(codec, DA7218_IN_2R_FILTER_CTRL, in_2r_filt_ctrl);
+
+ /* Restore input mixer control registers to original state */
+ snd_soc_write(codec, DA7218_MIXIN_1_CTRL, mixin_1_ctrl);
+ snd_soc_write(codec, DA7218_MIXIN_2_CTRL, mixin_2_ctrl);
+
+ /* Restore MIC control registers to original states */
+ snd_soc_write(codec, DA7218_MIC_1_CTRL, mic_1_ctrl);
+ snd_soc_write(codec, DA7218_MIC_2_CTRL, mic_2_ctrl);
+}
+
+static int da7218_mixin_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
+
+ /*
+ * If ALC in operation and value of control has been updated,
+ * make sure calibrated offsets are updated.
+ */
+ if ((ret == 1) && (da7218->alc_en))
+ da7218_alc_calib(codec);
+
+ return ret;
+}
+
+static int da7218_alc_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *) kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ unsigned int lvalue = ucontrol->value.integer.value[0];
+ unsigned int rvalue = ucontrol->value.integer.value[1];
+ unsigned int lshift = mc->shift;
+ unsigned int rshift = mc->rshift;
+ unsigned int mask = (mc->max << lshift) | (mc->max << rshift);
+
+ /* Force ALC offset calibration if enabling ALC */
+ if ((lvalue || rvalue) && (!da7218->alc_en))
+ da7218_alc_calib(codec);
+
+ /* Update bits to detail which channels are enabled/disabled */
+ da7218->alc_en &= ~mask;
+ da7218->alc_en |= (lvalue << lshift) | (rvalue << rshift);
+
+ return snd_soc_put_volsw(kcontrol, ucontrol);
+}
+
+/* ToneGen */
+static int da7218_tonegen_freq_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ struct soc_mixer_control *mixer_ctrl =
+ (struct soc_mixer_control *) kcontrol->private_value;
+ unsigned int reg = mixer_ctrl->reg;
+ u16 val;
+ int ret;
+
+ /*
+ * Frequency value spans two 8-bit registers, lower then upper byte.
+ * Therefore we need to convert to host endianness here.
+ */
+ ret = regmap_raw_read(da7218->regmap, reg, &val, 2);
+ if (ret)
+ return ret;
+
+ ucontrol->value.integer.value[0] = le16_to_cpu(val);
+
+ return 0;
+}
+
+static int da7218_tonegen_freq_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ struct soc_mixer_control *mixer_ctrl =
+ (struct soc_mixer_control *) kcontrol->private_value;
+ unsigned int reg = mixer_ctrl->reg;
+ u16 val;
+
+ /*
+ * Frequency value spans two 8-bit registers, lower then upper byte.
+ * Therefore we need to convert to little endian here to align with
+ * HW registers.
+ */
+ val = cpu_to_le16(ucontrol->value.integer.value[0]);
+
+ return regmap_raw_write(da7218->regmap, reg, &val, 2);
+}
+
+static int da7218_mic_lvl_det_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ struct soc_mixer_control *mixer_ctrl =
+ (struct soc_mixer_control *) kcontrol->private_value;
+ unsigned int lvalue = ucontrol->value.integer.value[0];
+ unsigned int rvalue = ucontrol->value.integer.value[1];
+ unsigned int lshift = mixer_ctrl->shift;
+ unsigned int rshift = mixer_ctrl->rshift;
+ unsigned int mask = (mixer_ctrl->max << lshift) |
+ (mixer_ctrl->max << rshift);
+ da7218->mic_lvl_det_en &= ~mask;
+ da7218->mic_lvl_det_en |= (lvalue << lshift) | (rvalue << rshift);
+
+ /*
+ * Here we only enable the feature on paths which are already
+ * powered. If a channel is enabled here for level detect, but that path
+ * isn't powered, then the channel will actually be enabled when we do
+ * power the path (IN_FILTER widget events). This handling avoids
+ * unwanted level detect events.
+ */
+ return snd_soc_write(codec, mixer_ctrl->reg,
+ (da7218->in_filt_en & da7218->mic_lvl_det_en));
+}
+
+static int da7218_mic_lvl_det_sw_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ struct soc_mixer_control *mixer_ctrl =
+ (struct soc_mixer_control *) kcontrol->private_value;
+ unsigned int lshift = mixer_ctrl->shift;
+ unsigned int rshift = mixer_ctrl->rshift;
+ unsigned int lmask = (mixer_ctrl->max << lshift);
+ unsigned int rmask = (mixer_ctrl->max << rshift);
+
+ ucontrol->value.integer.value[0] =
+ (da7218->mic_lvl_det_en & lmask) >> lshift;
+ ucontrol->value.integer.value[1] =
+ (da7218->mic_lvl_det_en & rmask) >> rshift;
+
+ return 0;
+}
+
+static int da7218_biquad_coeff_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+
+ /* Determine which BiQuads we're setting based on size of config data */
+ switch (bytes_ext->max) {
+ case DA7218_OUT_1_BIQ_5STAGE_CFG_SIZE:
+ memcpy(ucontrol->value.bytes.data, da7218->biq_5stage_coeff,
+ bytes_ext->max);
+ break;
+ case DA7218_SIDETONE_BIQ_3STAGE_CFG_SIZE:
+ memcpy(ucontrol->value.bytes.data, da7218->stbiq_3stage_coeff,
+ bytes_ext->max);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int da7218_biquad_coeff_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ u8 reg, out_filt1l;
+ u8 cfg[DA7218_BIQ_CFG_SIZE];
+ int i;
+
+ /*
+ * Determine which BiQuads we're setting based on size of config data,
+ * and stored the data for use by get function.
+ */
+ switch (bytes_ext->max) {
+ case DA7218_OUT_1_BIQ_5STAGE_CFG_SIZE:
+ reg = DA7218_OUT_1_BIQ_5STAGE_DATA;
+ memcpy(da7218->biq_5stage_coeff, ucontrol->value.bytes.data,
+ bytes_ext->max);
+ break;
+ case DA7218_SIDETONE_BIQ_3STAGE_CFG_SIZE:
+ reg = DA7218_SIDETONE_BIQ_3STAGE_DATA;
+ memcpy(da7218->stbiq_3stage_coeff, ucontrol->value.bytes.data,
+ bytes_ext->max);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Make sure at least out filter1 enabled to allow programming */
+ out_filt1l = snd_soc_read(codec, DA7218_OUT_1L_FILTER_CTRL);
+ snd_soc_write(codec, DA7218_OUT_1L_FILTER_CTRL,
+ out_filt1l | DA7218_OUT_1L_FILTER_EN_MASK);
+
+ for (i = 0; i < bytes_ext->max; ++i) {
+ cfg[DA7218_BIQ_CFG_DATA] = ucontrol->value.bytes.data[i];
+ cfg[DA7218_BIQ_CFG_ADDR] = i;
+ regmap_raw_write(da7218->regmap, reg, cfg, DA7218_BIQ_CFG_SIZE);
+ }
+
+ /* Restore filter to previous setting */
+ snd_soc_write(codec, DA7218_OUT_1L_FILTER_CTRL, out_filt1l);
+
+ return 0;
+}
+
+
+/*
+ * KControls
+ */
+
+static const struct snd_kcontrol_new da7218_snd_controls[] = {
+ /* Mics */
+ SOC_SINGLE_TLV("Mic1 Volume", DA7218_MIC_1_GAIN,
+ DA7218_MIC_1_AMP_GAIN_SHIFT, DA7218_MIC_AMP_GAIN_MAX,
+ DA7218_NO_INVERT, da7218_mic_gain_tlv),
+ SOC_SINGLE("Mic1 Switch", DA7218_MIC_1_CTRL,
+ DA7218_MIC_1_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+ SOC_SINGLE_TLV("Mic2 Volume", DA7218_MIC_2_GAIN,
+ DA7218_MIC_2_AMP_GAIN_SHIFT, DA7218_MIC_AMP_GAIN_MAX,
+ DA7218_NO_INVERT, da7218_mic_gain_tlv),
+ SOC_SINGLE("Mic2 Switch", DA7218_MIC_2_CTRL,
+ DA7218_MIC_2_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+
+ /* Mixer Input */
+ SOC_SINGLE_EXT_TLV("Mixin1 Volume", DA7218_MIXIN_1_GAIN,
+ DA7218_MIXIN_1_AMP_GAIN_SHIFT,
+ DA7218_MIXIN_AMP_GAIN_MAX, DA7218_NO_INVERT,
+ snd_soc_get_volsw, da7218_mixin_gain_put,
+ da7218_mixin_gain_tlv),
+ SOC_SINGLE("Mixin1 Switch", DA7218_MIXIN_1_CTRL,
+ DA7218_MIXIN_1_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+ SOC_SINGLE("Mixin1 Gain Ramp Switch", DA7218_MIXIN_1_CTRL,
+ DA7218_MIXIN_1_AMP_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("Mixin1 ZC Gain Switch", DA7218_MIXIN_1_CTRL,
+ DA7218_MIXIN_1_AMP_ZC_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE_EXT_TLV("Mixin2 Volume", DA7218_MIXIN_2_GAIN,
+ DA7218_MIXIN_2_AMP_GAIN_SHIFT,
+ DA7218_MIXIN_AMP_GAIN_MAX, DA7218_NO_INVERT,
+ snd_soc_get_volsw, da7218_mixin_gain_put,
+ da7218_mixin_gain_tlv),
+ SOC_SINGLE("Mixin2 Switch", DA7218_MIXIN_2_CTRL,
+ DA7218_MIXIN_2_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+ SOC_SINGLE("Mixin2 Gain Ramp Switch", DA7218_MIXIN_2_CTRL,
+ DA7218_MIXIN_2_AMP_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("Mixin2 ZC Gain Switch", DA7218_MIXIN_2_CTRL,
+ DA7218_MIXIN_2_AMP_ZC_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+
+ /* ADCs */
+ SOC_SINGLE("ADC1 AAF Switch", DA7218_ADC_1_CTRL,
+ DA7218_ADC_1_AAF_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("ADC2 AAF Switch", DA7218_ADC_2_CTRL,
+ DA7218_ADC_2_AAF_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("ADC LP Mode Switch", DA7218_ADC_MODE,
+ DA7218_ADC_LP_MODE_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+
+ /* Input Filters */
+ SOC_SINGLE_TLV("In Filter1L Volume", DA7218_IN_1L_GAIN,
+ DA7218_IN_1L_DIGITAL_GAIN_SHIFT,
+ DA7218_IN_DIGITAL_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_in_dig_gain_tlv),
+ SOC_SINGLE("In Filter1L Switch", DA7218_IN_1L_FILTER_CTRL,
+ DA7218_IN_1L_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+ SOC_SINGLE("In Filter1L Gain Ramp Switch", DA7218_IN_1L_FILTER_CTRL,
+ DA7218_IN_1L_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE_TLV("In Filter1R Volume", DA7218_IN_1R_GAIN,
+ DA7218_IN_1R_DIGITAL_GAIN_SHIFT,
+ DA7218_IN_DIGITAL_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_in_dig_gain_tlv),
+ SOC_SINGLE("In Filter1R Switch", DA7218_IN_1R_FILTER_CTRL,
+ DA7218_IN_1R_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+ SOC_SINGLE("In Filter1R Gain Ramp Switch",
+ DA7218_IN_1R_FILTER_CTRL, DA7218_IN_1R_RAMP_EN_SHIFT,
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT),
+ SOC_SINGLE_TLV("In Filter2L Volume", DA7218_IN_2L_GAIN,
+ DA7218_IN_2L_DIGITAL_GAIN_SHIFT,
+ DA7218_IN_DIGITAL_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_in_dig_gain_tlv),
+ SOC_SINGLE("In Filter2L Switch", DA7218_IN_2L_FILTER_CTRL,
+ DA7218_IN_2L_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+ SOC_SINGLE("In Filter2L Gain Ramp Switch", DA7218_IN_2L_FILTER_CTRL,
+ DA7218_IN_2L_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE_TLV("In Filter2R Volume", DA7218_IN_2R_GAIN,
+ DA7218_IN_2R_DIGITAL_GAIN_SHIFT,
+ DA7218_IN_DIGITAL_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_in_dig_gain_tlv),
+ SOC_SINGLE("In Filter2R Switch", DA7218_IN_2R_FILTER_CTRL,
+ DA7218_IN_2R_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+ SOC_SINGLE("In Filter2R Gain Ramp Switch",
+ DA7218_IN_2R_FILTER_CTRL, DA7218_IN_2R_RAMP_EN_SHIFT,
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT),
+
+ /* AGS */
+ SOC_SINGLE_TLV("AGS Trigger", DA7218_AGS_TRIGGER,
+ DA7218_AGS_TRIGGER_SHIFT, DA7218_AGS_TRIGGER_MAX,
+ DA7218_INVERT, da7218_ags_trigger_tlv),
+ SOC_SINGLE_TLV("AGS Max Attenuation", DA7218_AGS_ATT_MAX,
+ DA7218_AGS_ATT_MAX_SHIFT, DA7218_AGS_ATT_MAX_MAX,
+ DA7218_NO_INVERT, da7218_ags_att_max_tlv),
+ SOC_SINGLE("AGS Anticlip Switch", DA7218_AGS_ANTICLIP_CTRL,
+ DA7218_AGS_ANTICLIP_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("AGS Channel1 Switch", DA7218_AGS_ENABLE,
+ DA7218_AGS_ENABLE_CHAN1_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("AGS Channel2 Switch", DA7218_AGS_ENABLE,
+ DA7218_AGS_ENABLE_CHAN2_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+
+ /* ALC */
+ SOC_ENUM("ALC Attack Rate", da7218_alc_attack_rate),
+ SOC_ENUM("ALC Release Rate", da7218_alc_release_rate),
+ SOC_ENUM("ALC Hold Time", da7218_alc_hold_time),
+ SOC_SINGLE_TLV("ALC Noise Threshold", DA7218_ALC_NOISE,
+ DA7218_ALC_NOISE_SHIFT, DA7218_ALC_THRESHOLD_MAX,
+ DA7218_INVERT, da7218_alc_threshold_tlv),
+ SOC_SINGLE_TLV("ALC Min Threshold", DA7218_ALC_TARGET_MIN,
+ DA7218_ALC_THRESHOLD_MIN_SHIFT, DA7218_ALC_THRESHOLD_MAX,
+ DA7218_INVERT, da7218_alc_threshold_tlv),
+ SOC_SINGLE_TLV("ALC Max Threshold", DA7218_ALC_TARGET_MAX,
+ DA7218_ALC_THRESHOLD_MAX_SHIFT, DA7218_ALC_THRESHOLD_MAX,
+ DA7218_INVERT, da7218_alc_threshold_tlv),
+ SOC_SINGLE_TLV("ALC Max Attenuation", DA7218_ALC_GAIN_LIMITS,
+ DA7218_ALC_ATTEN_MAX_SHIFT, DA7218_ALC_ATTEN_GAIN_MAX,
+ DA7218_NO_INVERT, da7218_alc_gain_tlv),
+ SOC_SINGLE_TLV("ALC Max Gain", DA7218_ALC_GAIN_LIMITS,
+ DA7218_ALC_GAIN_MAX_SHIFT, DA7218_ALC_ATTEN_GAIN_MAX,
+ DA7218_NO_INVERT, da7218_alc_gain_tlv),
+ SOC_SINGLE_RANGE_TLV("ALC Min Analog Gain", DA7218_ALC_ANA_GAIN_LIMITS,
+ DA7218_ALC_ANA_GAIN_MIN_SHIFT,
+ DA7218_ALC_ANA_GAIN_MIN, DA7218_ALC_ANA_GAIN_MAX,
+ DA7218_NO_INVERT, da7218_alc_ana_gain_tlv),
+ SOC_SINGLE_RANGE_TLV("ALC Max Analog Gain", DA7218_ALC_ANA_GAIN_LIMITS,
+ DA7218_ALC_ANA_GAIN_MAX_SHIFT,
+ DA7218_ALC_ANA_GAIN_MIN, DA7218_ALC_ANA_GAIN_MAX,
+ DA7218_NO_INVERT, da7218_alc_ana_gain_tlv),
+ SOC_ENUM("ALC Anticlip Step", da7218_alc_anticlip_step),
+ SOC_SINGLE("ALC Anticlip Switch", DA7218_ALC_ANTICLIP_CTRL,
+ DA7218_ALC_ANTICLIP_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_DOUBLE_EXT("ALC Channel1 Switch", DA7218_ALC_CTRL1,
+ DA7218_ALC_CHAN1_L_EN_SHIFT, DA7218_ALC_CHAN1_R_EN_SHIFT,
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT,
+ snd_soc_get_volsw, da7218_alc_sw_put),
+ SOC_DOUBLE_EXT("ALC Channel2 Switch", DA7218_ALC_CTRL1,
+ DA7218_ALC_CHAN2_L_EN_SHIFT, DA7218_ALC_CHAN2_R_EN_SHIFT,
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT,
+ snd_soc_get_volsw, da7218_alc_sw_put),
+
+ /* Envelope Tracking */
+ SOC_ENUM("Envelope Tracking Attack Rate", da7218_integ_attack_rate),
+ SOC_ENUM("Envelope Tracking Release Rate", da7218_integ_release_rate),
+
+ /* Input High-Pass Filters */
+ SOC_ENUM("In Filter1 HPF Mode", da7218_in1_hpf_mode),
+ SOC_ENUM("In Filter1 HPF Corner Audio", da7218_in1_audio_hpf_corner),
+ SOC_ENUM("In Filter1 HPF Corner Voice", da7218_in1_voice_hpf_corner),
+ SOC_ENUM("In Filter2 HPF Mode", da7218_in2_hpf_mode),
+ SOC_ENUM("In Filter2 HPF Corner Audio", da7218_in2_audio_hpf_corner),
+ SOC_ENUM("In Filter2 HPF Corner Voice", da7218_in2_voice_hpf_corner),
+
+ /* Mic Level Detect */
+ SOC_DOUBLE_EXT("Mic Level Detect Channel1 Switch", DA7218_LVL_DET_CTRL,
+ DA7218_LVL_DET_EN_CHAN1L_SHIFT,
+ DA7218_LVL_DET_EN_CHAN1R_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT, da7218_mic_lvl_det_sw_get,
+ da7218_mic_lvl_det_sw_put),
+ SOC_DOUBLE_EXT("Mic Level Detect Channel2 Switch", DA7218_LVL_DET_CTRL,
+ DA7218_LVL_DET_EN_CHAN2L_SHIFT,
+ DA7218_LVL_DET_EN_CHAN2R_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT, da7218_mic_lvl_det_sw_get,
+ da7218_mic_lvl_det_sw_put),
+ SOC_SINGLE("Mic Level Detect Level", DA7218_LVL_DET_LEVEL,
+ DA7218_LVL_DET_LEVEL_SHIFT, DA7218_LVL_DET_LEVEL_MAX,
+ DA7218_NO_INVERT),
+
+ /* Digital Mixer (Input) */
+ SOC_SINGLE_TLV("DMix In Filter1L Out1 DAIL Volume",
+ DA7218_DMIX_OUTDAI_1L_INFILT_1L_GAIN,
+ DA7218_OUTDAI_1L_INFILT_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter1L Out1 DAIR Volume",
+ DA7218_DMIX_OUTDAI_1R_INFILT_1L_GAIN,
+ DA7218_OUTDAI_1R_INFILT_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter1L Out2 DAIL Volume",
+ DA7218_DMIX_OUTDAI_2L_INFILT_1L_GAIN,
+ DA7218_OUTDAI_2L_INFILT_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter1L Out2 DAIR Volume",
+ DA7218_DMIX_OUTDAI_2R_INFILT_1L_GAIN,
+ DA7218_OUTDAI_2R_INFILT_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In Filter1R Out1 DAIL Volume",
+ DA7218_DMIX_OUTDAI_1L_INFILT_1R_GAIN,
+ DA7218_OUTDAI_1L_INFILT_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter1R Out1 DAIR Volume",
+ DA7218_DMIX_OUTDAI_1R_INFILT_1R_GAIN,
+ DA7218_OUTDAI_1R_INFILT_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter1R Out2 DAIL Volume",
+ DA7218_DMIX_OUTDAI_2L_INFILT_1R_GAIN,
+ DA7218_OUTDAI_2L_INFILT_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter1R Out2 DAIR Volume",
+ DA7218_DMIX_OUTDAI_2R_INFILT_1R_GAIN,
+ DA7218_OUTDAI_2R_INFILT_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In Filter2L Out1 DAIL Volume",
+ DA7218_DMIX_OUTDAI_1L_INFILT_2L_GAIN,
+ DA7218_OUTDAI_1L_INFILT_2L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter2L Out1 DAIR Volume",
+ DA7218_DMIX_OUTDAI_1R_INFILT_2L_GAIN,
+ DA7218_OUTDAI_1R_INFILT_2L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter2L Out2 DAIL Volume",
+ DA7218_DMIX_OUTDAI_2L_INFILT_2L_GAIN,
+ DA7218_OUTDAI_2L_INFILT_2L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter2L Out2 DAIR Volume",
+ DA7218_DMIX_OUTDAI_2R_INFILT_2L_GAIN,
+ DA7218_OUTDAI_2R_INFILT_2L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In Filter2R Out1 DAIL Volume",
+ DA7218_DMIX_OUTDAI_1L_INFILT_2R_GAIN,
+ DA7218_OUTDAI_1L_INFILT_2R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter2R Out1 DAIR Volume",
+ DA7218_DMIX_OUTDAI_1R_INFILT_2R_GAIN,
+ DA7218_OUTDAI_1R_INFILT_2R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter2R Out2 DAIL Volume",
+ DA7218_DMIX_OUTDAI_2L_INFILT_2R_GAIN,
+ DA7218_OUTDAI_2L_INFILT_2R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter2R Out2 DAIR Volume",
+ DA7218_DMIX_OUTDAI_2R_INFILT_2R_GAIN,
+ DA7218_OUTDAI_2R_INFILT_2R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix ToneGen Out1 DAIL Volume",
+ DA7218_DMIX_OUTDAI_1L_TONEGEN_GAIN,
+ DA7218_OUTDAI_1L_TONEGEN_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix ToneGen Out1 DAIR Volume",
+ DA7218_DMIX_OUTDAI_1R_TONEGEN_GAIN,
+ DA7218_OUTDAI_1R_TONEGEN_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix ToneGen Out2 DAIL Volume",
+ DA7218_DMIX_OUTDAI_2L_TONEGEN_GAIN,
+ DA7218_OUTDAI_2L_TONEGEN_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix ToneGen Out2 DAIR Volume",
+ DA7218_DMIX_OUTDAI_2R_TONEGEN_GAIN,
+ DA7218_OUTDAI_2R_TONEGEN_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In DAIL Out1 DAIL Volume",
+ DA7218_DMIX_OUTDAI_1L_INDAI_1L_GAIN,
+ DA7218_OUTDAI_1L_INDAI_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In DAIL Out1 DAIR Volume",
+ DA7218_DMIX_OUTDAI_1R_INDAI_1L_GAIN,
+ DA7218_OUTDAI_1R_INDAI_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In DAIL Out2 DAIL Volume",
+ DA7218_DMIX_OUTDAI_2L_INDAI_1L_GAIN,
+ DA7218_OUTDAI_2L_INDAI_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In DAIL Out2 DAIR Volume",
+ DA7218_DMIX_OUTDAI_2R_INDAI_1L_GAIN,
+ DA7218_OUTDAI_2R_INDAI_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In DAIR Out1 DAIL Volume",
+ DA7218_DMIX_OUTDAI_1L_INDAI_1R_GAIN,
+ DA7218_OUTDAI_1L_INDAI_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In DAIR Out1 DAIR Volume",
+ DA7218_DMIX_OUTDAI_1R_INDAI_1R_GAIN,
+ DA7218_OUTDAI_1R_INDAI_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In DAIR Out2 DAIL Volume",
+ DA7218_DMIX_OUTDAI_2L_INDAI_1R_GAIN,
+ DA7218_OUTDAI_2L_INDAI_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In DAIR Out2 DAIR Volume",
+ DA7218_DMIX_OUTDAI_2R_INDAI_1R_GAIN,
+ DA7218_OUTDAI_2R_INDAI_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ /* Digital Mixer (Output) */
+ SOC_SINGLE_TLV("DMix In Filter1L Out FilterL Volume",
+ DA7218_DMIX_OUTFILT_1L_INFILT_1L_GAIN,
+ DA7218_OUTFILT_1L_INFILT_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter1L Out FilterR Volume",
+ DA7218_DMIX_OUTFILT_1R_INFILT_1L_GAIN,
+ DA7218_OUTFILT_1R_INFILT_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In Filter1R Out FilterL Volume",
+ DA7218_DMIX_OUTFILT_1L_INFILT_1R_GAIN,
+ DA7218_OUTFILT_1L_INFILT_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter1R Out FilterR Volume",
+ DA7218_DMIX_OUTFILT_1R_INFILT_1R_GAIN,
+ DA7218_OUTFILT_1R_INFILT_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In Filter2L Out FilterL Volume",
+ DA7218_DMIX_OUTFILT_1L_INFILT_2L_GAIN,
+ DA7218_OUTFILT_1L_INFILT_2L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter2L Out FilterR Volume",
+ DA7218_DMIX_OUTFILT_1R_INFILT_2L_GAIN,
+ DA7218_OUTFILT_1R_INFILT_2L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In Filter2R Out FilterL Volume",
+ DA7218_DMIX_OUTFILT_1L_INFILT_2R_GAIN,
+ DA7218_OUTFILT_1L_INFILT_2R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In Filter2R Out FilterR Volume",
+ DA7218_DMIX_OUTFILT_1R_INFILT_2R_GAIN,
+ DA7218_OUTFILT_1R_INFILT_2R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix ToneGen Out FilterL Volume",
+ DA7218_DMIX_OUTFILT_1L_TONEGEN_GAIN,
+ DA7218_OUTFILT_1L_TONEGEN_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix ToneGen Out FilterR Volume",
+ DA7218_DMIX_OUTFILT_1R_TONEGEN_GAIN,
+ DA7218_OUTFILT_1R_TONEGEN_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In DAIL Out FilterL Volume",
+ DA7218_DMIX_OUTFILT_1L_INDAI_1L_GAIN,
+ DA7218_OUTFILT_1L_INDAI_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In DAIL Out FilterR Volume",
+ DA7218_DMIX_OUTFILT_1R_INDAI_1L_GAIN,
+ DA7218_OUTFILT_1R_INDAI_1L_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ SOC_SINGLE_TLV("DMix In DAIR Out FilterL Volume",
+ DA7218_DMIX_OUTFILT_1L_INDAI_1R_GAIN,
+ DA7218_OUTFILT_1L_INDAI_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+ SOC_SINGLE_TLV("DMix In DAIR Out FilterR Volume",
+ DA7218_DMIX_OUTFILT_1R_INDAI_1R_GAIN,
+ DA7218_OUTFILT_1R_INDAI_1R_GAIN_SHIFT,
+ DA7218_DMIX_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_dmix_gain_tlv),
+
+ /* Sidetone Filter */
+ SND_SOC_BYTES_EXT("Sidetone BiQuad Coefficients",
+ DA7218_SIDETONE_BIQ_3STAGE_CFG_SIZE,
+ da7218_biquad_coeff_get, da7218_biquad_coeff_put),
+ SOC_SINGLE_TLV("Sidetone Volume", DA7218_SIDETONE_GAIN,
+ DA7218_SIDETONE_GAIN_SHIFT, DA7218_DMIX_GAIN_MAX,
+ DA7218_NO_INVERT, da7218_dmix_gain_tlv),
+ SOC_SINGLE("Sidetone Switch", DA7218_SIDETONE_CTRL,
+ DA7218_SIDETONE_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+
+ /* Tone Generator */
+ SOC_ENUM("ToneGen DTMF Key", da7218_tonegen_dtmf_key),
+ SOC_SINGLE("ToneGen DTMF Switch", DA7218_TONE_GEN_CFG1,
+ DA7218_DTMF_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_ENUM("ToneGen Sinewave Gen Type", da7218_tonegen_swg_sel),
+ SOC_SINGLE_EXT("ToneGen Sinewave1 Freq", DA7218_TONE_GEN_FREQ1_L,
+ DA7218_FREQ1_L_SHIFT, DA7218_FREQ_MAX, DA7218_NO_INVERT,
+ da7218_tonegen_freq_get, da7218_tonegen_freq_put),
+ SOC_SINGLE_EXT("ToneGen Sinewave2 Freq", DA7218_TONE_GEN_FREQ2_L,
+ DA7218_FREQ2_L_SHIFT, DA7218_FREQ_MAX, DA7218_NO_INVERT,
+ da7218_tonegen_freq_get, da7218_tonegen_freq_put),
+ SOC_SINGLE("ToneGen On Time", DA7218_TONE_GEN_ON_PER,
+ DA7218_BEEP_ON_PER_SHIFT, DA7218_BEEP_ON_OFF_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("ToneGen Off Time", DA7218_TONE_GEN_OFF_PER,
+ DA7218_BEEP_OFF_PER_SHIFT, DA7218_BEEP_ON_OFF_MAX,
+ DA7218_NO_INVERT),
+
+ /* Gain ramping */
+ SOC_ENUM("Gain Ramp Rate", da7218_gain_ramp_rate),
+
+ /* DGS */
+ SOC_SINGLE_TLV("DGS Trigger", DA7218_DGS_TRIGGER,
+ DA7218_DGS_TRIGGER_LVL_SHIFT, DA7218_DGS_TRIGGER_MAX,
+ DA7218_INVERT, da7218_dgs_trigger_tlv),
+ SOC_ENUM("DGS Rise Coefficient", da7218_dgs_rise_coeff),
+ SOC_ENUM("DGS Fall Coefficient", da7218_dgs_fall_coeff),
+ SOC_SINGLE("DGS Sync Delay", DA7218_DGS_SYNC_DELAY,
+ DA7218_DGS_SYNC_DELAY_SHIFT, DA7218_DGS_SYNC_DELAY_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("DGS Fast SR Sync Delay", DA7218_DGS_SYNC_DELAY2,
+ DA7218_DGS_SYNC_DELAY2_SHIFT, DA7218_DGS_SYNC_DELAY_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("DGS Voice Filter Sync Delay", DA7218_DGS_SYNC_DELAY3,
+ DA7218_DGS_SYNC_DELAY3_SHIFT, DA7218_DGS_SYNC_DELAY3_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE_TLV("DGS Anticlip Level", DA7218_DGS_LEVELS,
+ DA7218_DGS_ANTICLIP_LVL_SHIFT,
+ DA7218_DGS_ANTICLIP_LVL_MAX, DA7218_INVERT,
+ da7218_dgs_anticlip_tlv),
+ SOC_SINGLE_TLV("DGS Signal Level", DA7218_DGS_LEVELS,
+ DA7218_DGS_SIGNAL_LVL_SHIFT, DA7218_DGS_SIGNAL_LVL_MAX,
+ DA7218_INVERT, da7218_dgs_signal_tlv),
+ SOC_SINGLE("DGS Gain Subrange Switch", DA7218_DGS_GAIN_CTRL,
+ DA7218_DGS_SUBR_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("DGS Gain Ramp Switch", DA7218_DGS_GAIN_CTRL,
+ DA7218_DGS_RAMP_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_SINGLE("DGS Gain Steps", DA7218_DGS_GAIN_CTRL,
+ DA7218_DGS_STEPS_SHIFT, DA7218_DGS_STEPS_MAX,
+ DA7218_NO_INVERT),
+ SOC_DOUBLE("DGS Switch", DA7218_DGS_ENABLE, DA7218_DGS_ENABLE_L_SHIFT,
+ DA7218_DGS_ENABLE_R_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+
+ /* Output High-Pass Filter */
+ SOC_ENUM("Out Filter HPF Mode", da7218_out1_hpf_mode),
+ SOC_ENUM("Out Filter HPF Corner Audio", da7218_out1_audio_hpf_corner),
+ SOC_ENUM("Out Filter HPF Corner Voice", da7218_out1_voice_hpf_corner),
+
+ /* 5-Band Equaliser */
+ SOC_SINGLE_TLV("Out EQ Band1 Volume", DA7218_OUT_1_EQ_12_FILTER_CTRL,
+ DA7218_OUT_1_EQ_BAND1_SHIFT, DA7218_OUT_EQ_BAND_MAX,
+ DA7218_NO_INVERT, da7218_out_eq_band_tlv),
+ SOC_SINGLE_TLV("Out EQ Band2 Volume", DA7218_OUT_1_EQ_12_FILTER_CTRL,
+ DA7218_OUT_1_EQ_BAND2_SHIFT, DA7218_OUT_EQ_BAND_MAX,
+ DA7218_NO_INVERT, da7218_out_eq_band_tlv),
+ SOC_SINGLE_TLV("Out EQ Band3 Volume", DA7218_OUT_1_EQ_34_FILTER_CTRL,
+ DA7218_OUT_1_EQ_BAND3_SHIFT, DA7218_OUT_EQ_BAND_MAX,
+ DA7218_NO_INVERT, da7218_out_eq_band_tlv),
+ SOC_SINGLE_TLV("Out EQ Band4 Volume", DA7218_OUT_1_EQ_34_FILTER_CTRL,
+ DA7218_OUT_1_EQ_BAND4_SHIFT, DA7218_OUT_EQ_BAND_MAX,
+ DA7218_NO_INVERT, da7218_out_eq_band_tlv),
+ SOC_SINGLE_TLV("Out EQ Band5 Volume", DA7218_OUT_1_EQ_5_FILTER_CTRL,
+ DA7218_OUT_1_EQ_BAND5_SHIFT, DA7218_OUT_EQ_BAND_MAX,
+ DA7218_NO_INVERT, da7218_out_eq_band_tlv),
+ SOC_SINGLE("Out EQ Switch", DA7218_OUT_1_EQ_5_FILTER_CTRL,
+ DA7218_OUT_1_EQ_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+
+ /* BiQuad Filters */
+ SND_SOC_BYTES_EXT("BiQuad Coefficients",
+ DA7218_OUT_1_BIQ_5STAGE_CFG_SIZE,
+ da7218_biquad_coeff_get, da7218_biquad_coeff_put),
+ SOC_SINGLE("BiQuad Filter Switch", DA7218_OUT_1_BIQ_5STAGE_CTRL,
+ DA7218_OUT_1_BIQ_5STAGE_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+
+ /* Output Filters */
+ SOC_DOUBLE_R_RANGE_TLV("Out Filter Volume", DA7218_OUT_1L_GAIN,
+ DA7218_OUT_1R_GAIN,
+ DA7218_OUT_1L_DIGITAL_GAIN_SHIFT,
+ DA7218_OUT_DIGITAL_GAIN_MIN,
+ DA7218_OUT_DIGITAL_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_out_dig_gain_tlv),
+ SOC_DOUBLE_R("Out Filter Switch", DA7218_OUT_1L_FILTER_CTRL,
+ DA7218_OUT_1R_FILTER_CTRL, DA7218_OUT_1L_MUTE_EN_SHIFT,
+ DA7218_SWITCH_EN_MAX, DA7218_INVERT),
+ SOC_DOUBLE_R("Out Filter Gain Subrange Switch",
+ DA7218_OUT_1L_FILTER_CTRL, DA7218_OUT_1R_FILTER_CTRL,
+ DA7218_OUT_1L_SUBRANGE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_NO_INVERT),
+ SOC_DOUBLE_R("Out Filter Gain Ramp Switch", DA7218_OUT_1L_FILTER_CTRL,
+ DA7218_OUT_1R_FILTER_CTRL, DA7218_OUT_1L_RAMP_EN_SHIFT,
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT),
+
+ /* Mixer Output */
+ SOC_DOUBLE_R_RANGE_TLV("Mixout Volume", DA7218_MIXOUT_L_GAIN,
+ DA7218_MIXOUT_R_GAIN,
+ DA7218_MIXOUT_L_AMP_GAIN_SHIFT,
+ DA7218_MIXOUT_AMP_GAIN_MIN,
+ DA7218_MIXOUT_AMP_GAIN_MAX, DA7218_NO_INVERT,
+ da7218_mixout_gain_tlv),
+
+ /* DAC Noise Gate */
+ SOC_ENUM("DAC NG Setup Time", da7218_dac_ng_setup_time),
+ SOC_ENUM("DAC NG Rampup Rate", da7218_dac_ng_rampup_rate),
+ SOC_ENUM("DAC NG Rampdown Rate", da7218_dac_ng_rampdown_rate),
+ SOC_SINGLE_TLV("DAC NG Off Threshold", DA7218_DAC_NG_OFF_THRESH,
+ DA7218_DAC_NG_OFF_THRESHOLD_SHIFT,
+ DA7218_DAC_NG_THRESHOLD_MAX, DA7218_NO_INVERT,
+ da7218_dac_ng_threshold_tlv),
+ SOC_SINGLE_TLV("DAC NG On Threshold", DA7218_DAC_NG_ON_THRESH,
+ DA7218_DAC_NG_ON_THRESHOLD_SHIFT,
+ DA7218_DAC_NG_THRESHOLD_MAX, DA7218_NO_INVERT,
+ da7218_dac_ng_threshold_tlv),
+ SOC_SINGLE("DAC NG Switch", DA7218_DAC_NG_CTRL, DA7218_DAC_NG_EN_SHIFT,
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT),
+
+ /* CP */
+ SOC_ENUM("Charge Pump Track Mode", da7218_cp_mchange),
+ SOC_ENUM("Charge Pump Frequency", da7218_cp_fcontrol),
+ SOC_ENUM("Charge Pump Decay Rate", da7218_cp_tau_delay),
+ SOC_SINGLE("Charge Pump Threshold", DA7218_CP_VOL_THRESHOLD1,
+ DA7218_CP_THRESH_VDD2_SHIFT, DA7218_CP_THRESH_VDD2_MAX,
+ DA7218_NO_INVERT),
+
+ /* Headphones */
+ SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", DA7218_HP_L_GAIN,
+ DA7218_HP_R_GAIN, DA7218_HP_L_AMP_GAIN_SHIFT,
+ DA7218_HP_AMP_GAIN_MIN, DA7218_HP_AMP_GAIN_MAX,
+ DA7218_NO_INVERT, da7218_hp_gain_tlv),
+ SOC_DOUBLE_R("Headphone Switch", DA7218_HP_L_CTRL, DA7218_HP_R_CTRL,
+ DA7218_HP_L_AMP_MUTE_EN_SHIFT, DA7218_SWITCH_EN_MAX,
+ DA7218_INVERT),
+ SOC_DOUBLE_R("Headphone Gain Ramp Switch", DA7218_HP_L_CTRL,
+ DA7218_HP_R_CTRL, DA7218_HP_L_AMP_RAMP_EN_SHIFT,
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT),
+ SOC_DOUBLE_R("Headphone ZC Gain Switch", DA7218_HP_L_CTRL,
+ DA7218_HP_R_CTRL, DA7218_HP_L_AMP_ZC_EN_SHIFT,
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT),
+};
+
+
+/*
+ * DAPM Mux Controls
+ */
+
+static const char * const da7218_mic_sel_text[] = { "Analog", "Digital" };
+
+static const struct soc_enum da7218_mic1_sel =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(da7218_mic_sel_text),
+ da7218_mic_sel_text);
+
+static const struct snd_kcontrol_new da7218_mic1_sel_mux =
+ SOC_DAPM_ENUM("Mic1 Mux", da7218_mic1_sel);
+
+static const struct soc_enum da7218_mic2_sel =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(da7218_mic_sel_text),
+ da7218_mic_sel_text);
+
+static const struct snd_kcontrol_new da7218_mic2_sel_mux =
+ SOC_DAPM_ENUM("Mic2 Mux", da7218_mic2_sel);
+
+static const char * const da7218_sidetone_in_sel_txt[] = {
+ "In Filter1L", "In Filter1R", "In Filter2L", "In Filter2R"
+};
+
+static const struct soc_enum da7218_sidetone_in_sel =
+ SOC_ENUM_SINGLE(DA7218_SIDETONE_IN_SELECT,
+ DA7218_SIDETONE_IN_SELECT_SHIFT,
+ DA7218_SIDETONE_IN_SELECT_MAX,
+ da7218_sidetone_in_sel_txt);
+
+static const struct snd_kcontrol_new da7218_sidetone_in_sel_mux =
+ SOC_DAPM_ENUM("Sidetone Mux", da7218_sidetone_in_sel);
+
+static const char * const da7218_out_filt_biq_sel_txt[] = {
+ "Bypass", "Enabled"
+};
+
+static const struct soc_enum da7218_out_filtl_biq_sel =
+ SOC_ENUM_SINGLE(DA7218_OUT_1L_FILTER_CTRL,
+ DA7218_OUT_1L_BIQ_5STAGE_SEL_SHIFT,
+ DA7218_OUT_BIQ_5STAGE_SEL_MAX,
+ da7218_out_filt_biq_sel_txt);
+
+static const struct snd_kcontrol_new da7218_out_filtl_biq_sel_mux =
+ SOC_DAPM_ENUM("Out FilterL BiQuad Mux", da7218_out_filtl_biq_sel);
+
+static const struct soc_enum da7218_out_filtr_biq_sel =
+ SOC_ENUM_SINGLE(DA7218_OUT_1R_FILTER_CTRL,
+ DA7218_OUT_1R_BIQ_5STAGE_SEL_SHIFT,
+ DA7218_OUT_BIQ_5STAGE_SEL_MAX,
+ da7218_out_filt_biq_sel_txt);
+
+static const struct snd_kcontrol_new da7218_out_filtr_biq_sel_mux =
+ SOC_DAPM_ENUM("Out FilterR BiQuad Mux", da7218_out_filtr_biq_sel);
+
+
+/*
+ * DAPM Mixer Controls
+ */
+
+#define DA7218_DMIX_CTRLS(reg) \
+ SOC_DAPM_SINGLE("In Filter1L Switch", reg, \
+ DA7218_DMIX_SRC_INFILT1L, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \
+ SOC_DAPM_SINGLE("In Filter1R Switch", reg, \
+ DA7218_DMIX_SRC_INFILT1R, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \
+ SOC_DAPM_SINGLE("In Filter2L Switch", reg, \
+ DA7218_DMIX_SRC_INFILT2L, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \
+ SOC_DAPM_SINGLE("In Filter2R Switch", reg, \
+ DA7218_DMIX_SRC_INFILT2R, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \
+ SOC_DAPM_SINGLE("ToneGen Switch", reg, \
+ DA7218_DMIX_SRC_TONEGEN, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \
+ SOC_DAPM_SINGLE("DAIL Switch", reg, DA7218_DMIX_SRC_DAIL, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \
+ SOC_DAPM_SINGLE("DAIR Switch", reg, DA7218_DMIX_SRC_DAIR, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT)
+
+static const struct snd_kcontrol_new da7218_out_dai1l_mix_controls[] = {
+ DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTDAI_1L),
+};
+
+static const struct snd_kcontrol_new da7218_out_dai1r_mix_controls[] = {
+ DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTDAI_1R),
+};
+
+static const struct snd_kcontrol_new da7218_out_dai2l_mix_controls[] = {
+ DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTDAI_2L),
+};
+
+static const struct snd_kcontrol_new da7218_out_dai2r_mix_controls[] = {
+ DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTDAI_2R),
+};
+
+static const struct snd_kcontrol_new da7218_out_filtl_mix_controls[] = {
+ DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTFILT_1L),
+};
+
+static const struct snd_kcontrol_new da7218_out_filtr_mix_controls[] = {
+ DA7218_DMIX_CTRLS(DA7218_DROUTING_OUTFILT_1R),
+};
+
+#define DA7218_DMIX_ST_CTRLS(reg) \
+ SOC_DAPM_SINGLE("Out FilterL Switch", reg, \
+ DA7218_DMIX_ST_SRC_OUTFILT1L, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \
+ SOC_DAPM_SINGLE("Out FilterR Switch", reg, \
+ DA7218_DMIX_ST_SRC_OUTFILT1R, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT), \
+ SOC_DAPM_SINGLE("Sidetone Switch", reg, \
+ DA7218_DMIX_ST_SRC_SIDETONE, \
+ DA7218_SWITCH_EN_MAX, DA7218_NO_INVERT) \
+
+static const struct snd_kcontrol_new da7218_st_out_filtl_mix_controls[] = {
+ DA7218_DMIX_ST_CTRLS(DA7218_DROUTING_ST_OUTFILT_1L),
+};
+
+static const struct snd_kcontrol_new da7218_st_out_filtr_mix_controls[] = {
+ DA7218_DMIX_ST_CTRLS(DA7218_DROUTING_ST_OUTFILT_1R),
+};
+
+
+/*
+ * DAPM Events
+ */
+
+/*
+ * We keep track of which input filters are enabled. This is used in the logic
+ * for controlling the mic level detect feature.
+ */
+static int da7218_in_filter_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ u8 mask;
+
+ switch (w->reg) {
+ case DA7218_IN_1L_FILTER_CTRL:
+ mask = (1 << DA7218_LVL_DET_EN_CHAN1L_SHIFT);
+ break;
+ case DA7218_IN_1R_FILTER_CTRL:
+ mask = (1 << DA7218_LVL_DET_EN_CHAN1R_SHIFT);
+ break;
+ case DA7218_IN_2L_FILTER_CTRL:
+ mask = (1 << DA7218_LVL_DET_EN_CHAN2L_SHIFT);
+ break;
+ case DA7218_IN_2R_FILTER_CTRL:
+ mask = (1 << DA7218_LVL_DET_EN_CHAN2R_SHIFT);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ da7218->in_filt_en |= mask;
+ /*
+ * If we're enabling path for mic level detect, wait for path
+ * to settle before enabling feature to avoid incorrect and
+ * unwanted detect events.
+ */
+ if (mask & da7218->mic_lvl_det_en)
+ msleep(DA7218_MIC_LVL_DET_DELAY);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ da7218->in_filt_en &= ~mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Enable configured level detection paths */
+ snd_soc_write(codec, DA7218_LVL_DET_CTRL,
+ (da7218->in_filt_en & da7218->mic_lvl_det_en));
+
+ return 0;
+}
+
+static int da7218_dai_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ u8 pll_ctrl, pll_status, refosc_cal;
+ int i;
+ bool success;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (da7218->master)
+ /* Enable DAI clks for master mode */
+ snd_soc_update_bits(codec, DA7218_DAI_CLK_MODE,
+ DA7218_DAI_CLK_EN_MASK,
+ DA7218_DAI_CLK_EN_MASK);
+
+ /* Tune reference oscillator */
+ snd_soc_write(codec, DA7218_PLL_REFOSC_CAL,
+ DA7218_PLL_REFOSC_CAL_START_MASK);
+ snd_soc_write(codec, DA7218_PLL_REFOSC_CAL,
+ DA7218_PLL_REFOSC_CAL_START_MASK |
+ DA7218_PLL_REFOSC_CAL_EN_MASK);
+
+ /* Check tuning complete */
+ i = 0;
+ success = false;
+ do {
+ refosc_cal = snd_soc_read(codec, DA7218_PLL_REFOSC_CAL);
+ if (!(refosc_cal & DA7218_PLL_REFOSC_CAL_START_MASK)) {
+ success = true;
+ } else {
+ ++i;
+ usleep_range(DA7218_REF_OSC_CHECK_DELAY_MIN,
+ DA7218_REF_OSC_CHECK_DELAY_MAX);
+ }
+ } while ((i < DA7218_REF_OSC_CHECK_TRIES) && (!success));
+
+ if (!success)
+ dev_warn(codec->dev,
+ "Reference oscillator failed calibration\n");
+
+ /* PC synchronised to DAI */
+ snd_soc_write(codec, DA7218_PC_COUNT,
+ DA7218_PC_RESYNC_AUTO_MASK);
+
+ /* If SRM not enabled, we don't need to check status */
+ pll_ctrl = snd_soc_read(codec, DA7218_PLL_CTRL);
+ if ((pll_ctrl & DA7218_PLL_MODE_MASK) != DA7218_PLL_MODE_SRM)
+ return 0;
+
+ /* Check SRM has locked */
+ i = 0;
+ success = false;
+ do {
+ pll_status = snd_soc_read(codec, DA7218_PLL_STATUS);
+ if (pll_status & DA7218_PLL_SRM_STATUS_SRM_LOCK) {
+ success = true;
+ } else {
+ ++i;
+ msleep(DA7218_SRM_CHECK_DELAY);
+ }
+ } while ((i < DA7218_SRM_CHECK_TRIES) & (!success));
+
+ if (!success)
+ dev_warn(codec->dev, "SRM failed to lock\n");
+
+ return 0;
+ case SND_SOC_DAPM_POST_PMD:
+ /* PC free-running */
+ snd_soc_write(codec, DA7218_PC_COUNT, DA7218_PC_FREERUN_MASK);
+
+ if (da7218->master)
+ /* Disable DAI clks for master mode */
+ snd_soc_update_bits(codec, DA7218_DAI_CLK_MODE,
+ DA7218_DAI_CLK_EN_MASK, 0);
+
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int da7218_cp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+
+ /*
+ * If this is DA7217 and we're using single supply for differential
+ * output, we really don't want to touch the charge pump.
+ */
+ if (da7218->hp_single_supply)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, DA7218_CP_CTRL, DA7218_CP_EN_MASK,
+ DA7218_CP_EN_MASK);
+ return 0;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, DA7218_CP_CTRL, DA7218_CP_EN_MASK,
+ 0);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int da7218_hp_pga_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* Enable headphone output */
+ snd_soc_update_bits(codec, w->reg, DA7218_HP_AMP_OE_MASK,
+ DA7218_HP_AMP_OE_MASK);
+ return 0;
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Headphone output high impedance */
+ snd_soc_update_bits(codec, w->reg, DA7218_HP_AMP_OE_MASK, 0);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+
+/*
+ * DAPM Widgets
+ */
+
+static const struct snd_soc_dapm_widget da7218_dapm_widgets[] = {
+ /* Input Supplies */
+ SND_SOC_DAPM_SUPPLY("Mic Bias1", DA7218_MICBIAS_EN,
+ DA7218_MICBIAS_1_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Mic Bias2", DA7218_MICBIAS_EN,
+ DA7218_MICBIAS_2_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DMic1 Left", DA7218_DMIC_1_CTRL,
+ DA7218_DMIC_1L_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DMic1 Right", DA7218_DMIC_1_CTRL,
+ DA7218_DMIC_1R_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DMic2 Left", DA7218_DMIC_2_CTRL,
+ DA7218_DMIC_2L_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DMic2 Right", DA7218_DMIC_2_CTRL,
+ DA7218_DMIC_2R_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+
+ /* Inputs */
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_INPUT("MIC2"),
+ SND_SOC_DAPM_INPUT("DMIC1L"),
+ SND_SOC_DAPM_INPUT("DMIC1R"),
+ SND_SOC_DAPM_INPUT("DMIC2L"),
+ SND_SOC_DAPM_INPUT("DMIC2R"),
+
+ /* Input Mixer Supplies */
+ SND_SOC_DAPM_SUPPLY("Mixin1 Supply", DA7218_MIXIN_1_CTRL,
+ DA7218_MIXIN_1_MIX_SEL_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Mixin2 Supply", DA7218_MIXIN_2_CTRL,
+ DA7218_MIXIN_2_MIX_SEL_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+
+ /* Input PGAs */
+ SND_SOC_DAPM_PGA("Mic1 PGA", DA7218_MIC_1_CTRL,
+ DA7218_MIC_1_AMP_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("Mic2 PGA", DA7218_MIC_2_CTRL,
+ DA7218_MIC_2_AMP_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("Mixin1 PGA", DA7218_MIXIN_1_CTRL,
+ DA7218_MIXIN_1_AMP_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("Mixin2 PGA", DA7218_MIXIN_2_CTRL,
+ DA7218_MIXIN_2_AMP_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+
+ /* Mic/DMic Muxes */
+ SND_SOC_DAPM_MUX("Mic1 Mux", SND_SOC_NOPM, 0, 0, &da7218_mic1_sel_mux),
+ SND_SOC_DAPM_MUX("Mic2 Mux", SND_SOC_NOPM, 0, 0, &da7218_mic2_sel_mux),
+
+ /* Input Filters */
+ SND_SOC_DAPM_ADC_E("In Filter1L", NULL, DA7218_IN_1L_FILTER_CTRL,
+ DA7218_IN_1L_FILTER_EN_SHIFT, DA7218_NO_INVERT,
+ da7218_in_filter_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_ADC_E("In Filter1R", NULL, DA7218_IN_1R_FILTER_CTRL,
+ DA7218_IN_1R_FILTER_EN_SHIFT, DA7218_NO_INVERT,
+ da7218_in_filter_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_ADC_E("In Filter2L", NULL, DA7218_IN_2L_FILTER_CTRL,
+ DA7218_IN_2L_FILTER_EN_SHIFT, DA7218_NO_INVERT,
+ da7218_in_filter_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_ADC_E("In Filter2R", NULL, DA7218_IN_2R_FILTER_CTRL,
+ DA7218_IN_2R_FILTER_EN_SHIFT, DA7218_NO_INVERT,
+ da7218_in_filter_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ /* Tone Generator */
+ SND_SOC_DAPM_SIGGEN("TONE"),
+ SND_SOC_DAPM_PGA("Tone Generator", DA7218_TONE_GEN_CFG1,
+ DA7218_START_STOPN_SHIFT, DA7218_NO_INVERT, NULL, 0),
+
+ /* Sidetone Input */
+ SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
+ &da7218_sidetone_in_sel_mux),
+ SND_SOC_DAPM_ADC("Sidetone Filter", NULL, DA7218_SIDETONE_CTRL,
+ DA7218_SIDETONE_FILTER_EN_SHIFT, DA7218_NO_INVERT),
+
+ /* Input Mixers */
+ SND_SOC_DAPM_MIXER("Mixer DAI1L", SND_SOC_NOPM, 0, 0,
+ da7218_out_dai1l_mix_controls,
+ ARRAY_SIZE(da7218_out_dai1l_mix_controls)),
+ SND_SOC_DAPM_MIXER("Mixer DAI1R", SND_SOC_NOPM, 0, 0,
+ da7218_out_dai1r_mix_controls,
+ ARRAY_SIZE(da7218_out_dai1r_mix_controls)),
+ SND_SOC_DAPM_MIXER("Mixer DAI2L", SND_SOC_NOPM, 0, 0,
+ da7218_out_dai2l_mix_controls,
+ ARRAY_SIZE(da7218_out_dai2l_mix_controls)),
+ SND_SOC_DAPM_MIXER("Mixer DAI2R", SND_SOC_NOPM, 0, 0,
+ da7218_out_dai2r_mix_controls,
+ ARRAY_SIZE(da7218_out_dai2r_mix_controls)),
+
+ /* DAI Supply */
+ SND_SOC_DAPM_SUPPLY("DAI", DA7218_DAI_CTRL, DA7218_DAI_EN_SHIFT,
+ DA7218_NO_INVERT, da7218_dai_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* DAI */
+ SND_SOC_DAPM_AIF_OUT("DAIOUT", "Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("DAIIN", "Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ /* Output Mixers */
+ SND_SOC_DAPM_MIXER("Mixer Out FilterL", SND_SOC_NOPM, 0, 0,
+ da7218_out_filtl_mix_controls,
+ ARRAY_SIZE(da7218_out_filtl_mix_controls)),
+ SND_SOC_DAPM_MIXER("Mixer Out FilterR", SND_SOC_NOPM, 0, 0,
+ da7218_out_filtr_mix_controls,
+ ARRAY_SIZE(da7218_out_filtr_mix_controls)),
+
+ /* BiQuad Filters */
+ SND_SOC_DAPM_MUX("Out FilterL BiQuad Mux", SND_SOC_NOPM, 0, 0,
+ &da7218_out_filtl_biq_sel_mux),
+ SND_SOC_DAPM_MUX("Out FilterR BiQuad Mux", SND_SOC_NOPM, 0, 0,
+ &da7218_out_filtr_biq_sel_mux),
+ SND_SOC_DAPM_DAC("BiQuad Filter", NULL, DA7218_OUT_1_BIQ_5STAGE_CTRL,
+ DA7218_OUT_1_BIQ_5STAGE_FILTER_EN_SHIFT,
+ DA7218_NO_INVERT),
+
+ /* Sidetone Mixers */
+ SND_SOC_DAPM_MIXER("ST Mixer Out FilterL", SND_SOC_NOPM, 0, 0,
+ da7218_st_out_filtl_mix_controls,
+ ARRAY_SIZE(da7218_st_out_filtl_mix_controls)),
+ SND_SOC_DAPM_MIXER("ST Mixer Out FilterR", SND_SOC_NOPM, 0, 0,
+ da7218_st_out_filtr_mix_controls,
+ ARRAY_SIZE(da7218_st_out_filtr_mix_controls)),
+
+ /* Output Filters */
+ SND_SOC_DAPM_DAC("Out FilterL", NULL, DA7218_OUT_1L_FILTER_CTRL,
+ DA7218_OUT_1L_FILTER_EN_SHIFT, DA7218_NO_INVERT),
+ SND_SOC_DAPM_DAC("Out FilterR", NULL, DA7218_OUT_1R_FILTER_CTRL,
+ DA7218_IN_1R_FILTER_EN_SHIFT, DA7218_NO_INVERT),
+
+ /* Output PGAs */
+ SND_SOC_DAPM_PGA("Mixout Left PGA", DA7218_MIXOUT_L_CTRL,
+ DA7218_MIXOUT_L_AMP_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("Mixout Right PGA", DA7218_MIXOUT_R_CTRL,
+ DA7218_MIXOUT_R_AMP_EN_SHIFT, DA7218_NO_INVERT,
+ NULL, 0),
+ SND_SOC_DAPM_PGA_E("Headphone Left PGA", DA7218_HP_L_CTRL,
+ DA7218_HP_L_AMP_EN_SHIFT, DA7218_NO_INVERT, NULL, 0,
+ da7218_hp_pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_PGA_E("Headphone Right PGA", DA7218_HP_R_CTRL,
+ DA7218_HP_R_AMP_EN_SHIFT, DA7218_NO_INVERT, NULL, 0,
+ da7218_hp_pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ /* Output Supplies */
+ SND_SOC_DAPM_SUPPLY("Charge Pump", SND_SOC_NOPM, 0, 0, da7218_cp_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ /* Outputs */
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+};
+
+
+/*
+ * DAPM Mixer Routes
+ */
+
+#define DA7218_DMIX_ROUTES(name) \
+ {name, "In Filter1L Switch", "In Filter1L"}, \
+ {name, "In Filter1R Switch", "In Filter1R"}, \
+ {name, "In Filter2L Switch", "In Filter2L"}, \
+ {name, "In Filter2R Switch", "In Filter2R"}, \
+ {name, "ToneGen Switch", "Tone Generator"}, \
+ {name, "DAIL Switch", "DAIIN"}, \
+ {name, "DAIR Switch", "DAIIN"}
+
+#define DA7218_DMIX_ST_ROUTES(name) \
+ {name, "Out FilterL Switch", "Out FilterL BiQuad Mux"}, \
+ {name, "Out FilterR Switch", "Out FilterR BiQuad Mux"}, \
+ {name, "Sidetone Switch", "Sidetone Filter"}
+
+
+/*
+ * DAPM audio route definition
+ */
+
+static const struct snd_soc_dapm_route da7218_audio_map[] = {
+ /* Input paths */
+ {"MIC1", NULL, "Mic Bias1"},
+ {"MIC2", NULL, "Mic Bias2"},
+ {"DMIC1L", NULL, "Mic Bias1"},
+ {"DMIC1L", NULL, "DMic1 Left"},
+ {"DMIC1R", NULL, "Mic Bias1"},
+ {"DMIC1R", NULL, "DMic1 Right"},
+ {"DMIC2L", NULL, "Mic Bias2"},
+ {"DMIC2L", NULL, "DMic2 Left"},
+ {"DMIC2R", NULL, "Mic Bias2"},
+ {"DMIC2R", NULL, "DMic2 Right"},
+
+ {"Mic1 PGA", NULL, "MIC1"},
+ {"Mic2 PGA", NULL, "MIC2"},
+
+ {"Mixin1 PGA", NULL, "Mixin1 Supply"},
+ {"Mixin2 PGA", NULL, "Mixin2 Supply"},
+
+ {"Mixin1 PGA", NULL, "Mic1 PGA"},
+ {"Mixin2 PGA", NULL, "Mic2 PGA"},
+
+ {"Mic1 Mux", "Analog", "Mixin1 PGA"},
+ {"Mic1 Mux", "Digital", "DMIC1L"},
+ {"Mic1 Mux", "Digital", "DMIC1R"},
+ {"Mic2 Mux", "Analog", "Mixin2 PGA"},
+ {"Mic2 Mux", "Digital", "DMIC2L"},
+ {"Mic2 Mux", "Digital", "DMIC2R"},
+
+ {"In Filter1L", NULL, "Mic1 Mux"},
+ {"In Filter1R", NULL, "Mic1 Mux"},
+ {"In Filter2L", NULL, "Mic2 Mux"},
+ {"In Filter2R", NULL, "Mic2 Mux"},
+
+ {"Tone Generator", NULL, "TONE"},
+
+ {"Sidetone Mux", "In Filter1L", "In Filter1L"},
+ {"Sidetone Mux", "In Filter1R", "In Filter1R"},
+ {"Sidetone Mux", "In Filter2L", "In Filter2L"},
+ {"Sidetone Mux", "In Filter2R", "In Filter2R"},
+ {"Sidetone Filter", NULL, "Sidetone Mux"},
+
+ DA7218_DMIX_ROUTES("Mixer DAI1L"),
+ DA7218_DMIX_ROUTES("Mixer DAI1R"),
+ DA7218_DMIX_ROUTES("Mixer DAI2L"),
+ DA7218_DMIX_ROUTES("Mixer DAI2R"),
+
+ {"DAIOUT", NULL, "Mixer DAI1L"},
+ {"DAIOUT", NULL, "Mixer DAI1R"},
+ {"DAIOUT", NULL, "Mixer DAI2L"},
+ {"DAIOUT", NULL, "Mixer DAI2R"},
+
+ {"DAIOUT", NULL, "DAI"},
+
+ /* Output paths */
+ {"DAIIN", NULL, "DAI"},
+
+ DA7218_DMIX_ROUTES("Mixer Out FilterL"),
+ DA7218_DMIX_ROUTES("Mixer Out FilterR"),
+
+ {"BiQuad Filter", NULL, "Mixer Out FilterL"},
+ {"BiQuad Filter", NULL, "Mixer Out FilterR"},
+
+ {"Out FilterL BiQuad Mux", "Bypass", "Mixer Out FilterL"},
+ {"Out FilterL BiQuad Mux", "Enabled", "BiQuad Filter"},
+ {"Out FilterR BiQuad Mux", "Bypass", "Mixer Out FilterR"},
+ {"Out FilterR BiQuad Mux", "Enabled", "BiQuad Filter"},
+
+ DA7218_DMIX_ST_ROUTES("ST Mixer Out FilterL"),
+ DA7218_DMIX_ST_ROUTES("ST Mixer Out FilterR"),
+
+ {"Out FilterL", NULL, "ST Mixer Out FilterL"},
+ {"Out FilterR", NULL, "ST Mixer Out FilterR"},
+
+ {"Mixout Left PGA", NULL, "Out FilterL"},
+ {"Mixout Right PGA", NULL, "Out FilterR"},
+
+ {"Headphone Left PGA", NULL, "Mixout Left PGA"},
+ {"Headphone Right PGA", NULL, "Mixout Right PGA"},
+
+ {"HPL", NULL, "Headphone Left PGA"},
+ {"HPR", NULL, "Headphone Right PGA"},
+
+ {"HPL", NULL, "Charge Pump"},
+ {"HPR", NULL, "Charge Pump"},
+};
+
+
+/*
+ * DAI operations
+ */
+
+static int da7218_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ if (da7218->mclk_rate == freq)
+ return 0;
+
+ if (((freq < 2000000) && (freq != 32768)) || (freq > 54000000)) {
+ dev_err(codec_dai->dev, "Unsupported MCLK value %d\n",
+ freq);
+ return -EINVAL;
+ }
+
+ switch (clk_id) {
+ case DA7218_CLKSRC_MCLK_SQR:
+ snd_soc_update_bits(codec, DA7218_PLL_CTRL,
+ DA7218_PLL_MCLK_SQR_EN_MASK,
+ DA7218_PLL_MCLK_SQR_EN_MASK);
+ break;
+ case DA7218_CLKSRC_MCLK:
+ snd_soc_update_bits(codec, DA7218_PLL_CTRL,
+ DA7218_PLL_MCLK_SQR_EN_MASK, 0);
+ break;
+ default:
+ dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ if (da7218->mclk) {
+ freq = clk_round_rate(da7218->mclk, freq);
+ ret = clk_set_rate(da7218->mclk, freq);
+ if (ret) {
+ dev_err(codec_dai->dev, "Failed to set clock rate %d\n",
+ freq);
+ return ret;
+ }
+ }
+
+ da7218->mclk_rate = freq;
+
+ return 0;
+}
+
+static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+ int source, unsigned int fref, unsigned int fout)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+
+ u8 pll_ctrl, indiv_bits, indiv;
+ u8 pll_frac_top, pll_frac_bot, pll_integer;
+ u32 freq_ref;
+ u64 frac_div;
+
+ /* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */
+ if (da7218->mclk_rate == 32768) {
+ indiv_bits = DA7218_PLL_INDIV_2_5_MHZ;
+ indiv = DA7218_PLL_INDIV_2_10_MHZ_VAL;
+ } else if (da7218->mclk_rate < 2000000) {
+ dev_err(codec->dev, "PLL input clock %d below valid range\n",
+ da7218->mclk_rate);
+ return -EINVAL;
+ } else if (da7218->mclk_rate <= 5000000) {
+ indiv_bits = DA7218_PLL_INDIV_2_5_MHZ;
+ indiv = DA7218_PLL_INDIV_2_10_MHZ_VAL;
+ } else if (da7218->mclk_rate <= 10000000) {
+ indiv_bits = DA7218_PLL_INDIV_5_10_MHZ;
+ indiv = DA7218_PLL_INDIV_2_10_MHZ_VAL;
+ } else if (da7218->mclk_rate <= 20000000) {
+ indiv_bits = DA7218_PLL_INDIV_10_20_MHZ;
+ indiv = DA7218_PLL_INDIV_10_20_MHZ_VAL;
+ } else if (da7218->mclk_rate <= 40000000) {
+ indiv_bits = DA7218_PLL_INDIV_20_40_MHZ;
+ indiv = DA7218_PLL_INDIV_20_40_MHZ_VAL;
+ } else if (da7218->mclk_rate <= 54000000) {
+ indiv_bits = DA7218_PLL_INDIV_40_54_MHZ;
+ indiv = DA7218_PLL_INDIV_40_54_MHZ_VAL;
+ } else {
+ dev_err(codec->dev, "PLL input clock %d above valid range\n",
+ da7218->mclk_rate);
+ return -EINVAL;
+ }
+ freq_ref = (da7218->mclk_rate / indiv);
+ pll_ctrl = indiv_bits;
+
+ /* Configure PLL */
+ switch (source) {
+ case DA7218_SYSCLK_MCLK:
+ pll_ctrl |= DA7218_PLL_MODE_BYPASS;
+ snd_soc_update_bits(codec, DA7218_PLL_CTRL,
+ DA7218_PLL_INDIV_MASK |
+ DA7218_PLL_MODE_MASK, pll_ctrl);
+ return 0;
+ case DA7218_SYSCLK_PLL:
+ pll_ctrl |= DA7218_PLL_MODE_NORMAL;
+ break;
+ case DA7218_SYSCLK_PLL_SRM:
+ pll_ctrl |= DA7218_PLL_MODE_SRM;
+ break;
+ case DA7218_SYSCLK_PLL_32KHZ:
+ pll_ctrl |= DA7218_PLL_MODE_32KHZ;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid PLL config\n");
+ return -EINVAL;
+ }
+
+ /* Calculate dividers for PLL */
+ pll_integer = fout / freq_ref;
+ frac_div = (u64)(fout % freq_ref) * 8192ULL;
+ do_div(frac_div, freq_ref);
+ pll_frac_top = (frac_div >> DA7218_BYTE_SHIFT) & DA7218_BYTE_MASK;
+ pll_frac_bot = (frac_div) & DA7218_BYTE_MASK;
+
+ /* Write PLL config & dividers */
+ snd_soc_write(codec, DA7218_PLL_FRAC_TOP, pll_frac_top);
+ snd_soc_write(codec, DA7218_PLL_FRAC_BOT, pll_frac_bot);
+ snd_soc_write(codec, DA7218_PLL_INTEGER, pll_integer);
+ snd_soc_update_bits(codec, DA7218_PLL_CTRL,
+ DA7218_PLL_MODE_MASK | DA7218_PLL_INDIV_MASK,
+ pll_ctrl);
+
+ return 0;
+}
+
+static int da7218_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ u8 dai_clk_mode = 0, dai_ctrl = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ da7218->master = true;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ da7218->master = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_LEFT_J:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ dai_clk_mode |= DA7218_DAI_WCLK_POL_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ dai_clk_mode |= DA7218_DAI_CLK_POL_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ dai_clk_mode |= DA7218_DAI_WCLK_POL_INV |
+ DA7218_DAI_CLK_POL_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ dai_clk_mode |= DA7218_DAI_CLK_POL_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ dai_clk_mode |= DA7218_DAI_WCLK_POL_INV |
+ DA7218_DAI_CLK_POL_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ dai_clk_mode |= DA7218_DAI_WCLK_POL_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ dai_ctrl |= DA7218_DAI_FORMAT_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ dai_ctrl |= DA7218_DAI_FORMAT_LEFT_J;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ dai_ctrl |= DA7218_DAI_FORMAT_RIGHT_J;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ dai_ctrl |= DA7218_DAI_FORMAT_DSP;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* By default 64 BCLKs per WCLK is supported */
+ dai_clk_mode |= DA7218_DAI_BCLKS_PER_WCLK_64;
+
+ snd_soc_write(codec, DA7218_DAI_CLK_MODE, dai_clk_mode);
+ snd_soc_update_bits(codec, DA7218_DAI_CTRL, DA7218_DAI_FORMAT_MASK,
+ dai_ctrl);
+
+ return 0;
+}
+
+static int da7218_set_dai_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u8 dai_bclks_per_wclk;
+ u32 frame_size;
+
+ /* No channels enabled so disable TDM, revert to 64-bit frames */
+ if (!tx_mask) {
+ snd_soc_update_bits(codec, DA7218_DAI_TDM_CTRL,
+ DA7218_DAI_TDM_CH_EN_MASK |
+ DA7218_DAI_TDM_MODE_EN_MASK, 0);
+ snd_soc_update_bits(codec, DA7218_DAI_CLK_MODE,
+ DA7218_DAI_BCLKS_PER_WCLK_MASK,
+ DA7218_DAI_BCLKS_PER_WCLK_64);
+ return 0;
+ }
+
+ /* Check we have valid slots */
+ if (fls(tx_mask) > DA7218_DAI_TDM_MAX_SLOTS) {
+ dev_err(codec->dev, "Invalid number of slots, max = %d\n",
+ DA7218_DAI_TDM_MAX_SLOTS);
+ return -EINVAL;
+ }
+
+ /* Check we have a valid offset given (first 2 bytes of rx_mask) */
+ if (rx_mask >> DA7218_2BYTE_SHIFT) {
+ dev_err(codec->dev, "Invalid slot offset, max = %d\n",
+ DA7218_2BYTE_MASK);
+ return -EINVAL;
+ }
+
+ /* Calculate & validate frame size based on slot info provided. */
+ frame_size = slots * slot_width;
+ switch (frame_size) {
+ case 32:
+ dai_bclks_per_wclk = DA7218_DAI_BCLKS_PER_WCLK_32;
+ break;
+ case 64:
+ dai_bclks_per_wclk = DA7218_DAI_BCLKS_PER_WCLK_64;
+ break;
+ case 128:
+ dai_bclks_per_wclk = DA7218_DAI_BCLKS_PER_WCLK_128;
+ break;
+ case 256:
+ dai_bclks_per_wclk = DA7218_DAI_BCLKS_PER_WCLK_256;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid frame size\n");
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, DA7218_DAI_CLK_MODE,
+ DA7218_DAI_BCLKS_PER_WCLK_MASK,
+ dai_bclks_per_wclk);
+ snd_soc_write(codec, DA7218_DAI_OFFSET_LOWER,
+ (rx_mask & DA7218_BYTE_MASK));
+ snd_soc_write(codec, DA7218_DAI_OFFSET_UPPER,
+ ((rx_mask >> DA7218_BYTE_SHIFT) & DA7218_BYTE_MASK));
+ snd_soc_update_bits(codec, DA7218_DAI_TDM_CTRL,
+ DA7218_DAI_TDM_CH_EN_MASK |
+ DA7218_DAI_TDM_MODE_EN_MASK,
+ (tx_mask << DA7218_DAI_TDM_CH_EN_SHIFT) |
+ DA7218_DAI_TDM_MODE_EN_MASK);
+
+ return 0;
+}
+
+static int da7218_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u8 dai_ctrl = 0, fs;
+ unsigned int channels;
+
+ switch (params_width(params)) {
+ case 16:
+ dai_ctrl |= DA7218_DAI_WORD_LENGTH_S16_LE;
+ break;
+ case 20:
+ dai_ctrl |= DA7218_DAI_WORD_LENGTH_S20_LE;
+ break;
+ case 24:
+ dai_ctrl |= DA7218_DAI_WORD_LENGTH_S24_LE;
+ break;
+ case 32:
+ dai_ctrl |= DA7218_DAI_WORD_LENGTH_S32_LE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ channels = params_channels(params);
+ if ((channels < 1) || (channels > DA7218_DAI_CH_NUM_MAX)) {
+ dev_err(codec->dev,
+ "Invalid number of channels, only 1 to %d supported\n",
+ DA7218_DAI_CH_NUM_MAX);
+ return -EINVAL;
+ }
+ dai_ctrl |= channels << DA7218_DAI_CH_NUM_SHIFT;
+
+ switch (params_rate(params)) {
+ case 8000:
+ fs = DA7218_SR_8000;
+ break;
+ case 11025:
+ fs = DA7218_SR_11025;
+ break;
+ case 12000:
+ fs = DA7218_SR_12000;
+ break;
+ case 16000:
+ fs = DA7218_SR_16000;
+ break;
+ case 22050:
+ fs = DA7218_SR_22050;
+ break;
+ case 24000:
+ fs = DA7218_SR_24000;
+ break;
+ case 32000:
+ fs = DA7218_SR_32000;
+ break;
+ case 44100:
+ fs = DA7218_SR_44100;
+ break;
+ case 48000:
+ fs = DA7218_SR_48000;
+ break;
+ case 88200:
+ fs = DA7218_SR_88200;
+ break;
+ case 96000:
+ fs = DA7218_SR_96000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, DA7218_DAI_CTRL,
+ DA7218_DAI_WORD_LENGTH_MASK | DA7218_DAI_CH_NUM_MASK,
+ dai_ctrl);
+ /* SRs tied for ADCs and DACs. */
+ snd_soc_write(codec, DA7218_SR,
+ (fs << DA7218_SR_DAC_SHIFT) | (fs << DA7218_SR_ADC_SHIFT));
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops da7218_dai_ops = {
+ .hw_params = da7218_hw_params,
+ .set_sysclk = da7218_set_dai_sysclk,
+ .set_pll = da7218_set_dai_pll,
+ .set_fmt = da7218_set_dai_fmt,
+ .set_tdm_slot = da7218_set_dai_tdm_slot,
+};
+
+#define DA7218_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver da7218_dai = {
+ .name = "da7218-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 4, /* Only 2 channels of data */
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = DA7218_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = DA7218_FORMATS,
+ },
+ .ops = &da7218_dai_ops,
+ .symmetric_rates = 1,
+ .symmetric_channels = 1,
+ .symmetric_samplebits = 1,
+};
+
+
+/*
+ * HP Detect
+ */
+
+int da7218_hpldet(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+
+ if (da7218->dev_id == DA7217_DEV_ID)
+ return -EINVAL;
+
+ da7218->jack = jack;
+ snd_soc_update_bits(codec, DA7218_HPLDET_JACK,
+ DA7218_HPLDET_JACK_EN_MASK,
+ jack ? DA7218_HPLDET_JACK_EN_MASK : 0);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(da7218_hpldet);
+
+static void da7218_micldet_irq(struct snd_soc_codec *codec)
+{
+ char *envp[] = {
+ "EVENT=MIC_LEVEL_DETECT",
+ NULL,
+ };
+
+ kobject_uevent_env(&codec->dev->kobj, KOBJ_CHANGE, envp);
+}
+
+static void da7218_hpldet_irq(struct snd_soc_codec *codec)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ u8 jack_status;
+ int report;
+
+ jack_status = snd_soc_read(codec, DA7218_EVENT_STATUS);
+
+ if (jack_status & DA7218_HPLDET_JACK_STS_MASK)
+ report = SND_JACK_HEADPHONE;
+ else
+ report = 0;
+
+ snd_soc_jack_report(da7218->jack, report, SND_JACK_HEADPHONE);
+}
+
+/*
+ * IRQ
+ */
+
+static irqreturn_t da7218_irq_thread(int irq, void *data)
+{
+ struct snd_soc_codec *codec = data;
+ u8 status;
+
+ /* Read IRQ status reg */
+ status = snd_soc_read(codec, DA7218_EVENT);
+ if (!status)
+ return IRQ_NONE;
+
+ /* Mic level detect */
+ if (status & DA7218_LVL_DET_EVENT_MASK)
+ da7218_micldet_irq(codec);
+
+ /* HP detect */
+ if (status & DA7218_HPLDET_JACK_EVENT_MASK)
+ da7218_hpldet_irq(codec);
+
+ /* Clear interrupts */
+ snd_soc_write(codec, DA7218_EVENT, status);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * DT
+ */
+
+static const struct of_device_id da7218_of_match[] = {
+ { .compatible = "dlg,da7217", .data = (void *) DA7217_DEV_ID },
+ { .compatible = "dlg,da7218", .data = (void *) DA7218_DEV_ID },
+ { }
+};
+MODULE_DEVICE_TABLE(of, da7218_of_match);
+
+static inline int da7218_of_get_id(struct device *dev)
+{
+ const struct of_device_id *id = of_match_device(da7218_of_match, dev);
+
+ if (id)
+ return (uintptr_t)id->data;
+ else
+ return -EINVAL;
+}
+
+static enum da7218_micbias_voltage
+ da7218_of_micbias_lvl(struct snd_soc_codec *codec, u32 val)
+{
+ switch (val) {
+ case 1200:
+ return DA7218_MICBIAS_1_2V;
+ case 1600:
+ return DA7218_MICBIAS_1_6V;
+ case 1800:
+ return DA7218_MICBIAS_1_8V;
+ case 2000:
+ return DA7218_MICBIAS_2_0V;
+ case 2200:
+ return DA7218_MICBIAS_2_2V;
+ case 2400:
+ return DA7218_MICBIAS_2_4V;
+ case 2600:
+ return DA7218_MICBIAS_2_6V;
+ case 2800:
+ return DA7218_MICBIAS_2_8V;
+ case 3000:
+ return DA7218_MICBIAS_3_0V;
+ default:
+ dev_warn(codec->dev, "Invalid micbias level");
+ return DA7218_MICBIAS_1_6V;
+ }
+}
+
+static enum da7218_mic_amp_in_sel
+ da7218_of_mic_amp_in_sel(struct snd_soc_codec *codec, const char *str)
+{
+ if (!strcmp(str, "diff")) {
+ return DA7218_MIC_AMP_IN_SEL_DIFF;
+ } else if (!strcmp(str, "se_p")) {
+ return DA7218_MIC_AMP_IN_SEL_SE_P;
+ } else if (!strcmp(str, "se_n")) {
+ return DA7218_MIC_AMP_IN_SEL_SE_N;
+ } else {
+ dev_warn(codec->dev, "Invalid mic input type selection");
+ return DA7218_MIC_AMP_IN_SEL_DIFF;
+ }
+}
+
+static enum da7218_dmic_data_sel
+ da7218_of_dmic_data_sel(struct snd_soc_codec *codec, const char *str)
+{
+ if (!strcmp(str, "lrise_rfall")) {
+ return DA7218_DMIC_DATA_LRISE_RFALL;
+ } else if (!strcmp(str, "lfall_rrise")) {
+ return DA7218_DMIC_DATA_LFALL_RRISE;
+ } else {
+ dev_warn(codec->dev, "Invalid DMIC data type selection");
+ return DA7218_DMIC_DATA_LRISE_RFALL;
+ }
+}
+
+static enum da7218_dmic_samplephase
+ da7218_of_dmic_samplephase(struct snd_soc_codec *codec, const char *str)
+{
+ if (!strcmp(str, "on_clkedge")) {
+ return DA7218_DMIC_SAMPLE_ON_CLKEDGE;
+ } else if (!strcmp(str, "between_clkedge")) {
+ return DA7218_DMIC_SAMPLE_BETWEEN_CLKEDGE;
+ } else {
+ dev_warn(codec->dev, "Invalid DMIC sample phase");
+ return DA7218_DMIC_SAMPLE_ON_CLKEDGE;
+ }
+}
+
+static enum da7218_dmic_clk_rate
+ da7218_of_dmic_clkrate(struct snd_soc_codec *codec, u32 val)
+{
+ switch (val) {
+ case 1500000:
+ return DA7218_DMIC_CLK_1_5MHZ;
+ case 3000000:
+ return DA7218_DMIC_CLK_3_0MHZ;
+ default:
+ dev_warn(codec->dev, "Invalid DMIC clock rate");
+ return DA7218_DMIC_CLK_3_0MHZ;
+ }
+}
+
+static enum da7218_hpldet_jack_rate
+ da7218_of_jack_rate(struct snd_soc_codec *codec, u32 val)
+{
+ switch (val) {
+ case 5:
+ return DA7218_HPLDET_JACK_RATE_5US;
+ case 10:
+ return DA7218_HPLDET_JACK_RATE_10US;
+ case 20:
+ return DA7218_HPLDET_JACK_RATE_20US;
+ case 40:
+ return DA7218_HPLDET_JACK_RATE_40US;
+ case 80:
+ return DA7218_HPLDET_JACK_RATE_80US;
+ case 160:
+ return DA7218_HPLDET_JACK_RATE_160US;
+ case 320:
+ return DA7218_HPLDET_JACK_RATE_320US;
+ case 640:
+ return DA7218_HPLDET_JACK_RATE_640US;
+ default:
+ dev_warn(codec->dev, "Invalid jack detect rate");
+ return DA7218_HPLDET_JACK_RATE_40US;
+ }
+}
+
+static enum da7218_hpldet_jack_debounce
+ da7218_of_jack_debounce(struct snd_soc_codec *codec, u32 val)
+{
+ switch (val) {
+ case 0:
+ return DA7218_HPLDET_JACK_DEBOUNCE_OFF;
+ case 2:
+ return DA7218_HPLDET_JACK_DEBOUNCE_2;
+ case 3:
+ return DA7218_HPLDET_JACK_DEBOUNCE_3;
+ case 4:
+ return DA7218_HPLDET_JACK_DEBOUNCE_4;
+ default:
+ dev_warn(codec->dev, "Invalid jack debounce");
+ return DA7218_HPLDET_JACK_DEBOUNCE_2;
+ }
+}
+
+static enum da7218_hpldet_jack_thr
+ da7218_of_jack_thr(struct snd_soc_codec *codec, u32 val)
+{
+ switch (val) {
+ case 84:
+ return DA7218_HPLDET_JACK_THR_84PCT;
+ case 88:
+ return DA7218_HPLDET_JACK_THR_88PCT;
+ case 92:
+ return DA7218_HPLDET_JACK_THR_92PCT;
+ case 96:
+ return DA7218_HPLDET_JACK_THR_96PCT;
+ default:
+ dev_warn(codec->dev, "Invalid jack threshold level");
+ return DA7218_HPLDET_JACK_THR_84PCT;
+ }
+}
+
+static struct da7218_pdata *da7218_of_to_pdata(struct snd_soc_codec *codec)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ struct device_node *np = codec->dev->of_node;
+ struct device_node *hpldet_np;
+ struct da7218_pdata *pdata;
+ struct da7218_hpldet_pdata *hpldet_pdata;
+ const char *of_str;
+ u32 of_val32;
+
+ pdata = devm_kzalloc(codec->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_warn(codec->dev, "Failed to allocate memory for pdata\n");
+ return NULL;
+ }
+
+ if (of_property_read_u32(np, "dlg,micbias1-lvl-millivolt", &of_val32) >= 0)
+ pdata->micbias1_lvl = da7218_of_micbias_lvl(codec, of_val32);
+ else
+ pdata->micbias1_lvl = DA7218_MICBIAS_1_6V;
+
+ if (of_property_read_u32(np, "dlg,micbias2-lvl-millivolt", &of_val32) >= 0)
+ pdata->micbias2_lvl = da7218_of_micbias_lvl(codec, of_val32);
+ else
+ pdata->micbias2_lvl = DA7218_MICBIAS_1_6V;
+
+ if (!of_property_read_string(np, "dlg,mic1-amp-in-sel", &of_str))
+ pdata->mic1_amp_in_sel =
+ da7218_of_mic_amp_in_sel(codec, of_str);
+ else
+ pdata->mic1_amp_in_sel = DA7218_MIC_AMP_IN_SEL_DIFF;
+
+ if (!of_property_read_string(np, "dlg,mic2-amp-in-sel", &of_str))
+ pdata->mic2_amp_in_sel =
+ da7218_of_mic_amp_in_sel(codec, of_str);
+ else
+ pdata->mic2_amp_in_sel = DA7218_MIC_AMP_IN_SEL_DIFF;
+
+ if (!of_property_read_string(np, "dlg,dmic1-data-sel", &of_str))
+ pdata->dmic1_data_sel = da7218_of_dmic_data_sel(codec, of_str);
+ else
+ pdata->dmic1_data_sel = DA7218_DMIC_DATA_LRISE_RFALL;
+
+ if (!of_property_read_string(np, "dlg,dmic1-samplephase", &of_str))
+ pdata->dmic1_samplephase =
+ da7218_of_dmic_samplephase(codec, of_str);
+ else
+ pdata->dmic1_samplephase = DA7218_DMIC_SAMPLE_ON_CLKEDGE;
+
+ if (of_property_read_u32(np, "dlg,dmic1-clkrate-hz", &of_val32) >= 0)
+ pdata->dmic1_clk_rate = da7218_of_dmic_clkrate(codec, of_val32);
+ else
+ pdata->dmic1_clk_rate = DA7218_DMIC_CLK_3_0MHZ;
+
+ if (!of_property_read_string(np, "dlg,dmic2-data-sel", &of_str))
+ pdata->dmic2_data_sel = da7218_of_dmic_data_sel(codec, of_str);
+ else
+ pdata->dmic2_data_sel = DA7218_DMIC_DATA_LRISE_RFALL;
+
+ if (!of_property_read_string(np, "dlg,dmic2-samplephase", &of_str))
+ pdata->dmic2_samplephase =
+ da7218_of_dmic_samplephase(codec, of_str);
+ else
+ pdata->dmic2_samplephase = DA7218_DMIC_SAMPLE_ON_CLKEDGE;
+
+ if (of_property_read_u32(np, "dlg,dmic2-clkrate-hz", &of_val32) >= 0)
+ pdata->dmic2_clk_rate = da7218_of_dmic_clkrate(codec, of_val32);
+ else
+ pdata->dmic2_clk_rate = DA7218_DMIC_CLK_3_0MHZ;
+
+ if (da7218->dev_id == DA7217_DEV_ID) {
+ if (of_property_read_bool(np, "dlg,hp-diff-single-supply"))
+ pdata->hp_diff_single_supply = true;
+ }
+
+ if (da7218->dev_id == DA7218_DEV_ID) {
+ hpldet_np = of_find_node_by_name(np, "da7218_hpldet");
+ if (!hpldet_np)
+ return pdata;
+
+ hpldet_pdata = devm_kzalloc(codec->dev, sizeof(*hpldet_pdata),
+ GFP_KERNEL);
+ if (!hpldet_pdata) {
+ dev_warn(codec->dev,
+ "Failed to allocate memory for hpldet pdata\n");
+ of_node_put(hpldet_np);
+ return pdata;
+ }
+ pdata->hpldet_pdata = hpldet_pdata;
+
+ if (of_property_read_u32(hpldet_np, "dlg,jack-rate-us",
+ &of_val32) >= 0)
+ hpldet_pdata->jack_rate =
+ da7218_of_jack_rate(codec, of_val32);
+ else
+ hpldet_pdata->jack_rate = DA7218_HPLDET_JACK_RATE_40US;
+
+ if (of_property_read_u32(hpldet_np, "dlg,jack-debounce",
+ &of_val32) >= 0)
+ hpldet_pdata->jack_debounce =
+ da7218_of_jack_debounce(codec, of_val32);
+ else
+ hpldet_pdata->jack_debounce =
+ DA7218_HPLDET_JACK_DEBOUNCE_2;
+
+ if (of_property_read_u32(hpldet_np, "dlg,jack-threshold-pct",
+ &of_val32) >= 0)
+ hpldet_pdata->jack_thr =
+ da7218_of_jack_thr(codec, of_val32);
+ else
+ hpldet_pdata->jack_thr = DA7218_HPLDET_JACK_THR_84PCT;
+
+ if (of_property_read_bool(hpldet_np, "dlg,comp-inv"))
+ hpldet_pdata->comp_inv = true;
+
+ if (of_property_read_bool(hpldet_np, "dlg,hyst"))
+ hpldet_pdata->hyst = true;
+
+ if (of_property_read_bool(hpldet_np, "dlg,discharge"))
+ hpldet_pdata->discharge = true;
+
+ of_node_put(hpldet_np);
+ }
+
+ return pdata;
+}
+
+
+/*
+ * Codec driver functions
+ */
+
+static int da7218_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
+ /* MCLK */
+ if (da7218->mclk) {
+ ret = clk_prepare_enable(da7218->mclk);
+ if (ret) {
+ dev_err(codec->dev,
+ "Failed to enable mclk\n");
+ return ret;
+ }
+ }
+
+ /* Master bias */
+ snd_soc_update_bits(codec, DA7218_REFERENCES,
+ DA7218_BIAS_EN_MASK,
+ DA7218_BIAS_EN_MASK);
+
+ /* Internal LDO */
+ snd_soc_update_bits(codec, DA7218_LDO_CTRL,
+ DA7218_LDO_EN_MASK,
+ DA7218_LDO_EN_MASK);
+ }
+ break;
+ case SND_SOC_BIAS_OFF:
+ /* Only disable if jack detection disabled */
+ if (!da7218->jack) {
+ /* Internal LDO */
+ snd_soc_update_bits(codec, DA7218_LDO_CTRL,
+ DA7218_LDO_EN_MASK, 0);
+
+ /* Master bias */
+ snd_soc_update_bits(codec, DA7218_REFERENCES,
+ DA7218_BIAS_EN_MASK, 0);
+ }
+
+ /* MCLK */
+ if (da7218->mclk)
+ clk_disable_unprepare(da7218->mclk);
+ break;
+ }
+
+ return 0;
+}
+
+static const char *da7218_supply_names[DA7218_NUM_SUPPLIES] = {
+ [DA7218_SUPPLY_VDD] = "VDD",
+ [DA7218_SUPPLY_VDDMIC] = "VDDMIC",
+ [DA7218_SUPPLY_VDDIO] = "VDDIO",
+};
+
+static int da7218_handle_supplies(struct snd_soc_codec *codec)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ struct regulator *vddio;
+ u8 io_voltage_lvl = DA7218_IO_VOLTAGE_LEVEL_2_5V_3_6V;
+ int i, ret;
+
+ /* Get required supplies */
+ for (i = 0; i < DA7218_NUM_SUPPLIES; ++i)
+ da7218->supplies[i].supply = da7218_supply_names[i];
+
+ ret = devm_regulator_bulk_get(codec->dev, DA7218_NUM_SUPPLIES,
+ da7218->supplies);
+ if (ret) {
+ dev_err(codec->dev, "Failed to get supplies\n");
+ return ret;
+ }
+
+ /* Determine VDDIO voltage provided */
+ vddio = da7218->supplies[DA7218_SUPPLY_VDDIO].consumer;
+ ret = regulator_get_voltage(vddio);
+ if (ret < 1500000)
+ dev_warn(codec->dev, "Invalid VDDIO voltage\n");
+ else if (ret < 2500000)
+ io_voltage_lvl = DA7218_IO_VOLTAGE_LEVEL_1_5V_2_5V;
+
+ /* Enable main supplies */
+ ret = regulator_bulk_enable(DA7218_NUM_SUPPLIES, da7218->supplies);
+ if (ret) {
+ dev_err(codec->dev, "Failed to enable supplies\n");
+ return ret;
+ }
+
+ /* Ensure device in active mode */
+ snd_soc_write(codec, DA7218_SYSTEM_ACTIVE, DA7218_SYSTEM_ACTIVE_MASK);
+
+ /* Update IO voltage level range */
+ snd_soc_write(codec, DA7218_IO_CTRL, io_voltage_lvl);
+
+ return 0;
+}
+
+static void da7218_handle_pdata(struct snd_soc_codec *codec)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ struct da7218_pdata *pdata = da7218->pdata;
+
+ if (pdata) {
+ u8 micbias_lvl = 0, dmic_cfg = 0;
+
+ /* Mic Bias voltages */
+ switch (pdata->micbias1_lvl) {
+ case DA7218_MICBIAS_1_2V:
+ micbias_lvl |= DA7218_MICBIAS_1_LP_MODE_MASK;
+ break;
+ case DA7218_MICBIAS_1_6V:
+ case DA7218_MICBIAS_1_8V:
+ case DA7218_MICBIAS_2_0V:
+ case DA7218_MICBIAS_2_2V:
+ case DA7218_MICBIAS_2_4V:
+ case DA7218_MICBIAS_2_6V:
+ case DA7218_MICBIAS_2_8V:
+ case DA7218_MICBIAS_3_0V:
+ micbias_lvl |= (pdata->micbias1_lvl <<
+ DA7218_MICBIAS_1_LEVEL_SHIFT);
+ break;
+ }
+
+ switch (pdata->micbias2_lvl) {
+ case DA7218_MICBIAS_1_2V:
+ micbias_lvl |= DA7218_MICBIAS_2_LP_MODE_MASK;
+ break;
+ case DA7218_MICBIAS_1_6V:
+ case DA7218_MICBIAS_1_8V:
+ case DA7218_MICBIAS_2_0V:
+ case DA7218_MICBIAS_2_2V:
+ case DA7218_MICBIAS_2_4V:
+ case DA7218_MICBIAS_2_6V:
+ case DA7218_MICBIAS_2_8V:
+ case DA7218_MICBIAS_3_0V:
+ micbias_lvl |= (pdata->micbias2_lvl <<
+ DA7218_MICBIAS_2_LEVEL_SHIFT);
+ break;
+ }
+
+ snd_soc_write(codec, DA7218_MICBIAS_CTRL, micbias_lvl);
+
+ /* Mic */
+ switch (pdata->mic1_amp_in_sel) {
+ case DA7218_MIC_AMP_IN_SEL_DIFF:
+ case DA7218_MIC_AMP_IN_SEL_SE_P:
+ case DA7218_MIC_AMP_IN_SEL_SE_N:
+ snd_soc_write(codec, DA7218_MIC_1_SELECT,
+ pdata->mic1_amp_in_sel);
+ break;
+ }
+
+ switch (pdata->mic2_amp_in_sel) {
+ case DA7218_MIC_AMP_IN_SEL_DIFF:
+ case DA7218_MIC_AMP_IN_SEL_SE_P:
+ case DA7218_MIC_AMP_IN_SEL_SE_N:
+ snd_soc_write(codec, DA7218_MIC_2_SELECT,
+ pdata->mic2_amp_in_sel);
+ break;
+ }
+
+ /* DMic */
+ switch (pdata->dmic1_data_sel) {
+ case DA7218_DMIC_DATA_LFALL_RRISE:
+ case DA7218_DMIC_DATA_LRISE_RFALL:
+ dmic_cfg |= (pdata->dmic1_data_sel <<
+ DA7218_DMIC_1_DATA_SEL_SHIFT);
+ break;
+ }
+
+ switch (pdata->dmic1_samplephase) {
+ case DA7218_DMIC_SAMPLE_ON_CLKEDGE:
+ case DA7218_DMIC_SAMPLE_BETWEEN_CLKEDGE:
+ dmic_cfg |= (pdata->dmic1_samplephase <<
+ DA7218_DMIC_1_SAMPLEPHASE_SHIFT);
+ break;
+ }
+
+ switch (pdata->dmic1_clk_rate) {
+ case DA7218_DMIC_CLK_3_0MHZ:
+ case DA7218_DMIC_CLK_1_5MHZ:
+ dmic_cfg |= (pdata->dmic1_clk_rate <<
+ DA7218_DMIC_1_CLK_RATE_SHIFT);
+ break;
+ }
+
+ snd_soc_update_bits(codec, DA7218_DMIC_1_CTRL,
+ DA7218_DMIC_1_DATA_SEL_MASK |
+ DA7218_DMIC_1_SAMPLEPHASE_MASK |
+ DA7218_DMIC_1_CLK_RATE_MASK, dmic_cfg);
+
+ dmic_cfg = 0;
+ switch (pdata->dmic2_data_sel) {
+ case DA7218_DMIC_DATA_LFALL_RRISE:
+ case DA7218_DMIC_DATA_LRISE_RFALL:
+ dmic_cfg |= (pdata->dmic2_data_sel <<
+ DA7218_DMIC_2_DATA_SEL_SHIFT);
+ break;
+ }
+
+ switch (pdata->dmic2_samplephase) {
+ case DA7218_DMIC_SAMPLE_ON_CLKEDGE:
+ case DA7218_DMIC_SAMPLE_BETWEEN_CLKEDGE:
+ dmic_cfg |= (pdata->dmic2_samplephase <<
+ DA7218_DMIC_2_SAMPLEPHASE_SHIFT);
+ break;
+ }
+
+ switch (pdata->dmic2_clk_rate) {
+ case DA7218_DMIC_CLK_3_0MHZ:
+ case DA7218_DMIC_CLK_1_5MHZ:
+ dmic_cfg |= (pdata->dmic2_clk_rate <<
+ DA7218_DMIC_2_CLK_RATE_SHIFT);
+ break;
+ }
+
+ snd_soc_update_bits(codec, DA7218_DMIC_2_CTRL,
+ DA7218_DMIC_2_DATA_SEL_MASK |
+ DA7218_DMIC_2_SAMPLEPHASE_MASK |
+ DA7218_DMIC_2_CLK_RATE_MASK, dmic_cfg);
+
+ /* DA7217 Specific */
+ if (da7218->dev_id == DA7217_DEV_ID) {
+ da7218->hp_single_supply =
+ pdata->hp_diff_single_supply;
+
+ if (da7218->hp_single_supply) {
+ snd_soc_write(codec, DA7218_HP_DIFF_UNLOCK,
+ DA7218_HP_DIFF_UNLOCK_VAL);
+ snd_soc_update_bits(codec, DA7218_HP_DIFF_CTRL,
+ DA7218_HP_AMP_SINGLE_SUPPLY_EN_MASK,
+ DA7218_HP_AMP_SINGLE_SUPPLY_EN_MASK);
+ }
+ }
+
+ /* DA7218 Specific */
+ if ((da7218->dev_id == DA7218_DEV_ID) &&
+ (pdata->hpldet_pdata)) {
+ struct da7218_hpldet_pdata *hpldet_pdata =
+ pdata->hpldet_pdata;
+ u8 hpldet_cfg = 0;
+
+ switch (hpldet_pdata->jack_rate) {
+ case DA7218_HPLDET_JACK_RATE_5US:
+ case DA7218_HPLDET_JACK_RATE_10US:
+ case DA7218_HPLDET_JACK_RATE_20US:
+ case DA7218_HPLDET_JACK_RATE_40US:
+ case DA7218_HPLDET_JACK_RATE_80US:
+ case DA7218_HPLDET_JACK_RATE_160US:
+ case DA7218_HPLDET_JACK_RATE_320US:
+ case DA7218_HPLDET_JACK_RATE_640US:
+ hpldet_cfg |=
+ (hpldet_pdata->jack_rate <<
+ DA7218_HPLDET_JACK_RATE_SHIFT);
+ break;
+ }
+
+ switch (hpldet_pdata->jack_debounce) {
+ case DA7218_HPLDET_JACK_DEBOUNCE_OFF:
+ case DA7218_HPLDET_JACK_DEBOUNCE_2:
+ case DA7218_HPLDET_JACK_DEBOUNCE_3:
+ case DA7218_HPLDET_JACK_DEBOUNCE_4:
+ hpldet_cfg |=
+ (hpldet_pdata->jack_debounce <<
+ DA7218_HPLDET_JACK_DEBOUNCE_SHIFT);
+ break;
+ }
+
+ switch (hpldet_pdata->jack_thr) {
+ case DA7218_HPLDET_JACK_THR_84PCT:
+ case DA7218_HPLDET_JACK_THR_88PCT:
+ case DA7218_HPLDET_JACK_THR_92PCT:
+ case DA7218_HPLDET_JACK_THR_96PCT:
+ hpldet_cfg |=
+ (hpldet_pdata->jack_thr <<
+ DA7218_HPLDET_JACK_THR_SHIFT);
+ break;
+ }
+ snd_soc_update_bits(codec, DA7218_HPLDET_JACK,
+ DA7218_HPLDET_JACK_RATE_MASK |
+ DA7218_HPLDET_JACK_DEBOUNCE_MASK |
+ DA7218_HPLDET_JACK_THR_MASK,
+ hpldet_cfg);
+
+ hpldet_cfg = 0;
+ if (hpldet_pdata->comp_inv)
+ hpldet_cfg |= DA7218_HPLDET_COMP_INV_MASK;
+
+ if (hpldet_pdata->hyst)
+ hpldet_cfg |= DA7218_HPLDET_HYST_EN_MASK;
+
+ if (hpldet_pdata->discharge)
+ hpldet_cfg |= DA7218_HPLDET_DISCHARGE_EN_MASK;
+
+ snd_soc_write(codec, DA7218_HPLDET_CTRL, hpldet_cfg);
+ }
+ }
+}
+
+static int da7218_probe(struct snd_soc_codec *codec)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ /* Regulator configuration */
+ ret = da7218_handle_supplies(codec);
+ if (ret)
+ return ret;
+
+ /* Handle DT/Platform data */
+ if (codec->dev->of_node)
+ da7218->pdata = da7218_of_to_pdata(codec);
+ else
+ da7218->pdata = dev_get_platdata(codec->dev);
+
+ da7218_handle_pdata(codec);
+
+ /* Check if MCLK provided, if not the clock is NULL */
+ da7218->mclk = devm_clk_get(codec->dev, "mclk");
+ if (IS_ERR(da7218->mclk)) {
+ if (PTR_ERR(da7218->mclk) != -ENOENT) {
+ ret = PTR_ERR(da7218->mclk);
+ goto err_disable_reg;
+ } else {
+ da7218->mclk = NULL;
+ }
+ }
+
+ /* Default PC to free-running */
+ snd_soc_write(codec, DA7218_PC_COUNT, DA7218_PC_FREERUN_MASK);
+
+ /*
+ * Default Output Filter mixers to off otherwise DAPM will power
+ * Mic to HP passthrough paths by default at startup.
+ */
+ snd_soc_write(codec, DA7218_DROUTING_OUTFILT_1L, 0);
+ snd_soc_write(codec, DA7218_DROUTING_OUTFILT_1R, 0);
+
+ /* Default CP to normal load, power mode */
+ snd_soc_update_bits(codec, DA7218_CP_CTRL,
+ DA7218_CP_SMALL_SWITCH_FREQ_EN_MASK, 0);
+
+ /* Default gain ramping */
+ snd_soc_update_bits(codec, DA7218_MIXIN_1_CTRL,
+ DA7218_MIXIN_1_AMP_RAMP_EN_MASK,
+ DA7218_MIXIN_1_AMP_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_MIXIN_2_CTRL,
+ DA7218_MIXIN_2_AMP_RAMP_EN_MASK,
+ DA7218_MIXIN_2_AMP_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_IN_1L_FILTER_CTRL,
+ DA7218_IN_1L_RAMP_EN_MASK,
+ DA7218_IN_1L_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_IN_1R_FILTER_CTRL,
+ DA7218_IN_1R_RAMP_EN_MASK,
+ DA7218_IN_1R_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_IN_2L_FILTER_CTRL,
+ DA7218_IN_2L_RAMP_EN_MASK,
+ DA7218_IN_2L_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_IN_2R_FILTER_CTRL,
+ DA7218_IN_2R_RAMP_EN_MASK,
+ DA7218_IN_2R_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_DGS_GAIN_CTRL,
+ DA7218_DGS_RAMP_EN_MASK, DA7218_DGS_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_OUT_1L_FILTER_CTRL,
+ DA7218_OUT_1L_RAMP_EN_MASK,
+ DA7218_OUT_1L_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_OUT_1R_FILTER_CTRL,
+ DA7218_OUT_1R_RAMP_EN_MASK,
+ DA7218_OUT_1R_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_HP_L_CTRL,
+ DA7218_HP_L_AMP_RAMP_EN_MASK,
+ DA7218_HP_L_AMP_RAMP_EN_MASK);
+ snd_soc_update_bits(codec, DA7218_HP_R_CTRL,
+ DA7218_HP_R_AMP_RAMP_EN_MASK,
+ DA7218_HP_R_AMP_RAMP_EN_MASK);
+
+ /* Default infinite tone gen, start/stop by Kcontrol */
+ snd_soc_write(codec, DA7218_TONE_GEN_CYCLES, DA7218_BEEP_CYCLES_MASK);
+
+ /* DA7217 specific config */
+ if (da7218->dev_id == DA7217_DEV_ID) {
+ snd_soc_update_bits(codec, DA7218_HP_DIFF_CTRL,
+ DA7218_HP_AMP_DIFF_MODE_EN_MASK,
+ DA7218_HP_AMP_DIFF_MODE_EN_MASK);
+
+ /* Only DA7218 supports HP detect, mask off for DA7217 */
+ snd_soc_write(codec, DA7218_EVENT_MASK,
+ DA7218_HPLDET_JACK_EVENT_IRQ_MSK_MASK);
+ }
+
+ if (da7218->irq) {
+ ret = devm_request_threaded_irq(codec->dev, da7218->irq, NULL,
+ da7218_irq_thread,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "da7218", codec);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
+ da7218->irq, ret);
+ goto err_disable_reg;
+ }
+
+ }
+
+ return 0;
+
+err_disable_reg:
+ regulator_bulk_disable(DA7218_NUM_SUPPLIES, da7218->supplies);
+
+ return ret;
+}
+
+static int da7218_remove(struct snd_soc_codec *codec)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+
+ regulator_bulk_disable(DA7218_NUM_SUPPLIES, da7218->supplies);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int da7218_suspend(struct snd_soc_codec *codec)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+
+ da7218_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ /* Put device into standby mode if jack detection disabled */
+ if (!da7218->jack)
+ snd_soc_write(codec, DA7218_SYSTEM_ACTIVE, 0);
+
+ return 0;
+}
+
+static int da7218_resume(struct snd_soc_codec *codec)
+{
+ struct da7218_priv *da7218 = snd_soc_codec_get_drvdata(codec);
+
+ /* Put device into active mode if previously moved to standby */
+ if (!da7218->jack)
+ snd_soc_write(codec, DA7218_SYSTEM_ACTIVE,
+ DA7218_SYSTEM_ACTIVE_MASK);
+
+ da7218_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+#else
+#define da7218_suspend NULL
+#define da7218_resume NULL
+#endif
+
+static struct snd_soc_codec_driver soc_codec_dev_da7218 = {
+ .probe = da7218_probe,
+ .remove = da7218_remove,
+ .suspend = da7218_suspend,
+ .resume = da7218_resume,
+ .set_bias_level = da7218_set_bias_level,
+
+ .controls = da7218_snd_controls,
+ .num_controls = ARRAY_SIZE(da7218_snd_controls),
+
+ .dapm_widgets = da7218_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(da7218_dapm_widgets),
+ .dapm_routes = da7218_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(da7218_audio_map),
+};
+
+
+/*
+ * Regmap configs
+ */
+
+static struct reg_default da7218_reg_defaults[] = {
+ { DA7218_SYSTEM_ACTIVE, 0x00 },
+ { DA7218_CIF_CTRL, 0x00 },
+ { DA7218_SPARE1, 0x00 },
+ { DA7218_SR, 0xAA },
+ { DA7218_PC_COUNT, 0x02 },
+ { DA7218_GAIN_RAMP_CTRL, 0x00 },
+ { DA7218_CIF_TIMEOUT_CTRL, 0x01 },
+ { DA7218_SYSTEM_MODES_INPUT, 0x00 },
+ { DA7218_SYSTEM_MODES_OUTPUT, 0x00 },
+ { DA7218_IN_1L_FILTER_CTRL, 0x00 },
+ { DA7218_IN_1R_FILTER_CTRL, 0x00 },
+ { DA7218_IN_2L_FILTER_CTRL, 0x00 },
+ { DA7218_IN_2R_FILTER_CTRL, 0x00 },
+ { DA7218_OUT_1L_FILTER_CTRL, 0x40 },
+ { DA7218_OUT_1R_FILTER_CTRL, 0x40 },
+ { DA7218_OUT_1_HPF_FILTER_CTRL, 0x80 },
+ { DA7218_OUT_1_EQ_12_FILTER_CTRL, 0x77 },
+ { DA7218_OUT_1_EQ_34_FILTER_CTRL, 0x77 },
+ { DA7218_OUT_1_EQ_5_FILTER_CTRL, 0x07 },
+ { DA7218_OUT_1_BIQ_5STAGE_CTRL, 0x40 },
+ { DA7218_OUT_1_BIQ_5STAGE_DATA, 0x00 },
+ { DA7218_OUT_1_BIQ_5STAGE_ADDR, 0x00 },
+ { DA7218_MIXIN_1_CTRL, 0x48 },
+ { DA7218_MIXIN_1_GAIN, 0x03 },
+ { DA7218_MIXIN_2_CTRL, 0x48 },
+ { DA7218_MIXIN_2_GAIN, 0x03 },
+ { DA7218_ALC_CTRL1, 0x00 },
+ { DA7218_ALC_CTRL2, 0x00 },
+ { DA7218_ALC_CTRL3, 0x00 },
+ { DA7218_ALC_NOISE, 0x3F },
+ { DA7218_ALC_TARGET_MIN, 0x3F },
+ { DA7218_ALC_TARGET_MAX, 0x00 },
+ { DA7218_ALC_GAIN_LIMITS, 0xFF },
+ { DA7218_ALC_ANA_GAIN_LIMITS, 0x71 },
+ { DA7218_ALC_ANTICLIP_CTRL, 0x00 },
+ { DA7218_AGS_ENABLE, 0x00 },
+ { DA7218_AGS_TRIGGER, 0x09 },
+ { DA7218_AGS_ATT_MAX, 0x00 },
+ { DA7218_AGS_TIMEOUT, 0x00 },
+ { DA7218_AGS_ANTICLIP_CTRL, 0x00 },
+ { DA7218_ENV_TRACK_CTRL, 0x00 },
+ { DA7218_LVL_DET_CTRL, 0x00 },
+ { DA7218_LVL_DET_LEVEL, 0x7F },
+ { DA7218_DGS_TRIGGER, 0x24 },
+ { DA7218_DGS_ENABLE, 0x00 },
+ { DA7218_DGS_RISE_FALL, 0x50 },
+ { DA7218_DGS_SYNC_DELAY, 0xA3 },
+ { DA7218_DGS_SYNC_DELAY2, 0x31 },
+ { DA7218_DGS_SYNC_DELAY3, 0x11 },
+ { DA7218_DGS_LEVELS, 0x01 },
+ { DA7218_DGS_GAIN_CTRL, 0x74 },
+ { DA7218_DROUTING_OUTDAI_1L, 0x01 },
+ { DA7218_DMIX_OUTDAI_1L_INFILT_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1L_INFILT_1R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1L_INFILT_2L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1L_INFILT_2R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1L_TONEGEN_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1L_INDAI_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1L_INDAI_1R_GAIN, 0x1C },
+ { DA7218_DROUTING_OUTDAI_1R, 0x04 },
+ { DA7218_DMIX_OUTDAI_1R_INFILT_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1R_INFILT_1R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1R_INFILT_2L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1R_INFILT_2R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1R_TONEGEN_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1R_INDAI_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_1R_INDAI_1R_GAIN, 0x1C },
+ { DA7218_DROUTING_OUTFILT_1L, 0x01 },
+ { DA7218_DMIX_OUTFILT_1L_INFILT_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1L_INFILT_1R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1L_INFILT_2L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1L_INFILT_2R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1L_TONEGEN_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1L_INDAI_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1L_INDAI_1R_GAIN, 0x1C },
+ { DA7218_DROUTING_OUTFILT_1R, 0x04 },
+ { DA7218_DMIX_OUTFILT_1R_INFILT_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1R_INFILT_1R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1R_INFILT_2L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1R_INFILT_2R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1R_TONEGEN_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1R_INDAI_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTFILT_1R_INDAI_1R_GAIN, 0x1C },
+ { DA7218_DROUTING_OUTDAI_2L, 0x04 },
+ { DA7218_DMIX_OUTDAI_2L_INFILT_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2L_INFILT_1R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2L_INFILT_2L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2L_INFILT_2R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2L_TONEGEN_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2L_INDAI_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2L_INDAI_1R_GAIN, 0x1C },
+ { DA7218_DROUTING_OUTDAI_2R, 0x08 },
+ { DA7218_DMIX_OUTDAI_2R_INFILT_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2R_INFILT_1R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2R_INFILT_2L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2R_INFILT_2R_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2R_TONEGEN_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2R_INDAI_1L_GAIN, 0x1C },
+ { DA7218_DMIX_OUTDAI_2R_INDAI_1R_GAIN, 0x1C },
+ { DA7218_DAI_CTRL, 0x28 },
+ { DA7218_DAI_TDM_CTRL, 0x40 },
+ { DA7218_DAI_OFFSET_LOWER, 0x00 },
+ { DA7218_DAI_OFFSET_UPPER, 0x00 },
+ { DA7218_DAI_CLK_MODE, 0x01 },
+ { DA7218_PLL_CTRL, 0x04 },
+ { DA7218_PLL_FRAC_TOP, 0x00 },
+ { DA7218_PLL_FRAC_BOT, 0x00 },
+ { DA7218_PLL_INTEGER, 0x20 },
+ { DA7218_DAC_NG_CTRL, 0x00 },
+ { DA7218_DAC_NG_SETUP_TIME, 0x00 },
+ { DA7218_DAC_NG_OFF_THRESH, 0x00 },
+ { DA7218_DAC_NG_ON_THRESH, 0x00 },
+ { DA7218_TONE_GEN_CFG2, 0x00 },
+ { DA7218_TONE_GEN_FREQ1_L, 0x55 },
+ { DA7218_TONE_GEN_FREQ1_U, 0x15 },
+ { DA7218_TONE_GEN_FREQ2_L, 0x00 },
+ { DA7218_TONE_GEN_FREQ2_U, 0x40 },
+ { DA7218_TONE_GEN_CYCLES, 0x00 },
+ { DA7218_TONE_GEN_ON_PER, 0x02 },
+ { DA7218_TONE_GEN_OFF_PER, 0x01 },
+ { DA7218_CP_CTRL, 0x60 },
+ { DA7218_CP_DELAY, 0x11 },
+ { DA7218_CP_VOL_THRESHOLD1, 0x0E },
+ { DA7218_MIC_1_CTRL, 0x40 },
+ { DA7218_MIC_1_GAIN, 0x01 },
+ { DA7218_MIC_1_SELECT, 0x00 },
+ { DA7218_MIC_2_CTRL, 0x40 },
+ { DA7218_MIC_2_GAIN, 0x01 },
+ { DA7218_MIC_2_SELECT, 0x00 },
+ { DA7218_IN_1_HPF_FILTER_CTRL, 0x80 },
+ { DA7218_IN_2_HPF_FILTER_CTRL, 0x80 },
+ { DA7218_ADC_1_CTRL, 0x07 },
+ { DA7218_ADC_2_CTRL, 0x07 },
+ { DA7218_MIXOUT_L_CTRL, 0x00 },
+ { DA7218_MIXOUT_L_GAIN, 0x03 },
+ { DA7218_MIXOUT_R_CTRL, 0x00 },
+ { DA7218_MIXOUT_R_GAIN, 0x03 },
+ { DA7218_HP_L_CTRL, 0x40 },
+ { DA7218_HP_L_GAIN, 0x3B },
+ { DA7218_HP_R_CTRL, 0x40 },
+ { DA7218_HP_R_GAIN, 0x3B },
+ { DA7218_HP_DIFF_CTRL, 0x00 },
+ { DA7218_HP_DIFF_UNLOCK, 0xC3 },
+ { DA7218_HPLDET_JACK, 0x0B },
+ { DA7218_HPLDET_CTRL, 0x00 },
+ { DA7218_REFERENCES, 0x08 },
+ { DA7218_IO_CTRL, 0x00 },
+ { DA7218_LDO_CTRL, 0x00 },
+ { DA7218_SIDETONE_CTRL, 0x40 },
+ { DA7218_SIDETONE_IN_SELECT, 0x00 },
+ { DA7218_SIDETONE_GAIN, 0x1C },
+ { DA7218_DROUTING_ST_OUTFILT_1L, 0x01 },
+ { DA7218_DROUTING_ST_OUTFILT_1R, 0x02 },
+ { DA7218_SIDETONE_BIQ_3STAGE_DATA, 0x00 },
+ { DA7218_SIDETONE_BIQ_3STAGE_ADDR, 0x00 },
+ { DA7218_EVENT_MASK, 0x00 },
+ { DA7218_DMIC_1_CTRL, 0x00 },
+ { DA7218_DMIC_2_CTRL, 0x00 },
+ { DA7218_IN_1L_GAIN, 0x6F },
+ { DA7218_IN_1R_GAIN, 0x6F },
+ { DA7218_IN_2L_GAIN, 0x6F },
+ { DA7218_IN_2R_GAIN, 0x6F },
+ { DA7218_OUT_1L_GAIN, 0x6F },
+ { DA7218_OUT_1R_GAIN, 0x6F },
+ { DA7218_MICBIAS_CTRL, 0x00 },
+ { DA7218_MICBIAS_EN, 0x00 },
+};
+
+static bool da7218_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case DA7218_STATUS1:
+ case DA7218_SOFT_RESET:
+ case DA7218_SYSTEM_STATUS:
+ case DA7218_CALIB_CTRL:
+ case DA7218_CALIB_OFFSET_AUTO_M_1:
+ case DA7218_CALIB_OFFSET_AUTO_U_1:
+ case DA7218_CALIB_OFFSET_AUTO_M_2:
+ case DA7218_CALIB_OFFSET_AUTO_U_2:
+ case DA7218_PLL_STATUS:
+ case DA7218_PLL_REFOSC_CAL:
+ case DA7218_TONE_GEN_CFG1:
+ case DA7218_ADC_MODE:
+ case DA7218_HP_SNGL_CTRL:
+ case DA7218_HPLDET_TEST:
+ case DA7218_EVENT_STATUS:
+ case DA7218_EVENT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config da7218_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = DA7218_MICBIAS_EN,
+ .reg_defaults = da7218_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(da7218_reg_defaults),
+ .volatile_reg = da7218_volatile_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+
+/*
+ * I2C layer
+ */
+
+static int da7218_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct da7218_priv *da7218;
+ int ret;
+
+ da7218 = devm_kzalloc(&i2c->dev, sizeof(struct da7218_priv),
+ GFP_KERNEL);
+ if (!da7218)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, da7218);
+
+ if (i2c->dev.of_node)
+ da7218->dev_id = da7218_of_get_id(&i2c->dev);
+ else
+ da7218->dev_id = id->driver_data;
+
+ if ((da7218->dev_id != DA7217_DEV_ID) &&
+ (da7218->dev_id != DA7218_DEV_ID)) {
+ dev_err(&i2c->dev, "Invalid device Id\n");
+ return -EINVAL;
+ }
+
+ da7218->irq = i2c->irq;
+
+ da7218->regmap = devm_regmap_init_i2c(i2c, &da7218_regmap_config);
+ if (IS_ERR(da7218->regmap)) {
+ ret = PTR_ERR(da7218->regmap);
+ dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_da7218, &da7218_dai, 1);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to register da7218 codec: %d\n",
+ ret);
+ }
+ return ret;
+}
+
+static int da7218_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id da7218_i2c_id[] = {
+ { "da7217", DA7217_DEV_ID },
+ { "da7218", DA7218_DEV_ID },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, da7218_i2c_id);
+
+static struct i2c_driver da7218_i2c_driver = {
+ .driver = {
+ .name = "da7218",
+ .of_match_table = of_match_ptr(da7218_of_match),
+ },
+ .probe = da7218_i2c_probe,
+ .remove = da7218_i2c_remove,
+ .id_table = da7218_i2c_id,
+};
+
+module_i2c_driver(da7218_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC DA7218 Codec driver");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/da7218.h b/sound/soc/codecs/da7218.h
new file mode 100644
index 000000000000..c2c59049a2ad
--- /dev/null
+++ b/sound/soc/codecs/da7218.h
@@ -0,0 +1,1414 @@
+/*
+ * da7218.h - DA7218 ALSA SoC Codec Driver
+ *
+ * Copyright (c) 2015 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.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; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _DA7218_H
+#define _DA7218_H
+
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <sound/da7218.h>
+
+
+/*
+ * Registers
+ */
+#define DA7218_SYSTEM_ACTIVE 0x0
+#define DA7218_CIF_CTRL 0x1
+#define DA7218_CHIP_ID1 0x4
+#define DA7218_CHIP_ID2 0x5
+#define DA7218_CHIP_REVISION 0x6
+#define DA7218_SPARE1 0x7
+#define DA7218_STATUS1 0x8
+#define DA7218_SOFT_RESET 0x9
+#define DA7218_SR 0xB
+#define DA7218_PC_COUNT 0xC
+#define DA7218_GAIN_RAMP_CTRL 0xD
+#define DA7218_CIF_TIMEOUT_CTRL 0x10
+#define DA7218_SYSTEM_MODES_INPUT 0x14
+#define DA7218_SYSTEM_MODES_OUTPUT 0x15
+#define DA7218_SYSTEM_STATUS 0x16
+#define DA7218_IN_1L_FILTER_CTRL 0x18
+#define DA7218_IN_1R_FILTER_CTRL 0x19
+#define DA7218_IN_2L_FILTER_CTRL 0x1A
+#define DA7218_IN_2R_FILTER_CTRL 0x1B
+#define DA7218_OUT_1L_FILTER_CTRL 0x20
+#define DA7218_OUT_1R_FILTER_CTRL 0x21
+#define DA7218_OUT_1_HPF_FILTER_CTRL 0x24
+#define DA7218_OUT_1_EQ_12_FILTER_CTRL 0x25
+#define DA7218_OUT_1_EQ_34_FILTER_CTRL 0x26
+#define DA7218_OUT_1_EQ_5_FILTER_CTRL 0x27
+#define DA7218_OUT_1_BIQ_5STAGE_CTRL 0x28
+#define DA7218_OUT_1_BIQ_5STAGE_DATA 0x29
+#define DA7218_OUT_1_BIQ_5STAGE_ADDR 0x2A
+#define DA7218_MIXIN_1_CTRL 0x2C
+#define DA7218_MIXIN_1_GAIN 0x2D
+#define DA7218_MIXIN_2_CTRL 0x2E
+#define DA7218_MIXIN_2_GAIN 0x2F
+#define DA7218_ALC_CTRL1 0x30
+#define DA7218_ALC_CTRL2 0x31
+#define DA7218_ALC_CTRL3 0x32
+#define DA7218_ALC_NOISE 0x33
+#define DA7218_ALC_TARGET_MIN 0x34
+#define DA7218_ALC_TARGET_MAX 0x35
+#define DA7218_ALC_GAIN_LIMITS 0x36
+#define DA7218_ALC_ANA_GAIN_LIMITS 0x37
+#define DA7218_ALC_ANTICLIP_CTRL 0x38
+#define DA7218_AGS_ENABLE 0x3C
+#define DA7218_AGS_TRIGGER 0x3D
+#define DA7218_AGS_ATT_MAX 0x3E
+#define DA7218_AGS_TIMEOUT 0x3F
+#define DA7218_AGS_ANTICLIP_CTRL 0x40
+#define DA7218_CALIB_CTRL 0x44
+#define DA7218_CALIB_OFFSET_AUTO_M_1 0x45
+#define DA7218_CALIB_OFFSET_AUTO_U_1 0x46
+#define DA7218_CALIB_OFFSET_AUTO_M_2 0x47
+#define DA7218_CALIB_OFFSET_AUTO_U_2 0x48
+#define DA7218_ENV_TRACK_CTRL 0x4C
+#define DA7218_LVL_DET_CTRL 0x50
+#define DA7218_LVL_DET_LEVEL 0x51
+#define DA7218_DGS_TRIGGER 0x54
+#define DA7218_DGS_ENABLE 0x55
+#define DA7218_DGS_RISE_FALL 0x56
+#define DA7218_DGS_SYNC_DELAY 0x57
+#define DA7218_DGS_SYNC_DELAY2 0x58
+#define DA7218_DGS_SYNC_DELAY3 0x59
+#define DA7218_DGS_LEVELS 0x5A
+#define DA7218_DGS_GAIN_CTRL 0x5B
+#define DA7218_DROUTING_OUTDAI_1L 0x5C
+#define DA7218_DMIX_OUTDAI_1L_INFILT_1L_GAIN 0x5D
+#define DA7218_DMIX_OUTDAI_1L_INFILT_1R_GAIN 0x5E
+#define DA7218_DMIX_OUTDAI_1L_INFILT_2L_GAIN 0x5F
+#define DA7218_DMIX_OUTDAI_1L_INFILT_2R_GAIN 0x60
+#define DA7218_DMIX_OUTDAI_1L_TONEGEN_GAIN 0x61
+#define DA7218_DMIX_OUTDAI_1L_INDAI_1L_GAIN 0x62
+#define DA7218_DMIX_OUTDAI_1L_INDAI_1R_GAIN 0x63
+#define DA7218_DROUTING_OUTDAI_1R 0x64
+#define DA7218_DMIX_OUTDAI_1R_INFILT_1L_GAIN 0x65
+#define DA7218_DMIX_OUTDAI_1R_INFILT_1R_GAIN 0x66
+#define DA7218_DMIX_OUTDAI_1R_INFILT_2L_GAIN 0x67
+#define DA7218_DMIX_OUTDAI_1R_INFILT_2R_GAIN 0x68
+#define DA7218_DMIX_OUTDAI_1R_TONEGEN_GAIN 0x69
+#define DA7218_DMIX_OUTDAI_1R_INDAI_1L_GAIN 0x6A
+#define DA7218_DMIX_OUTDAI_1R_INDAI_1R_GAIN 0x6B
+#define DA7218_DROUTING_OUTFILT_1L 0x6C
+#define DA7218_DMIX_OUTFILT_1L_INFILT_1L_GAIN 0x6D
+#define DA7218_DMIX_OUTFILT_1L_INFILT_1R_GAIN 0x6E
+#define DA7218_DMIX_OUTFILT_1L_INFILT_2L_GAIN 0x6F
+#define DA7218_DMIX_OUTFILT_1L_INFILT_2R_GAIN 0x70
+#define DA7218_DMIX_OUTFILT_1L_TONEGEN_GAIN 0x71
+#define DA7218_DMIX_OUTFILT_1L_INDAI_1L_GAIN 0x72
+#define DA7218_DMIX_OUTFILT_1L_INDAI_1R_GAIN 0x73
+#define DA7218_DROUTING_OUTFILT_1R 0x74
+#define DA7218_DMIX_OUTFILT_1R_INFILT_1L_GAIN 0x75
+#define DA7218_DMIX_OUTFILT_1R_INFILT_1R_GAIN 0x76
+#define DA7218_DMIX_OUTFILT_1R_INFILT_2L_GAIN 0x77
+#define DA7218_DMIX_OUTFILT_1R_INFILT_2R_GAIN 0x78
+#define DA7218_DMIX_OUTFILT_1R_TONEGEN_GAIN 0x79
+#define DA7218_DMIX_OUTFILT_1R_INDAI_1L_GAIN 0x7A
+#define DA7218_DMIX_OUTFILT_1R_INDAI_1R_GAIN 0x7B
+#define DA7218_DROUTING_OUTDAI_2L 0x7C
+#define DA7218_DMIX_OUTDAI_2L_INFILT_1L_GAIN 0x7D
+#define DA7218_DMIX_OUTDAI_2L_INFILT_1R_GAIN 0x7E
+#define DA7218_DMIX_OUTDAI_2L_INFILT_2L_GAIN 0x7F
+#define DA7218_DMIX_OUTDAI_2L_INFILT_2R_GAIN 0x80
+#define DA7218_DMIX_OUTDAI_2L_TONEGEN_GAIN 0x81
+#define DA7218_DMIX_OUTDAI_2L_INDAI_1L_GAIN 0x82
+#define DA7218_DMIX_OUTDAI_2L_INDAI_1R_GAIN 0x83
+#define DA7218_DROUTING_OUTDAI_2R 0x84
+#define DA7218_DMIX_OUTDAI_2R_INFILT_1L_GAIN 0x85
+#define DA7218_DMIX_OUTDAI_2R_INFILT_1R_GAIN 0x86
+#define DA7218_DMIX_OUTDAI_2R_INFILT_2L_GAIN 0x87
+#define DA7218_DMIX_OUTDAI_2R_INFILT_2R_GAIN 0x88
+#define DA7218_DMIX_OUTDAI_2R_TONEGEN_GAIN 0x89
+#define DA7218_DMIX_OUTDAI_2R_INDAI_1L_GAIN 0x8A
+#define DA7218_DMIX_OUTDAI_2R_INDAI_1R_GAIN 0x8B
+#define DA7218_DAI_CTRL 0x8C
+#define DA7218_DAI_TDM_CTRL 0x8D
+#define DA7218_DAI_OFFSET_LOWER 0x8E
+#define DA7218_DAI_OFFSET_UPPER 0x8F
+#define DA7218_DAI_CLK_MODE 0x90
+#define DA7218_PLL_CTRL 0x91
+#define DA7218_PLL_FRAC_TOP 0x92
+#define DA7218_PLL_FRAC_BOT 0x93
+#define DA7218_PLL_INTEGER 0x94
+#define DA7218_PLL_STATUS 0x95
+#define DA7218_PLL_REFOSC_CAL 0x98
+#define DA7218_DAC_NG_CTRL 0x9C
+#define DA7218_DAC_NG_SETUP_TIME 0x9D
+#define DA7218_DAC_NG_OFF_THRESH 0x9E
+#define DA7218_DAC_NG_ON_THRESH 0x9F
+#define DA7218_TONE_GEN_CFG1 0xA0
+#define DA7218_TONE_GEN_CFG2 0xA1
+#define DA7218_TONE_GEN_FREQ1_L 0xA2
+#define DA7218_TONE_GEN_FREQ1_U 0xA3
+#define DA7218_TONE_GEN_FREQ2_L 0xA4
+#define DA7218_TONE_GEN_FREQ2_U 0xA5
+#define DA7218_TONE_GEN_CYCLES 0xA6
+#define DA7218_TONE_GEN_ON_PER 0xA7
+#define DA7218_TONE_GEN_OFF_PER 0xA8
+#define DA7218_CP_CTRL 0xAC
+#define DA7218_CP_DELAY 0xAD
+#define DA7218_CP_VOL_THRESHOLD1 0xAE
+#define DA7218_MIC_1_CTRL 0xB4
+#define DA7218_MIC_1_GAIN 0xB5
+#define DA7218_MIC_1_SELECT 0xB7
+#define DA7218_MIC_2_CTRL 0xB8
+#define DA7218_MIC_2_GAIN 0xB9
+#define DA7218_MIC_2_SELECT 0xBB
+#define DA7218_IN_1_HPF_FILTER_CTRL 0xBC
+#define DA7218_IN_2_HPF_FILTER_CTRL 0xBD
+#define DA7218_ADC_1_CTRL 0xC0
+#define DA7218_ADC_2_CTRL 0xC1
+#define DA7218_ADC_MODE 0xC2
+#define DA7218_MIXOUT_L_CTRL 0xCC
+#define DA7218_MIXOUT_L_GAIN 0xCD
+#define DA7218_MIXOUT_R_CTRL 0xCE
+#define DA7218_MIXOUT_R_GAIN 0xCF
+#define DA7218_HP_L_CTRL 0xD0
+#define DA7218_HP_L_GAIN 0xD1
+#define DA7218_HP_R_CTRL 0xD2
+#define DA7218_HP_R_GAIN 0xD3
+#define DA7218_HP_SNGL_CTRL 0xD4
+#define DA7218_HP_DIFF_CTRL 0xD5
+#define DA7218_HP_DIFF_UNLOCK 0xD7
+#define DA7218_HPLDET_JACK 0xD8
+#define DA7218_HPLDET_CTRL 0xD9
+#define DA7218_HPLDET_TEST 0xDA
+#define DA7218_REFERENCES 0xDC
+#define DA7218_IO_CTRL 0xE0
+#define DA7218_LDO_CTRL 0xE1
+#define DA7218_SIDETONE_CTRL 0xE4
+#define DA7218_SIDETONE_IN_SELECT 0xE5
+#define DA7218_SIDETONE_GAIN 0xE6
+#define DA7218_DROUTING_ST_OUTFILT_1L 0xE8
+#define DA7218_DROUTING_ST_OUTFILT_1R 0xE9
+#define DA7218_SIDETONE_BIQ_3STAGE_DATA 0xEA
+#define DA7218_SIDETONE_BIQ_3STAGE_ADDR 0xEB
+#define DA7218_EVENT_STATUS 0xEC
+#define DA7218_EVENT 0xED
+#define DA7218_EVENT_MASK 0xEE
+#define DA7218_DMIC_1_CTRL 0xF0
+#define DA7218_DMIC_2_CTRL 0xF1
+#define DA7218_IN_1L_GAIN 0xF4
+#define DA7218_IN_1R_GAIN 0xF5
+#define DA7218_IN_2L_GAIN 0xF6
+#define DA7218_IN_2R_GAIN 0xF7
+#define DA7218_OUT_1L_GAIN 0xF8
+#define DA7218_OUT_1R_GAIN 0xF9
+#define DA7218_MICBIAS_CTRL 0xFC
+#define DA7218_MICBIAS_EN 0xFD
+
+
+/*
+ * Bit Fields
+ */
+
+#define DA7218_SWITCH_EN_MAX 0x1
+
+/* DA7218_SYSTEM_ACTIVE = 0x0 */
+#define DA7218_SYSTEM_ACTIVE_SHIFT 0
+#define DA7218_SYSTEM_ACTIVE_MASK (0x1 << 0)
+
+/* DA7218_CIF_CTRL = 0x1 */
+#define DA7218_CIF_I2C_WRITE_MODE_SHIFT 0
+#define DA7218_CIF_I2C_WRITE_MODE_MASK (0x1 << 0)
+
+/* DA7218_CHIP_ID1 = 0x4 */
+#define DA7218_CHIP_ID1_SHIFT 0
+#define DA7218_CHIP_ID1_MASK (0xFF << 0)
+
+/* DA7218_CHIP_ID2 = 0x5 */
+#define DA7218_CHIP_ID2_SHIFT 0
+#define DA7218_CHIP_ID2_MASK (0xFF << 0)
+
+/* DA7218_CHIP_REVISION = 0x6 */
+#define DA7218_CHIP_MINOR_SHIFT 0
+#define DA7218_CHIP_MINOR_MASK (0xF << 0)
+#define DA7218_CHIP_MAJOR_SHIFT 4
+#define DA7218_CHIP_MAJOR_MASK (0xF << 4)
+
+/* DA7218_SPARE1 = 0x7 */
+#define DA7218_SPARE1_SHIFT 0
+#define DA7218_SPARE1_MASK (0xFF << 0)
+
+/* DA7218_STATUS1 = 0x8 */
+#define DA7218_STATUS_SPARE1_SHIFT 0
+#define DA7218_STATUS_SPARE1_MASK (0xFF << 0)
+
+/* DA7218_SOFT_RESET = 0x9 */
+#define DA7218_CIF_REG_SOFT_RESET_SHIFT 7
+#define DA7218_CIF_REG_SOFT_RESET_MASK (0x1 << 7)
+
+/* DA7218_SR = 0xB */
+#define DA7218_SR_ADC_SHIFT 0
+#define DA7218_SR_ADC_MASK (0xF << 0)
+#define DA7218_SR_DAC_SHIFT 4
+#define DA7218_SR_DAC_MASK (0xF << 4)
+#define DA7218_SR_8000 0x01
+#define DA7218_SR_11025 0x02
+#define DA7218_SR_12000 0x03
+#define DA7218_SR_16000 0x05
+#define DA7218_SR_22050 0x06
+#define DA7218_SR_24000 0x07
+#define DA7218_SR_32000 0x09
+#define DA7218_SR_44100 0x0A
+#define DA7218_SR_48000 0x0B
+#define DA7218_SR_88200 0x0E
+#define DA7218_SR_96000 0x0F
+
+/* DA7218_PC_COUNT = 0xC */
+#define DA7218_PC_FREERUN_SHIFT 0
+#define DA7218_PC_FREERUN_MASK (0x1 << 0)
+#define DA7218_PC_RESYNC_AUTO_SHIFT 1
+#define DA7218_PC_RESYNC_AUTO_MASK (0x1 << 1)
+
+/* DA7218_GAIN_RAMP_CTRL = 0xD */
+#define DA7218_GAIN_RAMP_RATE_SHIFT 0
+#define DA7218_GAIN_RAMP_RATE_MASK (0x3 << 0)
+#define DA7218_GAIN_RAMP_RATE_MAX 4
+
+/* DA7218_CIF_TIMEOUT_CTRL = 0x10 */
+#define DA7218_I2C_TIMEOUT_EN_SHIFT 0
+#define DA7218_I2C_TIMEOUT_EN_MASK (0x1 << 0)
+
+/* DA7218_SYSTEM_MODES_INPUT = 0x14 */
+#define DA7218_MODE_SUBMIT_SHIFT 0
+#define DA7218_MODE_SUBMIT_MASK (0x1 << 0)
+#define DA7218_ADC_MODE_SHIFT 1
+#define DA7218_ADC_MODE_MASK (0x7F << 1)
+
+/* DA7218_SYSTEM_MODES_OUTPUT = 0x15 */
+#define DA7218_MODE_SUBMIT_SHIFT 0
+#define DA7218_MODE_SUBMIT_MASK (0x1 << 0)
+#define DA7218_DAC_MODE_SHIFT 1
+#define DA7218_DAC_MODE_MASK (0x7F << 1)
+
+/* DA7218_SYSTEM_STATUS = 0x16 */
+#define DA7218_SC1_BUSY_SHIFT 0
+#define DA7218_SC1_BUSY_MASK (0x1 << 0)
+#define DA7218_SC2_BUSY_SHIFT 1
+#define DA7218_SC2_BUSY_MASK (0x1 << 1)
+
+/* DA7218_IN_1L_FILTER_CTRL = 0x18 */
+#define DA7218_IN_1L_RAMP_EN_SHIFT 5
+#define DA7218_IN_1L_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_IN_1L_MUTE_EN_SHIFT 6
+#define DA7218_IN_1L_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_IN_1L_FILTER_EN_SHIFT 7
+#define DA7218_IN_1L_FILTER_EN_MASK (0x1 << 7)
+
+/* DA7218_IN_1R_FILTER_CTRL = 0x19 */
+#define DA7218_IN_1R_RAMP_EN_SHIFT 5
+#define DA7218_IN_1R_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_IN_1R_MUTE_EN_SHIFT 6
+#define DA7218_IN_1R_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_IN_1R_FILTER_EN_SHIFT 7
+#define DA7218_IN_1R_FILTER_EN_MASK (0x1 << 7)
+
+/* DA7218_IN_2L_FILTER_CTRL = 0x1A */
+#define DA7218_IN_2L_RAMP_EN_SHIFT 5
+#define DA7218_IN_2L_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_IN_2L_MUTE_EN_SHIFT 6
+#define DA7218_IN_2L_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_IN_2L_FILTER_EN_SHIFT 7
+#define DA7218_IN_2L_FILTER_EN_MASK (0x1 << 7)
+
+/* DA7218_IN_2R_FILTER_CTRL = 0x1B */
+#define DA7218_IN_2R_RAMP_EN_SHIFT 5
+#define DA7218_IN_2R_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_IN_2R_MUTE_EN_SHIFT 6
+#define DA7218_IN_2R_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_IN_2R_FILTER_EN_SHIFT 7
+#define DA7218_IN_2R_FILTER_EN_MASK (0x1 << 7)
+
+/* DA7218_OUT_1L_FILTER_CTRL = 0x20 */
+#define DA7218_OUT_1L_BIQ_5STAGE_SEL_SHIFT 3
+#define DA7218_OUT_1L_BIQ_5STAGE_SEL_MASK (0x1 << 3)
+#define DA7218_OUT_BIQ_5STAGE_SEL_MAX 2
+#define DA7218_OUT_1L_SUBRANGE_EN_SHIFT 4
+#define DA7218_OUT_1L_SUBRANGE_EN_MASK (0x1 << 4)
+#define DA7218_OUT_1L_RAMP_EN_SHIFT 5
+#define DA7218_OUT_1L_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_OUT_1L_MUTE_EN_SHIFT 6
+#define DA7218_OUT_1L_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_OUT_1L_FILTER_EN_SHIFT 7
+#define DA7218_OUT_1L_FILTER_EN_MASK (0x1 << 7)
+
+/* DA7218_OUT_1R_FILTER_CTRL = 0x21 */
+#define DA7218_OUT_1R_BIQ_5STAGE_SEL_SHIFT 3
+#define DA7218_OUT_1R_BIQ_5STAGE_SEL_MASK (0x1 << 3)
+#define DA7218_OUT_1R_SUBRANGE_EN_SHIFT 4
+#define DA7218_OUT_1R_SUBRANGE_EN_MASK (0x1 << 4)
+#define DA7218_OUT_1R_RAMP_EN_SHIFT 5
+#define DA7218_OUT_1R_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_OUT_1R_MUTE_EN_SHIFT 6
+#define DA7218_OUT_1R_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_OUT_1R_FILTER_EN_SHIFT 7
+#define DA7218_OUT_1R_FILTER_EN_MASK (0x1 << 7)
+
+/* DA7218_OUT_1_HPF_FILTER_CTRL = 0x24 */
+#define DA7218_OUT_1_VOICE_HPF_CORNER_SHIFT 0
+#define DA7218_OUT_1_VOICE_HPF_CORNER_MASK (0x7 << 0)
+#define DA7218_VOICE_HPF_CORNER_MAX 8
+#define DA7218_OUT_1_VOICE_EN_SHIFT 3
+#define DA7218_OUT_1_VOICE_EN_MASK (0x1 << 3)
+#define DA7218_OUT_1_AUDIO_HPF_CORNER_SHIFT 4
+#define DA7218_OUT_1_AUDIO_HPF_CORNER_MASK (0x3 << 4)
+#define DA7218_AUDIO_HPF_CORNER_MAX 4
+#define DA7218_OUT_1_HPF_EN_SHIFT 7
+#define DA7218_OUT_1_HPF_EN_MASK (0x1 << 7)
+#define DA7218_HPF_MODE_SHIFT 0
+#define DA7218_HPF_DISABLED ((0x0 << 3) | (0x0 << 7))
+#define DA7218_HPF_AUDIO_EN ((0x0 << 3) | (0x1 << 7))
+#define DA7218_HPF_VOICE_EN ((0x1 << 3) | (0x1 << 7))
+#define DA7218_HPF_MODE_MASK ((0x1 << 3) | (0x1 << 7))
+#define DA7218_HPF_MODE_MAX 3
+
+/* DA7218_OUT_1_EQ_12_FILTER_CTRL = 0x25 */
+#define DA7218_OUT_1_EQ_BAND1_SHIFT 0
+#define DA7218_OUT_1_EQ_BAND1_MASK (0xF << 0)
+#define DA7218_OUT_EQ_BAND_MAX 0xF
+#define DA7218_OUT_1_EQ_BAND2_SHIFT 4
+#define DA7218_OUT_1_EQ_BAND2_MASK (0xF << 4)
+
+/* DA7218_OUT_1_EQ_34_FILTER_CTRL = 0x26 */
+#define DA7218_OUT_1_EQ_BAND3_SHIFT 0
+#define DA7218_OUT_1_EQ_BAND3_MASK (0xF << 0)
+#define DA7218_OUT_1_EQ_BAND4_SHIFT 4
+#define DA7218_OUT_1_EQ_BAND4_MASK (0xF << 4)
+
+/* DA7218_OUT_1_EQ_5_FILTER_CTRL = 0x27 */
+#define DA7218_OUT_1_EQ_BAND5_SHIFT 0
+#define DA7218_OUT_1_EQ_BAND5_MASK (0xF << 0)
+#define DA7218_OUT_1_EQ_EN_SHIFT 7
+#define DA7218_OUT_1_EQ_EN_MASK (0x1 << 7)
+
+/* DA7218_OUT_1_BIQ_5STAGE_CTRL = 0x28 */
+#define DA7218_OUT_1_BIQ_5STAGE_MUTE_EN_SHIFT 6
+#define DA7218_OUT_1_BIQ_5STAGE_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_OUT_1_BIQ_5STAGE_FILTER_EN_SHIFT 7
+#define DA7218_OUT_1_BIQ_5STAGE_FILTER_EN_MASK (0x1 << 7)
+
+/* DA7218_OUT_1_BIQ_5STAGE_DATA = 0x29 */
+#define DA7218_OUT_1_BIQ_5STAGE_DATA_SHIFT 0
+#define DA7218_OUT_1_BIQ_5STAGE_DATA_MASK (0xFF << 0)
+
+/* DA7218_OUT_1_BIQ_5STAGE_ADDR = 0x2A */
+#define DA7218_OUT_1_BIQ_5STAGE_ADDR_SHIFT 0
+#define DA7218_OUT_1_BIQ_5STAGE_ADDR_MASK (0x3F << 0)
+#define DA7218_OUT_1_BIQ_5STAGE_CFG_SIZE 50
+
+/* DA7218_MIXIN_1_CTRL = 0x2C */
+#define DA7218_MIXIN_1_MIX_SEL_SHIFT 3
+#define DA7218_MIXIN_1_MIX_SEL_MASK (0x1 << 3)
+#define DA7218_MIXIN_1_AMP_ZC_EN_SHIFT 4
+#define DA7218_MIXIN_1_AMP_ZC_EN_MASK (0x1 << 4)
+#define DA7218_MIXIN_1_AMP_RAMP_EN_SHIFT 5
+#define DA7218_MIXIN_1_AMP_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_MIXIN_1_AMP_MUTE_EN_SHIFT 6
+#define DA7218_MIXIN_1_AMP_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_MIXIN_1_AMP_EN_SHIFT 7
+#define DA7218_MIXIN_1_AMP_EN_MASK (0x1 << 7)
+
+/* DA7218_MIXIN_1_GAIN = 0x2D */
+#define DA7218_MIXIN_1_AMP_GAIN_SHIFT 0
+#define DA7218_MIXIN_1_AMP_GAIN_MASK (0xF << 0)
+#define DA7218_MIXIN_AMP_GAIN_MAX 0xF
+
+/* DA7218_MIXIN_2_CTRL = 0x2E */
+#define DA7218_MIXIN_2_MIX_SEL_SHIFT 3
+#define DA7218_MIXIN_2_MIX_SEL_MASK (0x1 << 3)
+#define DA7218_MIXIN_2_AMP_ZC_EN_SHIFT 4
+#define DA7218_MIXIN_2_AMP_ZC_EN_MASK (0x1 << 4)
+#define DA7218_MIXIN_2_AMP_RAMP_EN_SHIFT 5
+#define DA7218_MIXIN_2_AMP_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_MIXIN_2_AMP_MUTE_EN_SHIFT 6
+#define DA7218_MIXIN_2_AMP_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_MIXIN_2_AMP_EN_SHIFT 7
+#define DA7218_MIXIN_2_AMP_EN_MASK (0x1 << 7)
+
+/* DA7218_MIXIN_2_GAIN = 0x2F */
+#define DA7218_MIXIN_2_AMP_GAIN_SHIFT 0
+#define DA7218_MIXIN_2_AMP_GAIN_MASK (0xF << 0)
+
+/* DA7218_ALC_CTRL1 = 0x30 */
+#define DA7218_ALC_EN_SHIFT 0
+#define DA7218_ALC_EN_MASK (0xF << 0)
+#define DA7218_ALC_CHAN1_L_EN_SHIFT 0
+#define DA7218_ALC_CHAN1_R_EN_SHIFT 1
+#define DA7218_ALC_CHAN2_L_EN_SHIFT 2
+#define DA7218_ALC_CHAN2_R_EN_SHIFT 3
+#define DA7218_ALC_SYNC_MODE_SHIFT 4
+#define DA7218_ALC_SYNC_MODE_MASK (0xF << 4)
+#define DA7218_ALC_SYNC_MODE_CH1 (0x1 << 4)
+#define DA7218_ALC_SYNC_MODE_CH2 (0x4 << 4)
+
+/* DA7218_ALC_CTRL2 = 0x31 */
+#define DA7218_ALC_ATTACK_SHIFT 0
+#define DA7218_ALC_ATTACK_MASK (0xF << 0)
+#define DA7218_ALC_ATTACK_MAX 13
+#define DA7218_ALC_RELEASE_SHIFT 4
+#define DA7218_ALC_RELEASE_MASK (0xF << 4)
+#define DA7218_ALC_RELEASE_MAX 11
+
+/* DA7218_ALC_CTRL3 = 0x32 */
+#define DA7218_ALC_HOLD_SHIFT 0
+#define DA7218_ALC_HOLD_MASK (0xF << 0)
+#define DA7218_ALC_HOLD_MAX 16
+
+/* DA7218_ALC_NOISE = 0x33 */
+#define DA7218_ALC_NOISE_SHIFT 0
+#define DA7218_ALC_NOISE_MASK (0x3F << 0)
+#define DA7218_ALC_THRESHOLD_MAX 0x3F
+
+/* DA7218_ALC_TARGET_MIN = 0x34 */
+#define DA7218_ALC_THRESHOLD_MIN_SHIFT 0
+#define DA7218_ALC_THRESHOLD_MIN_MASK (0x3F << 0)
+
+/* DA7218_ALC_TARGET_MAX = 0x35 */
+#define DA7218_ALC_THRESHOLD_MAX_SHIFT 0
+#define DA7218_ALC_THRESHOLD_MAX_MASK (0x3F << 0)
+
+/* DA7218_ALC_GAIN_LIMITS = 0x36 */
+#define DA7218_ALC_ATTEN_MAX_SHIFT 0
+#define DA7218_ALC_ATTEN_MAX_MASK (0xF << 0)
+#define DA7218_ALC_ATTEN_GAIN_MAX 0xF
+#define DA7218_ALC_GAIN_MAX_SHIFT 4
+#define DA7218_ALC_GAIN_MAX_MASK (0xF << 4)
+
+/* DA7218_ALC_ANA_GAIN_LIMITS = 0x37 */
+#define DA7218_ALC_ANA_GAIN_MIN_SHIFT 0
+#define DA7218_ALC_ANA_GAIN_MIN_MASK (0x7 << 0)
+#define DA7218_ALC_ANA_GAIN_MIN 0x1
+#define DA7218_ALC_ANA_GAIN_MAX 0x7
+#define DA7218_ALC_ANA_GAIN_MAX_SHIFT 4
+#define DA7218_ALC_ANA_GAIN_MAX_MASK (0x7 << 4)
+
+/* DA7218_ALC_ANTICLIP_CTRL = 0x38 */
+#define DA7218_ALC_ANTICLIP_STEP_SHIFT 0
+#define DA7218_ALC_ANTICLIP_STEP_MASK (0x3 << 0)
+#define DA7218_ALC_ANTICLIP_STEP_MAX 4
+#define DA7218_ALC_ANTICLIP_EN_SHIFT 7
+#define DA7218_ALC_ANTICLIP_EN_MASK (0x1 << 7)
+
+/* DA7218_AGS_ENABLE = 0x3C */
+#define DA7218_AGS_ENABLE_SHIFT 0
+#define DA7218_AGS_ENABLE_MASK (0x3 << 0)
+#define DA7218_AGS_ENABLE_CHAN1_SHIFT 0
+#define DA7218_AGS_ENABLE_CHAN2_SHIFT 1
+
+/* DA7218_AGS_TRIGGER = 0x3D */
+#define DA7218_AGS_TRIGGER_SHIFT 0
+#define DA7218_AGS_TRIGGER_MASK (0xF << 0)
+#define DA7218_AGS_TRIGGER_MAX 0xF
+
+/* DA7218_AGS_ATT_MAX = 0x3E */
+#define DA7218_AGS_ATT_MAX_SHIFT 0
+#define DA7218_AGS_ATT_MAX_MASK (0x7 << 0)
+#define DA7218_AGS_ATT_MAX_MAX 0x7
+
+/* DA7218_AGS_TIMEOUT = 0x3F */
+#define DA7218_AGS_TIMEOUT_EN_SHIFT 0
+#define DA7218_AGS_TIMEOUT_EN_MASK (0x1 << 0)
+
+/* DA7218_AGS_ANTICLIP_CTRL = 0x40 */
+#define DA7218_AGS_ANTICLIP_EN_SHIFT 7
+#define DA7218_AGS_ANTICLIP_EN_MASK (0x1 << 7)
+
+/* DA7218_CALIB_CTRL = 0x44 */
+#define DA7218_CALIB_OFFSET_EN_SHIFT 0
+#define DA7218_CALIB_OFFSET_EN_MASK (0x1 << 0)
+#define DA7218_CALIB_AUTO_EN_SHIFT 2
+#define DA7218_CALIB_AUTO_EN_MASK (0x1 << 2)
+#define DA7218_CALIB_OVERFLOW_SHIFT 3
+#define DA7218_CALIB_OVERFLOW_MASK (0x1 << 3)
+
+/* DA7218_CALIB_OFFSET_AUTO_M_1 = 0x45 */
+#define DA7218_CALIB_OFFSET_AUTO_M_1_SHIFT 0
+#define DA7218_CALIB_OFFSET_AUTO_M_1_MASK (0xFF << 0)
+
+/* DA7218_CALIB_OFFSET_AUTO_U_1 = 0x46 */
+#define DA7218_CALIB_OFFSET_AUTO_U_1_SHIFT 0
+#define DA7218_CALIB_OFFSET_AUTO_U_1_MASK (0xF << 0)
+
+/* DA7218_CALIB_OFFSET_AUTO_M_2 = 0x47 */
+#define DA7218_CALIB_OFFSET_AUTO_M_2_SHIFT 0
+#define DA7218_CALIB_OFFSET_AUTO_M_2_MASK (0xFF << 0)
+
+/* DA7218_CALIB_OFFSET_AUTO_U_2 = 0x48 */
+#define DA7218_CALIB_OFFSET_AUTO_U_2_SHIFT 0
+#define DA7218_CALIB_OFFSET_AUTO_U_2_MASK (0xF << 0)
+
+/* DA7218_ENV_TRACK_CTRL = 0x4C */
+#define DA7218_INTEG_ATTACK_SHIFT 0
+#define DA7218_INTEG_ATTACK_MASK (0x3 << 0)
+#define DA7218_INTEG_RELEASE_SHIFT 4
+#define DA7218_INTEG_RELEASE_MASK (0x3 << 4)
+#define DA7218_INTEG_MAX 4
+
+/* DA7218_LVL_DET_CTRL = 0x50 */
+#define DA7218_LVL_DET_EN_SHIFT 0
+#define DA7218_LVL_DET_EN_MASK (0xF << 0)
+#define DA7218_LVL_DET_EN_CHAN1L_SHIFT 0
+#define DA7218_LVL_DET_EN_CHAN1R_SHIFT 1
+#define DA7218_LVL_DET_EN_CHAN2L_SHIFT 2
+#define DA7218_LVL_DET_EN_CHAN2R_SHIFT 3
+
+/* DA7218_LVL_DET_LEVEL = 0x51 */
+#define DA7218_LVL_DET_LEVEL_SHIFT 0
+#define DA7218_LVL_DET_LEVEL_MASK (0x7F << 0)
+#define DA7218_LVL_DET_LEVEL_MAX 0x7F
+
+/* DA7218_DGS_TRIGGER = 0x54 */
+#define DA7218_DGS_TRIGGER_LVL_SHIFT 0
+#define DA7218_DGS_TRIGGER_LVL_MASK (0x3F << 0)
+#define DA7218_DGS_TRIGGER_MAX 0x3F
+
+/* DA7218_DGS_ENABLE = 0x55 */
+#define DA7218_DGS_ENABLE_SHIFT 0
+#define DA7218_DGS_ENABLE_MASK (0x3 << 0)
+#define DA7218_DGS_ENABLE_L_SHIFT 0
+#define DA7218_DGS_ENABLE_R_SHIFT 1
+
+/* DA7218_DGS_RISE_FALL = 0x56 */
+#define DA7218_DGS_RISE_COEFF_SHIFT 0
+#define DA7218_DGS_RISE_COEFF_MASK (0x7 << 0)
+#define DA7218_DGS_RISE_COEFF_MAX 7
+#define DA7218_DGS_FALL_COEFF_SHIFT 4
+#define DA7218_DGS_FALL_COEFF_MASK (0x7 << 4)
+#define DA7218_DGS_FALL_COEFF_MAX 8
+
+/* DA7218_DGS_SYNC_DELAY = 0x57 */
+#define DA7218_DGS_SYNC_DELAY_SHIFT 0
+#define DA7218_DGS_SYNC_DELAY_MASK (0xFF << 0)
+#define DA7218_DGS_SYNC_DELAY_MAX 0xFF
+
+/* DA7218_DGS_SYNC_DELAY2 = 0x58 */
+#define DA7218_DGS_SYNC_DELAY2_SHIFT 0
+#define DA7218_DGS_SYNC_DELAY2_MASK (0xFF << 0)
+
+/* DA7218_DGS_SYNC_DELAY3 = 0x59 */
+#define DA7218_DGS_SYNC_DELAY3_SHIFT 0
+#define DA7218_DGS_SYNC_DELAY3_MASK (0x7F << 0)
+#define DA7218_DGS_SYNC_DELAY3_MAX 0x7F
+
+/* DA7218_DGS_LEVELS = 0x5A */
+#define DA7218_DGS_ANTICLIP_LVL_SHIFT 0
+#define DA7218_DGS_ANTICLIP_LVL_MASK (0x7 << 0)
+#define DA7218_DGS_ANTICLIP_LVL_MAX 0x7
+#define DA7218_DGS_SIGNAL_LVL_SHIFT 4
+#define DA7218_DGS_SIGNAL_LVL_MASK (0xF << 4)
+#define DA7218_DGS_SIGNAL_LVL_MAX 0xF
+
+/* DA7218_DGS_GAIN_CTRL = 0x5B */
+#define DA7218_DGS_STEPS_SHIFT 0
+#define DA7218_DGS_STEPS_MASK (0x1F << 0)
+#define DA7218_DGS_STEPS_MAX 0x1F
+#define DA7218_DGS_RAMP_EN_SHIFT 5
+#define DA7218_DGS_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_DGS_SUBR_EN_SHIFT 6
+#define DA7218_DGS_SUBR_EN_MASK (0x1 << 6)
+
+/* DA7218_DROUTING_OUTDAI_1L = 0x5C */
+#define DA7218_OUTDAI_1L_SRC_SHIFT 0
+#define DA7218_OUTDAI_1L_SRC_MASK (0x7F << 0)
+#define DA7218_DMIX_SRC_INFILT1L 0
+#define DA7218_DMIX_SRC_INFILT1R 1
+#define DA7218_DMIX_SRC_INFILT2L 2
+#define DA7218_DMIX_SRC_INFILT2R 3
+#define DA7218_DMIX_SRC_TONEGEN 4
+#define DA7218_DMIX_SRC_DAIL 5
+#define DA7218_DMIX_SRC_DAIR 6
+
+/* DA7218_DMIX_OUTDAI_1L_INFILT_1L_GAIN = 0x5D */
+#define DA7218_OUTDAI_1L_INFILT_1L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1L_INFILT_1L_GAIN_MASK (0x1F << 0)
+#define DA7218_DMIX_GAIN_MAX 0x1F
+
+/* DA7218_DMIX_OUTDAI_1L_INFILT_1R_GAIN = 0x5E */
+#define DA7218_OUTDAI_1L_INFILT_1R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1L_INFILT_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1L_INFILT_2L_GAIN = 0x5F */
+#define DA7218_OUTDAI_1L_INFILT_2L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1L_INFILT_2L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1L_INFILT_2R_GAIN = 0x60 */
+#define DA7218_OUTDAI_1L_INFILT_2R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1L_INFILT_2R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1L_TONEGEN_GAIN = 0x61 */
+#define DA7218_OUTDAI_1L_TONEGEN_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1L_TONEGEN_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1L_INDAI_1L_GAIN = 0x62 */
+#define DA7218_OUTDAI_1L_INDAI_1L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1L_INDAI_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1L_INDAI_1R_GAIN = 0x63 */
+#define DA7218_OUTDAI_1L_INDAI_1R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1L_INDAI_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DROUTING_OUTDAI_1R = 0x64 */
+#define DA7218_OUTDAI_1R_SRC_SHIFT 0
+#define DA7218_OUTDAI_1R_SRC_MASK (0x7F << 0)
+
+/* DA7218_DMIX_OUTDAI_1R_INFILT_1L_GAIN = 0x65 */
+#define DA7218_OUTDAI_1R_INFILT_1L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1R_INFILT_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1R_INFILT_1R_GAIN = 0x66 */
+#define DA7218_OUTDAI_1R_INFILT_1R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1R_INFILT_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1R_INFILT_2L_GAIN = 0x67 */
+#define DA7218_OUTDAI_1R_INFILT_2L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1R_INFILT_2L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1R_INFILT_2R_GAIN = 0x68 */
+#define DA7218_OUTDAI_1R_INFILT_2R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1R_INFILT_2R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1R_TONEGEN_GAIN = 0x69 */
+#define DA7218_OUTDAI_1R_TONEGEN_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1R_TONEGEN_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1R_INDAI_1L_GAIN = 0x6A */
+#define DA7218_OUTDAI_1R_INDAI_1L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1R_INDAI_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_1R_INDAI_1R_GAIN = 0x6B */
+#define DA7218_OUTDAI_1R_INDAI_1R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_1R_INDAI_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DROUTING_OUTFILT_1L = 0x6C */
+#define DA7218_OUTFILT_1L_SRC_SHIFT 0
+#define DA7218_OUTFILT_1L_SRC_MASK (0x7F << 0)
+
+/* DA7218_DMIX_OUTFILT_1L_INFILT_1L_GAIN = 0x6D */
+#define DA7218_OUTFILT_1L_INFILT_1L_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1L_INFILT_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1L_INFILT_1R_GAIN = 0x6E */
+#define DA7218_OUTFILT_1L_INFILT_1R_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1L_INFILT_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1L_INFILT_2L_GAIN = 0x6F */
+#define DA7218_OUTFILT_1L_INFILT_2L_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1L_INFILT_2L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1L_INFILT_2R_GAIN = 0x70 */
+#define DA7218_OUTFILT_1L_INFILT_2R_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1L_INFILT_2R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1L_TONEGEN_GAIN = 0x71 */
+#define DA7218_OUTFILT_1L_TONEGEN_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1L_TONEGEN_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1L_INDAI_1L_GAIN = 0x72 */
+#define DA7218_OUTFILT_1L_INDAI_1L_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1L_INDAI_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1L_INDAI_1R_GAIN = 0x73 */
+#define DA7218_OUTFILT_1L_INDAI_1R_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1L_INDAI_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DROUTING_OUTFILT_1R = 0x74 */
+#define DA7218_OUTFILT_1R_SRC_SHIFT 0
+#define DA7218_OUTFILT_1R_SRC_MASK (0x7F << 0)
+
+/* DA7218_DMIX_OUTFILT_1R_INFILT_1L_GAIN = 0x75 */
+#define DA7218_OUTFILT_1R_INFILT_1L_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1R_INFILT_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1R_INFILT_1R_GAIN = 0x76 */
+#define DA7218_OUTFILT_1R_INFILT_1R_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1R_INFILT_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1R_INFILT_2L_GAIN = 0x77 */
+#define DA7218_OUTFILT_1R_INFILT_2L_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1R_INFILT_2L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1R_INFILT_2R_GAIN = 0x78 */
+#define DA7218_OUTFILT_1R_INFILT_2R_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1R_INFILT_2R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1R_TONEGEN_GAIN = 0x79 */
+#define DA7218_OUTFILT_1R_TONEGEN_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1R_TONEGEN_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1R_INDAI_1L_GAIN = 0x7A */
+#define DA7218_OUTFILT_1R_INDAI_1L_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1R_INDAI_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTFILT_1R_INDAI_1R_GAIN = 0x7B */
+#define DA7218_OUTFILT_1R_INDAI_1R_GAIN_SHIFT 0
+#define DA7218_OUTFILT_1R_INDAI_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DROUTING_OUTDAI_2L = 0x7C */
+#define DA7218_OUTDAI_2L_SRC_SHIFT 0
+#define DA7218_OUTDAI_2L_SRC_MASK (0x7F << 0)
+
+/* DA7218_DMIX_OUTDAI_2L_INFILT_1L_GAIN = 0x7D */
+#define DA7218_OUTDAI_2L_INFILT_1L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2L_INFILT_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2L_INFILT_1R_GAIN = 0x7E */
+#define DA7218_OUTDAI_2L_INFILT_1R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2L_INFILT_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2L_INFILT_2L_GAIN = 0x7F */
+#define DA7218_OUTDAI_2L_INFILT_2L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2L_INFILT_2L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2L_INFILT_2R_GAIN = 0x80 */
+#define DA7218_OUTDAI_2L_INFILT_2R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2L_INFILT_2R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2L_TONEGEN_GAIN = 0x81 */
+#define DA7218_OUTDAI_2L_TONEGEN_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2L_TONEGEN_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2L_INDAI_1L_GAIN = 0x82 */
+#define DA7218_OUTDAI_2L_INDAI_1L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2L_INDAI_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2L_INDAI_1R_GAIN = 0x83 */
+#define DA7218_OUTDAI_2L_INDAI_1R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2L_INDAI_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DROUTING_OUTDAI_2R = 0x84 */
+#define DA7218_OUTDAI_2R_SRC_SHIFT 0
+#define DA7218_OUTDAI_2R_SRC_MASK (0x7F << 0)
+
+/* DA7218_DMIX_OUTDAI_2R_INFILT_1L_GAIN = 0x85 */
+#define DA7218_OUTDAI_2R_INFILT_1L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2R_INFILT_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2R_INFILT_1R_GAIN = 0x86 */
+#define DA7218_OUTDAI_2R_INFILT_1R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2R_INFILT_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2R_INFILT_2L_GAIN = 0x87 */
+#define DA7218_OUTDAI_2R_INFILT_2L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2R_INFILT_2L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2R_INFILT_2R_GAIN = 0x88 */
+#define DA7218_OUTDAI_2R_INFILT_2R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2R_INFILT_2R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2R_TONEGEN_GAIN = 0x89 */
+#define DA7218_OUTDAI_2R_TONEGEN_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2R_TONEGEN_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2R_INDAI_1L_GAIN = 0x8A */
+#define DA7218_OUTDAI_2R_INDAI_1L_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2R_INDAI_1L_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DMIX_OUTDAI_2R_INDAI_1R_GAIN = 0x8B */
+#define DA7218_OUTDAI_2R_INDAI_1R_GAIN_SHIFT 0
+#define DA7218_OUTDAI_2R_INDAI_1R_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DAI_CTRL = 0x8C */
+#define DA7218_DAI_FORMAT_SHIFT 0
+#define DA7218_DAI_FORMAT_MASK (0x3 << 0)
+#define DA7218_DAI_FORMAT_I2S (0x0 << 0)
+#define DA7218_DAI_FORMAT_LEFT_J (0x1 << 0)
+#define DA7218_DAI_FORMAT_RIGHT_J (0x2 << 0)
+#define DA7218_DAI_FORMAT_DSP (0x3 << 0)
+#define DA7218_DAI_WORD_LENGTH_SHIFT 2
+#define DA7218_DAI_WORD_LENGTH_MASK (0x3 << 2)
+#define DA7218_DAI_WORD_LENGTH_S16_LE (0x0 << 2)
+#define DA7218_DAI_WORD_LENGTH_S20_LE (0x1 << 2)
+#define DA7218_DAI_WORD_LENGTH_S24_LE (0x2 << 2)
+#define DA7218_DAI_WORD_LENGTH_S32_LE (0x3 << 2)
+#define DA7218_DAI_CH_NUM_SHIFT 4
+#define DA7218_DAI_CH_NUM_MASK (0x7 << 4)
+#define DA7218_DAI_CH_NUM_MAX 4
+#define DA7218_DAI_EN_SHIFT 7
+#define DA7218_DAI_EN_MASK (0x1 << 7)
+
+/* DA7218_DAI_TDM_CTRL = 0x8D */
+#define DA7218_DAI_TDM_CH_EN_SHIFT 0
+#define DA7218_DAI_TDM_CH_EN_MASK (0xF << 0)
+#define DA7218_DAI_TDM_MAX_SLOTS 4
+#define DA7218_DAI_OE_SHIFT 6
+#define DA7218_DAI_OE_MASK (0x1 << 6)
+#define DA7218_DAI_TDM_MODE_EN_SHIFT 7
+#define DA7218_DAI_TDM_MODE_EN_MASK (0x1 << 7)
+
+/* DA7218_DAI_OFFSET_LOWER = 0x8E */
+#define DA7218_DAI_OFFSET_LOWER_SHIFT 0
+#define DA7218_DAI_OFFSET_LOWER_MASK (0xFF << 0)
+
+/* DA7218_DAI_OFFSET_UPPER = 0x8F */
+#define DA7218_DAI_OFFSET_UPPER_SHIFT 0
+#define DA7218_DAI_OFFSET_UPPER_MASK (0x7 << 0)
+
+/* DA7218_DAI_CLK_MODE = 0x90 */
+#define DA7218_DAI_BCLKS_PER_WCLK_SHIFT 0
+#define DA7218_DAI_BCLKS_PER_WCLK_MASK (0x3 << 0)
+#define DA7218_DAI_BCLKS_PER_WCLK_32 (0x0 << 0)
+#define DA7218_DAI_BCLKS_PER_WCLK_64 (0x1 << 0)
+#define DA7218_DAI_BCLKS_PER_WCLK_128 (0x2 << 0)
+#define DA7218_DAI_BCLKS_PER_WCLK_256 (0x3 << 0)
+#define DA7218_DAI_CLK_POL_SHIFT 2
+#define DA7218_DAI_CLK_POL_MASK (0x1 << 2)
+#define DA7218_DAI_CLK_POL_INV (0x1 << 2)
+#define DA7218_DAI_WCLK_POL_SHIFT 3
+#define DA7218_DAI_WCLK_POL_MASK (0x1 << 3)
+#define DA7218_DAI_WCLK_POL_INV (0x1 << 3)
+#define DA7218_DAI_WCLK_TRI_STATE_SHIFT 4
+#define DA7218_DAI_WCLK_TRI_STATE_MASK (0x1 << 4)
+#define DA7218_DAI_CLK_EN_SHIFT 7
+#define DA7218_DAI_CLK_EN_MASK (0x1 << 7)
+
+/* DA7218_PLL_CTRL = 0x91 */
+#define DA7218_PLL_INDIV_SHIFT 0
+#define DA7218_PLL_INDIV_MASK (0x7 << 0)
+#define DA7218_PLL_INDIV_2_5_MHZ (0x0 << 0)
+#define DA7218_PLL_INDIV_5_10_MHZ (0x1 << 0)
+#define DA7218_PLL_INDIV_10_20_MHZ (0x2 << 0)
+#define DA7218_PLL_INDIV_20_40_MHZ (0x3 << 0)
+#define DA7218_PLL_INDIV_40_54_MHZ (0x4 << 0)
+#define DA7218_PLL_INDIV_2_10_MHZ_VAL 2
+#define DA7218_PLL_INDIV_10_20_MHZ_VAL 4
+#define DA7218_PLL_INDIV_20_40_MHZ_VAL 8
+#define DA7218_PLL_INDIV_40_54_MHZ_VAL 16
+#define DA7218_PLL_MCLK_SQR_EN_SHIFT 4
+#define DA7218_PLL_MCLK_SQR_EN_MASK (0x1 << 4)
+#define DA7218_PLL_MODE_SHIFT 6
+#define DA7218_PLL_MODE_MASK (0x3 << 6)
+#define DA7218_PLL_MODE_BYPASS (0x0 << 6)
+#define DA7218_PLL_MODE_NORMAL (0x1 << 6)
+#define DA7218_PLL_MODE_SRM (0x2 << 6)
+#define DA7218_PLL_MODE_32KHZ (0x3 << 6)
+
+/* DA7218_PLL_FRAC_TOP = 0x92 */
+#define DA7218_PLL_FBDIV_FRAC_TOP_SHIFT 0
+#define DA7218_PLL_FBDIV_FRAC_TOP_MASK (0x1F << 0)
+
+/* DA7218_PLL_FRAC_BOT = 0x93 */
+#define DA7218_PLL_FBDIV_FRAC_BOT_SHIFT 0
+#define DA7218_PLL_FBDIV_FRAC_BOT_MASK (0xFF << 0)
+
+/* DA7218_PLL_INTEGER = 0x94 */
+#define DA7218_PLL_FBDIV_INTEGER_SHIFT 0
+#define DA7218_PLL_FBDIV_INTEGER_MASK (0x7F << 0)
+
+/* DA7218_PLL_STATUS = 0x95 */
+#define DA7218_PLL_SRM_STATUS_SHIFT 0
+#define DA7218_PLL_SRM_STATUS_MASK (0xFF << 0)
+#define DA7218_PLL_SRM_STATUS_SRM_LOCK (0x1 << 7)
+
+/* DA7218_PLL_REFOSC_CAL = 0x98 */
+#define DA7218_PLL_REFOSC_CAL_CTRL_SHIFT 0
+#define DA7218_PLL_REFOSC_CAL_CTRL_MASK (0x1F << 0)
+#define DA7218_PLL_REFOSC_CAL_START_SHIFT 6
+#define DA7218_PLL_REFOSC_CAL_START_MASK (0x1 << 6)
+#define DA7218_PLL_REFOSC_CAL_EN_SHIFT 7
+#define DA7218_PLL_REFOSC_CAL_EN_MASK (0x1 << 7)
+
+/* DA7218_DAC_NG_CTRL = 0x9C */
+#define DA7218_DAC_NG_EN_SHIFT 7
+#define DA7218_DAC_NG_EN_MASK (0x1 << 7)
+
+/* DA7218_DAC_NG_SETUP_TIME = 0x9D */
+#define DA7218_DAC_NG_SETUP_TIME_SHIFT 0
+#define DA7218_DAC_NG_SETUP_TIME_MASK (0x3 << 0)
+#define DA7218_DAC_NG_SETUP_TIME_MAX 4
+#define DA7218_DAC_NG_RAMPUP_RATE_SHIFT 2
+#define DA7218_DAC_NG_RAMPUP_RATE_MASK (0x1 << 2)
+#define DA7218_DAC_NG_RAMPUP_RATE_MAX 2
+#define DA7218_DAC_NG_RAMPDN_RATE_SHIFT 3
+#define DA7218_DAC_NG_RAMPDN_RATE_MASK (0x1 << 3)
+#define DA7218_DAC_NG_RAMPDN_RATE_MAX 2
+
+/* DA7218_DAC_NG_OFF_THRESH = 0x9E */
+#define DA7218_DAC_NG_OFF_THRESHOLD_SHIFT 0
+#define DA7218_DAC_NG_OFF_THRESHOLD_MASK (0x7 << 0)
+#define DA7218_DAC_NG_THRESHOLD_MAX 0x7
+
+/* DA7218_DAC_NG_ON_THRESH = 0x9F */
+#define DA7218_DAC_NG_ON_THRESHOLD_SHIFT 0
+#define DA7218_DAC_NG_ON_THRESHOLD_MASK (0x7 << 0)
+
+/* DA7218_TONE_GEN_CFG1 = 0xA0 */
+#define DA7218_DTMF_REG_SHIFT 0
+#define DA7218_DTMF_REG_MASK (0xF << 0)
+#define DA7218_DTMF_REG_MAX 16
+#define DA7218_DTMF_EN_SHIFT 4
+#define DA7218_DTMF_EN_MASK (0x1 << 4)
+#define DA7218_START_STOPN_SHIFT 7
+#define DA7218_START_STOPN_MASK (0x1 << 7)
+
+/* DA7218_TONE_GEN_CFG2 = 0xA1 */
+#define DA7218_SWG_SEL_SHIFT 0
+#define DA7218_SWG_SEL_MASK (0x3 << 0)
+#define DA7218_SWG_SEL_MAX 4
+
+/* DA7218_TONE_GEN_FREQ1_L = 0xA2 */
+#define DA7218_FREQ1_L_SHIFT 0
+#define DA7218_FREQ1_L_MASK (0xFF << 0)
+#define DA7218_FREQ_MAX 0xFFFF
+
+/* DA7218_TONE_GEN_FREQ1_U = 0xA3 */
+#define DA7218_FREQ1_U_SHIFT 0
+#define DA7218_FREQ1_U_MASK (0xFF << 0)
+
+/* DA7218_TONE_GEN_FREQ2_L = 0xA4 */
+#define DA7218_FREQ2_L_SHIFT 0
+#define DA7218_FREQ2_L_MASK (0xFF << 0)
+
+/* DA7218_TONE_GEN_FREQ2_U = 0xA5 */
+#define DA7218_FREQ2_U_SHIFT 0
+#define DA7218_FREQ2_U_MASK (0xFF << 0)
+
+/* DA7218_TONE_GEN_CYCLES = 0xA6 */
+#define DA7218_BEEP_CYCLES_SHIFT 0
+#define DA7218_BEEP_CYCLES_MASK (0x7 << 0)
+
+/* DA7218_TONE_GEN_ON_PER = 0xA7 */
+#define DA7218_BEEP_ON_PER_SHIFT 0
+#define DA7218_BEEP_ON_PER_MASK (0x3F << 0)
+
+/* DA7218_TONE_GEN_OFF_PER = 0xA8 */
+#define DA7218_BEEP_OFF_PER_SHIFT 0
+#define DA7218_BEEP_OFF_PER_MASK (0x3F << 0)
+#define DA7218_BEEP_ON_OFF_MAX 0x3F
+
+/* DA7218_CP_CTRL = 0xAC */
+#define DA7218_CP_MOD_SHIFT 2
+#define DA7218_CP_MOD_MASK (0x3 << 2)
+#define DA7218_CP_MCHANGE_SHIFT 4
+#define DA7218_CP_MCHANGE_MASK (0x3 << 4)
+#define DA7218_CP_MCHANGE_REL_MASK 0x3
+#define DA7218_CP_MCHANGE_MAX 3
+#define DA7218_CP_MCHANGE_LARGEST_VOL 0x1
+#define DA7218_CP_MCHANGE_DAC_VOL 0x2
+#define DA7218_CP_MCHANGE_SIG_MAG 0x3
+#define DA7218_CP_SMALL_SWITCH_FREQ_EN_SHIFT 6
+#define DA7218_CP_SMALL_SWITCH_FREQ_EN_MASK (0x1 << 6)
+#define DA7218_CP_EN_SHIFT 7
+#define DA7218_CP_EN_MASK (0x1 << 7)
+
+/* DA7218_CP_DELAY = 0xAD */
+#define DA7218_CP_FCONTROL_SHIFT 0
+#define DA7218_CP_FCONTROL_MASK (0x7 << 0)
+#define DA7218_CP_FCONTROL_MAX 6
+#define DA7218_CP_TAU_DELAY_SHIFT 3
+#define DA7218_CP_TAU_DELAY_MASK (0x7 << 3)
+#define DA7218_CP_TAU_DELAY_MAX 8
+
+/* DA7218_CP_VOL_THRESHOLD1 = 0xAE */
+#define DA7218_CP_THRESH_VDD2_SHIFT 0
+#define DA7218_CP_THRESH_VDD2_MASK (0x3F << 0)
+#define DA7218_CP_THRESH_VDD2_MAX 0x3F
+
+/* DA7218_MIC_1_CTRL = 0xB4 */
+#define DA7218_MIC_1_AMP_MUTE_EN_SHIFT 6
+#define DA7218_MIC_1_AMP_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_MIC_1_AMP_EN_SHIFT 7
+#define DA7218_MIC_1_AMP_EN_MASK (0x1 << 7)
+
+/* DA7218_MIC_1_GAIN = 0xB5 */
+#define DA7218_MIC_1_AMP_GAIN_SHIFT 0
+#define DA7218_MIC_1_AMP_GAIN_MASK (0x7 << 0)
+#define DA7218_MIC_AMP_GAIN_MAX 0x7
+
+/* DA7218_MIC_1_SELECT = 0xB7 */
+#define DA7218_MIC_1_AMP_IN_SEL_SHIFT 0
+#define DA7218_MIC_1_AMP_IN_SEL_MASK (0x3 << 0)
+
+/* DA7218_MIC_2_CTRL = 0xB8 */
+#define DA7218_MIC_2_AMP_MUTE_EN_SHIFT 6
+#define DA7218_MIC_2_AMP_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_MIC_2_AMP_EN_SHIFT 7
+#define DA7218_MIC_2_AMP_EN_MASK (0x1 << 7)
+
+/* DA7218_MIC_2_GAIN = 0xB9 */
+#define DA7218_MIC_2_AMP_GAIN_SHIFT 0
+#define DA7218_MIC_2_AMP_GAIN_MASK (0x7 << 0)
+
+/* DA7218_MIC_2_SELECT = 0xBB */
+#define DA7218_MIC_2_AMP_IN_SEL_SHIFT 0
+#define DA7218_MIC_2_AMP_IN_SEL_MASK (0x3 << 0)
+
+/* DA7218_IN_1_HPF_FILTER_CTRL = 0xBC */
+#define DA7218_IN_1_VOICE_HPF_CORNER_SHIFT 0
+#define DA7218_IN_1_VOICE_HPF_CORNER_MASK (0x7 << 0)
+#define DA7218_IN_VOICE_HPF_CORNER_MAX 8
+#define DA7218_IN_1_VOICE_EN_SHIFT 3
+#define DA7218_IN_1_VOICE_EN_MASK (0x1 << 3)
+#define DA7218_IN_1_AUDIO_HPF_CORNER_SHIFT 4
+#define DA7218_IN_1_AUDIO_HPF_CORNER_MASK (0x3 << 4)
+#define DA7218_IN_1_HPF_EN_SHIFT 7
+#define DA7218_IN_1_HPF_EN_MASK (0x1 << 7)
+
+/* DA7218_IN_2_HPF_FILTER_CTRL = 0xBD */
+#define DA7218_IN_2_VOICE_HPF_CORNER_SHIFT 0
+#define DA7218_IN_2_VOICE_HPF_CORNER_MASK (0x7 << 0)
+#define DA7218_IN_2_VOICE_EN_SHIFT 3
+#define DA7218_IN_2_VOICE_EN_MASK (0x1 << 3)
+#define DA7218_IN_2_AUDIO_HPF_CORNER_SHIFT 4
+#define DA7218_IN_2_AUDIO_HPF_CORNER_MASK (0x3 << 4)
+#define DA7218_IN_2_HPF_EN_SHIFT 7
+#define DA7218_IN_2_HPF_EN_MASK (0x1 << 7)
+
+/* DA7218_ADC_1_CTRL = 0xC0 */
+#define DA7218_ADC_1_AAF_EN_SHIFT 2
+#define DA7218_ADC_1_AAF_EN_MASK (0x1 << 2)
+
+/* DA7218_ADC_2_CTRL = 0xC1 */
+#define DA7218_ADC_2_AAF_EN_SHIFT 2
+#define DA7218_ADC_2_AAF_EN_MASK (0x1 << 2)
+
+/* DA7218_ADC_MODE = 0xC2 */
+#define DA7218_ADC_LP_MODE_SHIFT 0
+#define DA7218_ADC_LP_MODE_MASK (0x1 << 0)
+#define DA7218_ADC_LVLDET_MODE_SHIFT 1
+#define DA7218_ADC_LVLDET_MODE_MASK (0x1 << 1)
+#define DA7218_ADC_LVLDET_AUTO_EXIT_SHIFT 2
+#define DA7218_ADC_LVLDET_AUTO_EXIT_MASK (0x1 << 2)
+
+/* DA7218_MIXOUT_L_CTRL = 0xCC */
+#define DA7218_MIXOUT_L_AMP_EN_SHIFT 7
+#define DA7218_MIXOUT_L_AMP_EN_MASK (0x1 << 7)
+
+/* DA7218_MIXOUT_L_GAIN = 0xCD */
+#define DA7218_MIXOUT_L_AMP_GAIN_SHIFT 0
+#define DA7218_MIXOUT_L_AMP_GAIN_MASK (0x3 << 0)
+#define DA7218_MIXOUT_AMP_GAIN_MIN 0x1
+#define DA7218_MIXOUT_AMP_GAIN_MAX 0x3
+
+/* DA7218_MIXOUT_R_CTRL = 0xCE */
+#define DA7218_MIXOUT_R_AMP_EN_SHIFT 7
+#define DA7218_MIXOUT_R_AMP_EN_MASK (0x1 << 7)
+
+/* DA7218_MIXOUT_R_GAIN = 0xCF */
+#define DA7218_MIXOUT_R_AMP_GAIN_SHIFT 0
+#define DA7218_MIXOUT_R_AMP_GAIN_MASK (0x3 << 0)
+
+/* DA7218_HP_L_CTRL = 0xD0 */
+#define DA7218_HP_L_AMP_MIN_GAIN_EN_SHIFT 2
+#define DA7218_HP_L_AMP_MIN_GAIN_EN_MASK (0x1 << 2)
+#define DA7218_HP_L_AMP_OE_SHIFT 3
+#define DA7218_HP_L_AMP_OE_MASK (0x1 << 3)
+#define DA7218_HP_L_AMP_ZC_EN_SHIFT 4
+#define DA7218_HP_L_AMP_ZC_EN_MASK (0x1 << 4)
+#define DA7218_HP_L_AMP_RAMP_EN_SHIFT 5
+#define DA7218_HP_L_AMP_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_HP_L_AMP_MUTE_EN_SHIFT 6
+#define DA7218_HP_L_AMP_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_HP_L_AMP_EN_SHIFT 7
+#define DA7218_HP_L_AMP_EN_MASK (0x1 << 7)
+#define DA7218_HP_AMP_OE_MASK (0x1 << 3)
+
+/* DA7218_HP_L_GAIN = 0xD1 */
+#define DA7218_HP_L_AMP_GAIN_SHIFT 0
+#define DA7218_HP_L_AMP_GAIN_MASK (0x3F << 0)
+#define DA7218_HP_AMP_GAIN_MIN 0x15
+#define DA7218_HP_AMP_GAIN_MAX 0x3F
+
+/* DA7218_HP_R_CTRL = 0xD2 */
+#define DA7218_HP_R_AMP_MIN_GAIN_EN_SHIFT 2
+#define DA7218_HP_R_AMP_MIN_GAIN_EN_MASK (0x1 << 2)
+#define DA7218_HP_R_AMP_OE_SHIFT 3
+#define DA7218_HP_R_AMP_OE_MASK (0x1 << 3)
+#define DA7218_HP_R_AMP_ZC_EN_SHIFT 4
+#define DA7218_HP_R_AMP_ZC_EN_MASK (0x1 << 4)
+#define DA7218_HP_R_AMP_RAMP_EN_SHIFT 5
+#define DA7218_HP_R_AMP_RAMP_EN_MASK (0x1 << 5)
+#define DA7218_HP_R_AMP_MUTE_EN_SHIFT 6
+#define DA7218_HP_R_AMP_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_HP_R_AMP_EN_SHIFT 7
+#define DA7218_HP_R_AMP_EN_MASK (0x1 << 7)
+
+/* DA7218_HP_R_GAIN = 0xD3 */
+#define DA7218_HP_R_AMP_GAIN_SHIFT 0
+#define DA7218_HP_R_AMP_GAIN_MASK (0x3F << 0)
+
+/* DA7218_HP_SNGL_CTRL = 0xD4 */
+#define DA7218_HP_AMP_STEREO_DETECT_STATUS_SHIFT 0
+#define DA7218_HP_AMP_STEREO_DETECT_STATUS_MASK (0x1 << 0)
+#define DA7218_HPL_AMP_LOAD_DETECT_STATUS_SHIFT 1
+#define DA7218_HPL_AMP_LOAD_DETECT_STATUS_MASK (0x1 << 1)
+#define DA7218_HPR_AMP_LOAD_DETECT_STATUS_SHIFT 2
+#define DA7218_HPR_AMP_LOAD_DETECT_STATUS_MASK (0x1 << 2)
+#define DA7218_HP_AMP_LOAD_DETECT_EN_SHIFT 6
+#define DA7218_HP_AMP_LOAD_DETECT_EN_MASK (0x1 << 6)
+#define DA7218_HP_AMP_STEREO_DETECT_EN_SHIFT 7
+#define DA7218_HP_AMP_STEREO_DETECT_EN_MASK (0x1 << 7)
+
+/* DA7218_HP_DIFF_CTRL = 0xD5 */
+#define DA7218_HP_AMP_DIFF_MODE_EN_SHIFT 0
+#define DA7218_HP_AMP_DIFF_MODE_EN_MASK (0x1 << 0)
+#define DA7218_HP_AMP_SINGLE_SUPPLY_EN_SHIFT 4
+#define DA7218_HP_AMP_SINGLE_SUPPLY_EN_MASK (0x1 << 4)
+
+/* DA7218_HP_DIFF_UNLOCK = 0xD7 */
+#define DA7218_HP_DIFF_UNLOCK_SHIFT 0
+#define DA7218_HP_DIFF_UNLOCK_MASK (0x1 << 0)
+#define DA7218_HP_DIFF_UNLOCK_VAL 0xC3
+
+/* DA7218_HPLDET_JACK = 0xD8 */
+#define DA7218_HPLDET_JACK_RATE_SHIFT 0
+#define DA7218_HPLDET_JACK_RATE_MASK (0x7 << 0)
+#define DA7218_HPLDET_JACK_DEBOUNCE_SHIFT 3
+#define DA7218_HPLDET_JACK_DEBOUNCE_MASK (0x3 << 3)
+#define DA7218_HPLDET_JACK_THR_SHIFT 5
+#define DA7218_HPLDET_JACK_THR_MASK (0x3 << 5)
+#define DA7218_HPLDET_JACK_EN_SHIFT 7
+#define DA7218_HPLDET_JACK_EN_MASK (0x1 << 7)
+
+/* DA7218_HPLDET_CTRL = 0xD9 */
+#define DA7218_HPLDET_COMP_INV_SHIFT 0
+#define DA7218_HPLDET_COMP_INV_MASK (0x1 << 0)
+#define DA7218_HPLDET_HYST_EN_SHIFT 1
+#define DA7218_HPLDET_HYST_EN_MASK (0x1 << 1)
+#define DA7218_HPLDET_DISCHARGE_EN_SHIFT 7
+#define DA7218_HPLDET_DISCHARGE_EN_MASK (0x1 << 7)
+
+/* DA7218_HPLDET_TEST = 0xDA */
+#define DA7218_HPLDET_COMP_STS_SHIFT 4
+#define DA7218_HPLDET_COMP_STS_MASK (0x1 << 4)
+
+/* DA7218_REFERENCES = 0xDC */
+#define DA7218_BIAS_EN_SHIFT 3
+#define DA7218_BIAS_EN_MASK (0x1 << 3)
+
+/* DA7218_IO_CTRL = 0xE0 */
+#define DA7218_IO_VOLTAGE_LEVEL_SHIFT 0
+#define DA7218_IO_VOLTAGE_LEVEL_MASK (0x1 << 0)
+#define DA7218_IO_VOLTAGE_LEVEL_2_5V_3_6V 0
+#define DA7218_IO_VOLTAGE_LEVEL_1_5V_2_5V 1
+
+/* DA7218_LDO_CTRL = 0xE1 */
+#define DA7218_LDO_LEVEL_SELECT_SHIFT 4
+#define DA7218_LDO_LEVEL_SELECT_MASK (0x3 << 4)
+#define DA7218_LDO_EN_SHIFT 7
+#define DA7218_LDO_EN_MASK (0x1 << 7)
+
+/* DA7218_SIDETONE_CTRL = 0xE4 */
+#define DA7218_SIDETONE_MUTE_EN_SHIFT 6
+#define DA7218_SIDETONE_MUTE_EN_MASK (0x1 << 6)
+#define DA7218_SIDETONE_FILTER_EN_SHIFT 7
+#define DA7218_SIDETONE_FILTER_EN_MASK (0x1 << 7)
+
+/* DA7218_SIDETONE_IN_SELECT = 0xE5 */
+#define DA7218_SIDETONE_IN_SELECT_SHIFT 0
+#define DA7218_SIDETONE_IN_SELECT_MASK (0x3 << 0)
+#define DA7218_SIDETONE_IN_SELECT_MAX 4
+
+/* DA7218_SIDETONE_GAIN = 0xE6 */
+#define DA7218_SIDETONE_GAIN_SHIFT 0
+#define DA7218_SIDETONE_GAIN_MASK (0x1F << 0)
+
+/* DA7218_DROUTING_ST_OUTFILT_1L = 0xE8 */
+#define DA7218_OUTFILT_ST_1L_SRC_SHIFT 0
+#define DA7218_OUTFILT_ST_1L_SRC_MASK (0x7 << 0)
+#define DA7218_DMIX_ST_SRC_OUTFILT1L 0
+#define DA7218_DMIX_ST_SRC_OUTFILT1R 1
+#define DA7218_DMIX_ST_SRC_SIDETONE 2
+
+/* DA7218_DROUTING_ST_OUTFILT_1R = 0xE9 */
+#define DA7218_OUTFILT_ST_1R_SRC_SHIFT 0
+#define DA7218_OUTFILT_ST_1R_SRC_MASK (0x7 << 0)
+
+/* DA7218_SIDETONE_BIQ_3STAGE_DATA = 0xEA */
+#define DA7218_SIDETONE_BIQ_3STAGE_DATA_SHIFT 0
+#define DA7218_SIDETONE_BIQ_3STAGE_DATA_MASK (0xFF << 0)
+
+/* DA7218_SIDETONE_BIQ_3STAGE_ADDR = 0xEB */
+#define DA7218_SIDETONE_BIQ_3STAGE_ADDR_SHIFT 0
+#define DA7218_SIDETONE_BIQ_3STAGE_ADDR_MASK (0x1F << 0)
+#define DA7218_SIDETONE_BIQ_3STAGE_CFG_SIZE 30
+
+/* DA7218_EVENT_STATUS = 0xEC */
+#define DA7218_HPLDET_JACK_STS_SHIFT 7
+#define DA7218_HPLDET_JACK_STS_MASK (0x1 << 7)
+
+/* DA7218_EVENT = 0xED */
+#define DA7218_LVL_DET_EVENT_SHIFT 0
+#define DA7218_LVL_DET_EVENT_MASK (0x1 << 0)
+#define DA7218_HPLDET_JACK_EVENT_SHIFT 7
+#define DA7218_HPLDET_JACK_EVENT_MASK (0x1 << 7)
+
+/* DA7218_EVENT_MASK = 0xEE */
+#define DA7218_LVL_DET_EVENT_MSK_SHIFT 0
+#define DA7218_LVL_DET_EVENT_MSK_MASK (0x1 << 0)
+#define DA7218_HPLDET_JACK_EVENT_IRQ_MSK_SHIFT 7
+#define DA7218_HPLDET_JACK_EVENT_IRQ_MSK_MASK (0x1 << 7)
+
+/* DA7218_DMIC_1_CTRL = 0xF0 */
+#define DA7218_DMIC_1_DATA_SEL_SHIFT 0
+#define DA7218_DMIC_1_DATA_SEL_MASK (0x1 << 0)
+#define DA7218_DMIC_1_SAMPLEPHASE_SHIFT 1
+#define DA7218_DMIC_1_SAMPLEPHASE_MASK (0x1 << 1)
+#define DA7218_DMIC_1_CLK_RATE_SHIFT 2
+#define DA7218_DMIC_1_CLK_RATE_MASK (0x1 << 2)
+#define DA7218_DMIC_1L_EN_SHIFT 6
+#define DA7218_DMIC_1L_EN_MASK (0x1 << 6)
+#define DA7218_DMIC_1R_EN_SHIFT 7
+#define DA7218_DMIC_1R_EN_MASK (0x1 << 7)
+
+/* DA7218_DMIC_2_CTRL = 0xF1 */
+#define DA7218_DMIC_2_DATA_SEL_SHIFT 0
+#define DA7218_DMIC_2_DATA_SEL_MASK (0x1 << 0)
+#define DA7218_DMIC_2_SAMPLEPHASE_SHIFT 1
+#define DA7218_DMIC_2_SAMPLEPHASE_MASK (0x1 << 1)
+#define DA7218_DMIC_2_CLK_RATE_SHIFT 2
+#define DA7218_DMIC_2_CLK_RATE_MASK (0x1 << 2)
+#define DA7218_DMIC_2L_EN_SHIFT 6
+#define DA7218_DMIC_2L_EN_MASK (0x1 << 6)
+#define DA7218_DMIC_2R_EN_SHIFT 7
+#define DA7218_DMIC_2R_EN_MASK (0x1 << 7)
+
+/* DA7218_IN_1L_GAIN = 0xF4 */
+#define DA7218_IN_1L_DIGITAL_GAIN_SHIFT 0
+#define DA7218_IN_1L_DIGITAL_GAIN_MASK (0x7F << 0)
+#define DA7218_IN_DIGITAL_GAIN_MAX 0x7F
+
+/* DA7218_IN_1R_GAIN = 0xF5 */
+#define DA7218_IN_1R_DIGITAL_GAIN_SHIFT 0
+#define DA7218_IN_1R_DIGITAL_GAIN_MASK (0x7F << 0)
+
+/* DA7218_IN_2L_GAIN = 0xF6 */
+#define DA7218_IN_2L_DIGITAL_GAIN_SHIFT 0
+#define DA7218_IN_2L_DIGITAL_GAIN_MASK (0x7F << 0)
+
+/* DA7218_IN_2R_GAIN = 0xF7 */
+#define DA7218_IN_2R_DIGITAL_GAIN_SHIFT 0
+#define DA7218_IN_2R_DIGITAL_GAIN_MASK (0x7F << 0)
+
+/* DA7218_OUT_1L_GAIN = 0xF8 */
+#define DA7218_OUT_1L_DIGITAL_GAIN_SHIFT 0
+#define DA7218_OUT_1L_DIGITAL_GAIN_MASK (0xFF << 0)
+#define DA7218_OUT_DIGITAL_GAIN_MIN 0x0
+#define DA7218_OUT_DIGITAL_GAIN_MAX 0x97
+
+/* DA7218_OUT_1R_GAIN = 0xF9 */
+#define DA7218_OUT_1R_DIGITAL_GAIN_SHIFT 0
+#define DA7218_OUT_1R_DIGITAL_GAIN_MASK (0xFF << 0)
+
+/* DA7218_MICBIAS_CTRL = 0xFC */
+#define DA7218_MICBIAS_1_LEVEL_SHIFT 0
+#define DA7218_MICBIAS_1_LEVEL_MASK (0x7 << 0)
+#define DA7218_MICBIAS_1_LP_MODE_SHIFT 3
+#define DA7218_MICBIAS_1_LP_MODE_MASK (0x1 << 3)
+#define DA7218_MICBIAS_2_LEVEL_SHIFT 4
+#define DA7218_MICBIAS_2_LEVEL_MASK (0x7 << 4)
+#define DA7218_MICBIAS_2_LP_MODE_SHIFT 7
+#define DA7218_MICBIAS_2_LP_MODE_MASK (0x1 << 7)
+
+/* DA7218_MICBIAS_EN = 0xFD */
+#define DA7218_MICBIAS_1_EN_SHIFT 0
+#define DA7218_MICBIAS_1_EN_MASK (0x1 << 0)
+#define DA7218_MICBIAS_2_EN_SHIFT 4
+#define DA7218_MICBIAS_2_EN_MASK (0x1 << 4)
+
+
+/*
+ * General defines & data
+ */
+
+/* Register inversion */
+#define DA7218_NO_INVERT 0
+#define DA7218_INVERT 1
+
+/* Byte related defines */
+#define DA7218_BYTE_SHIFT 8
+#define DA7218_BYTE_MASK 0xFF
+#define DA7218_2BYTE_SHIFT 16
+#define DA7218_2BYTE_MASK 0xFFFF
+
+/* PLL Output Frequencies */
+#define DA7218_PLL_FREQ_OUT_90316 90316800
+#define DA7218_PLL_FREQ_OUT_98304 98304000
+
+/* ALC Calibration */
+#define DA7218_ALC_CALIB_DELAY_MIN 2500
+#define DA7218_ALC_CALIB_DELAY_MAX 5000
+#define DA7218_ALC_CALIB_MAX_TRIES 5
+
+/* Ref Oscillator */
+#define DA7218_REF_OSC_CHECK_DELAY_MIN 5000
+#define DA7218_REF_OSC_CHECK_DELAY_MAX 10000
+#define DA7218_REF_OSC_CHECK_TRIES 4
+
+/* SRM */
+#define DA7218_SRM_CHECK_DELAY 50
+#define DA7218_SRM_CHECK_TRIES 8
+
+/* Mic Level Detect */
+#define DA7218_MIC_LVL_DET_DELAY 50
+
+enum da7218_biq_cfg {
+ DA7218_BIQ_CFG_DATA = 0,
+ DA7218_BIQ_CFG_ADDR,
+ DA7218_BIQ_CFG_SIZE,
+};
+
+enum da7218_clk_src {
+ DA7218_CLKSRC_MCLK = 0,
+ DA7218_CLKSRC_MCLK_SQR,
+};
+
+enum da7218_sys_clk {
+ DA7218_SYSCLK_MCLK = 0,
+ DA7218_SYSCLK_PLL,
+ DA7218_SYSCLK_PLL_SRM,
+ DA7218_SYSCLK_PLL_32KHZ
+};
+
+enum da7218_dev_id {
+ DA7217_DEV_ID = 0,
+ DA7218_DEV_ID,
+};
+
+/* Regulators */
+enum da7218_supplies {
+ DA7218_SUPPLY_VDD = 0,
+ DA7218_SUPPLY_VDDMIC,
+ DA7218_SUPPLY_VDDIO,
+ DA7218_NUM_SUPPLIES,
+};
+
+/* Private data */
+struct da7218_priv {
+ struct da7218_pdata *pdata;
+
+ struct regulator_bulk_data supplies[DA7218_NUM_SUPPLIES];
+ struct regmap *regmap;
+ int dev_id;
+
+ struct snd_soc_jack *jack;
+ int irq;
+
+ struct clk *mclk;
+ unsigned int mclk_rate;
+
+ bool hp_single_supply;
+ bool master;
+ u8 alc_en;
+ u8 in_filt_en;
+ u8 mic_lvl_det_en;
+
+ u8 biq_5stage_coeff[DA7218_OUT_1_BIQ_5STAGE_CFG_SIZE];
+ u8 stbiq_3stage_coeff[DA7218_SIDETONE_BIQ_3STAGE_CFG_SIZE];
+};
+
+/* HP detect control */
+int da7218_hpldet(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
+
+#endif /* _DA7218_H */
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index f238c1e8a69c..81c0708b85c1 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -968,10 +968,11 @@ static const struct snd_soc_dapm_route da7219_audio_map[] = {
{"Mixin PGA", NULL, "Mic PGA"},
{"ADC", NULL, "Mixin PGA"},
- {"Sidetone Filter", NULL, "ADC"},
{"Mixer In", NULL, "Mixer In Supply"},
{"Mixer In", "Mic Switch", "ADC"},
+ {"Sidetone Filter", NULL, "Mixer In"},
+
{"Tone Generator", NULL, "TONE"},
DA7219_OUT_DAI_MUX_ROUTES("Out DAIL Mux"),
@@ -1073,11 +1074,8 @@ static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
u32 freq_ref;
u64 frac_div;
- /* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */
- if (da7219->mclk_rate == 32768) {
- indiv_bits = DA7219_PLL_INDIV_2_5_MHZ;
- indiv = DA7219_PLL_INDIV_2_5_MHZ_VAL;
- } else if (da7219->mclk_rate < 2000000) {
+ /* Verify 2MHz - 54MHz MCLK provided, and set input divider */
+ if (da7219->mclk_rate < 2000000) {
dev_err(codec->dev, "PLL input clock %d below valid range\n",
da7219->mclk_rate);
return -EINVAL;
@@ -1118,9 +1116,6 @@ static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
case DA7219_SYSCLK_PLL_SRM:
pll_ctrl |= DA7219_PLL_MODE_SRM;
break;
- case DA7219_SYSCLK_PLL_32KHZ:
- pll_ctrl |= DA7219_PLL_MODE_32KHZ;
- break;
default:
dev_err(codec->dev, "Invalid PLL config\n");
return -EINVAL;
@@ -1161,18 +1156,44 @@ static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
return -EINVAL;
}
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- break;
- case SND_SOC_DAIFMT_NB_IF:
- dai_clk_mode |= DA7219_DAI_WCLK_POL_INV;
- break;
- case SND_SOC_DAIFMT_IB_NF:
- dai_clk_mode |= DA7219_DAI_CLK_POL_INV;
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_LEFT_J:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ dai_clk_mode |= DA7219_DAI_WCLK_POL_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ dai_clk_mode |= DA7219_DAI_CLK_POL_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ dai_clk_mode |= DA7219_DAI_WCLK_POL_INV |
+ DA7219_DAI_CLK_POL_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
- case SND_SOC_DAIFMT_IB_IF:
- dai_clk_mode |= DA7219_DAI_WCLK_POL_INV |
- DA7219_DAI_CLK_POL_INV;
+ case SND_SOC_DAIFMT_DSP_B:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ dai_clk_mode |= DA7219_DAI_CLK_POL_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ dai_clk_mode |= DA7219_DAI_WCLK_POL_INV |
+ DA7219_DAI_CLK_POL_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ dai_clk_mode |= DA7219_DAI_WCLK_POL_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
@@ -1306,7 +1327,7 @@ static int da7219_hw_params(struct snd_pcm_substream *substream,
}
channels = params_channels(params);
- if ((channels < 1) | (channels > DA7219_DAI_CH_NUM_MAX)) {
+ if ((channels < 1) || (channels > DA7219_DAI_CH_NUM_MAX)) {
dev_err(codec->dev,
"Invalid number of channels, only 1 to %d supported\n",
DA7219_DAI_CH_NUM_MAX);
@@ -1405,28 +1426,12 @@ static const struct of_device_id da7219_of_match[] = {
};
MODULE_DEVICE_TABLE(of, da7219_of_match);
-static enum da7219_ldo_lvl_sel da7219_of_ldo_lvl(struct snd_soc_codec *codec,
- u32 val)
-{
- switch (val) {
- case 1050:
- return DA7219_LDO_LVL_SEL_1_05V;
- case 1100:
- return DA7219_LDO_LVL_SEL_1_10V;
- case 1200:
- return DA7219_LDO_LVL_SEL_1_20V;
- case 1400:
- return DA7219_LDO_LVL_SEL_1_40V;
- default:
- dev_warn(codec->dev, "Invalid LDO level");
- return DA7219_LDO_LVL_SEL_1_05V;
- }
-}
-
static enum da7219_micbias_voltage
da7219_of_micbias_lvl(struct snd_soc_codec *codec, u32 val)
{
switch (val) {
+ case 1600:
+ return DA7219_MICBIAS_1_6V;
case 1800:
return DA7219_MICBIAS_1_8V;
case 2000:
@@ -1469,9 +1474,6 @@ static struct da7219_pdata *da7219_of_to_pdata(struct snd_soc_codec *codec)
if (!pdata)
return NULL;
- if (of_property_read_u32(np, "dlg,ldo-lvl", &of_val32) >= 0)
- pdata->ldo_lvl_sel = da7219_of_ldo_lvl(codec, of_val32);
-
if (of_property_read_u32(np, "dlg,micbias-lvl", &of_val32) >= 0)
pdata->micbias_lvl = da7219_of_micbias_lvl(codec, of_val32);
else
@@ -1516,24 +1518,13 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, DA7219_REFERENCES,
DA7219_BIAS_EN_MASK,
DA7219_BIAS_EN_MASK);
-
- /* Enable Internal Digital LDO */
- snd_soc_update_bits(codec, DA7219_LDO_CTRL,
- DA7219_LDO_EN_MASK,
- DA7219_LDO_EN_MASK);
}
break;
case SND_SOC_BIAS_OFF:
- /* Only disable if jack detection not active */
- if (!da7219->aad->jack) {
- /* Bypass Internal Digital LDO */
- snd_soc_update_bits(codec, DA7219_LDO_CTRL,
- DA7219_LDO_EN_MASK, 0);
-
- /* Master bias */
+ /* Only disable master bias if jack detection not active */
+ if (!da7219->aad->jack)
snd_soc_update_bits(codec, DA7219_REFERENCES,
DA7219_BIAS_EN_MASK, 0);
- }
/* MCLK */
if (da7219->mclk)
@@ -1600,21 +1591,9 @@ static void da7219_handle_pdata(struct snd_soc_codec *codec)
if (pdata) {
u8 micbias_lvl = 0;
- /* Internal LDO */
- switch (pdata->ldo_lvl_sel) {
- case DA7219_LDO_LVL_SEL_1_05V:
- case DA7219_LDO_LVL_SEL_1_10V:
- case DA7219_LDO_LVL_SEL_1_20V:
- case DA7219_LDO_LVL_SEL_1_40V:
- snd_soc_update_bits(codec, DA7219_LDO_CTRL,
- DA7219_LDO_LEVEL_SELECT_MASK,
- (pdata->ldo_lvl_sel <<
- DA7219_LDO_LEVEL_SELECT_SHIFT));
- break;
- }
-
/* Mic Bias voltages */
switch (pdata->micbias_lvl) {
+ case DA7219_MICBIAS_1_6V:
case DA7219_MICBIAS_1_8V:
case DA7219_MICBIAS_2_0V:
case DA7219_MICBIAS_2_2V:
@@ -1639,9 +1618,14 @@ static void da7219_handle_pdata(struct snd_soc_codec *codec)
}
}
+static struct reg_sequence da7219_rev_aa_patch[] = {
+ { DA7219_REFERENCES, 0x08 },
+};
+
static int da7219_probe(struct snd_soc_codec *codec)
{
struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
+ unsigned int rev;
int ret;
mutex_init(&da7219->lock);
@@ -1651,6 +1635,26 @@ static int da7219_probe(struct snd_soc_codec *codec)
if (ret)
return ret;
+ ret = regmap_read(da7219->regmap, DA7219_CHIP_REVISION, &rev);
+ if (ret) {
+ dev_err(codec->dev, "Failed to read chip revision: %d\n", ret);
+ goto err_disable_reg;
+ }
+
+ switch (rev & DA7219_CHIP_MINOR_MASK) {
+ case 0:
+ ret = regmap_register_patch(da7219->regmap, da7219_rev_aa_patch,
+ ARRAY_SIZE(da7219_rev_aa_patch));
+ if (ret) {
+ dev_err(codec->dev, "Failed to register AA patch: %d\n",
+ ret);
+ goto err_disable_reg;
+ }
+ break;
+ default:
+ break;
+ }
+
/* Handle DT/Platform data */
if (codec->dev->of_node)
da7219->pdata = da7219_of_to_pdata(codec);
@@ -1662,10 +1666,12 @@ static int da7219_probe(struct snd_soc_codec *codec)
/* Check if MCLK provided */
da7219->mclk = devm_clk_get(codec->dev, "mclk");
if (IS_ERR(da7219->mclk)) {
- if (PTR_ERR(da7219->mclk) != -ENOENT)
- return PTR_ERR(da7219->mclk);
- else
+ if (PTR_ERR(da7219->mclk) != -ENOENT) {
+ ret = PTR_ERR(da7219->mclk);
+ goto err_disable_reg;
+ } else {
da7219->mclk = NULL;
+ }
}
/* Default PC counter to free-running */
@@ -1693,7 +1699,16 @@ static int da7219_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, DA7219_TONE_GEN_CYCLES, DA7219_BEEP_CYCLES_MASK);
/* Initialise AAD block */
- return da7219_aad_init(codec);
+ ret = da7219_aad_init(codec);
+ if (ret)
+ goto err_disable_reg;
+
+ return 0;
+
+err_disable_reg:
+ regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies);
+
+ return ret;
}
static int da7219_remove(struct snd_soc_codec *codec)
@@ -1776,7 +1791,7 @@ static struct reg_default da7219_reg_defaults[] = {
{ DA7219_DIG_ROUTING_DAC, 0x32 },
{ DA7219_DAI_OFFSET_LOWER, 0x00 },
{ DA7219_DAI_OFFSET_UPPER, 0x00 },
- { DA7219_REFERENCES, 0x00 },
+ { DA7219_REFERENCES, 0x08 },
{ DA7219_MIXIN_L_SELECT, 0x00 },
{ DA7219_MIXIN_L_GAIN, 0x03 },
{ DA7219_ADC_L_GAIN, 0x6F },
@@ -1810,8 +1825,6 @@ static struct reg_default da7219_reg_defaults[] = {
{ DA7219_MIXOUT_R_CTRL, 0x10 },
{ DA7219_CHIP_ID1, 0x23 },
{ DA7219_CHIP_ID2, 0x93 },
- { DA7219_CHIP_REVISION, 0x00 },
- { DA7219_LDO_CTRL, 0x00 },
{ DA7219_IO_CTRL, 0x00 },
{ DA7219_GAIN_RAMP_CTRL, 0x00 },
{ DA7219_PC_COUNT, 0x02 },
diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h
index b514268c6c56..5a787e738084 100644
--- a/sound/soc/codecs/da7219.h
+++ b/sound/soc/codecs/da7219.h
@@ -85,7 +85,6 @@
#define DA7219_CHIP_ID1 0x81
#define DA7219_CHIP_ID2 0x82
#define DA7219_CHIP_REVISION 0x83
-#define DA7219_LDO_CTRL 0x90
#define DA7219_IO_CTRL 0x91
#define DA7219_GAIN_RAMP_CTRL 0x92
#define DA7219_PC_COUNT 0x94
@@ -207,7 +206,6 @@
#define DA7219_PLL_MODE_BYPASS (0x0 << 6)
#define DA7219_PLL_MODE_NORMAL (0x1 << 6)
#define DA7219_PLL_MODE_SRM (0x2 << 6)
-#define DA7219_PLL_MODE_32KHZ (0x3 << 6)
/* DA7219_PLL_FRAC_TOP = 0x22 */
#define DA7219_PLL_FBDIV_FRAC_TOP_SHIFT 0
@@ -569,12 +567,6 @@
#define DA7219_CHIP_MAJOR_SHIFT 4
#define DA7219_CHIP_MAJOR_MASK (0xF << 4)
-/* DA7219_LDO_CTRL = 0x90 */
-#define DA7219_LDO_LEVEL_SELECT_SHIFT 4
-#define DA7219_LDO_LEVEL_SELECT_MASK (0x3 << 4)
-#define DA7219_LDO_EN_SHIFT 7
-#define DA7219_LDO_EN_MASK (0x1 << 7)
-
/* DA7219_IO_CTRL = 0x91 */
#define DA7219_IO_VOLTAGE_LEVEL_SHIFT 0
#define DA7219_IO_VOLTAGE_LEVEL_MASK (0x1 << 0)
@@ -787,7 +779,6 @@ enum da7219_sys_clk {
DA7219_SYSCLK_MCLK = 0,
DA7219_SYSCLK_PLL,
DA7219_SYSCLK_PLL_SRM,
- DA7219_SYSCLK_PLL_32KHZ
};
/* Regulators */
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
new file mode 100644
index 000000000000..5a1ec0f7a1a6
--- /dev/null
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -0,0 +1,697 @@
+/*
+ * hdac_hdmi.c - ASoc HDA-HDMI codec driver for Intel platforms
+ *
+ * Copyright (C) 2014-2015 Intel Corp
+ * Author: Samreen Nilofer <samreen.nilofer@intel.com>
+ * Subhransu S. Prusty <subhransu.s.prusty@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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/hdmi.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/hdaudio_ext.h>
+#include <sound/hda_i915.h>
+#include "../../hda/local.h"
+
+#define AMP_OUT_MUTE 0xb080
+#define AMP_OUT_UNMUTE 0xb000
+#define PIN_OUT (AC_PINCTL_OUT_EN)
+
+#define HDA_MAX_CONNECTIONS 32
+
+struct hdac_hdmi_cvt_params {
+ unsigned int channels_min;
+ unsigned int channels_max;
+ u32 rates;
+ u64 formats;
+ unsigned int maxbps;
+};
+
+struct hdac_hdmi_cvt {
+ struct list_head head;
+ hda_nid_t nid;
+ struct hdac_hdmi_cvt_params params;
+};
+
+struct hdac_hdmi_pin {
+ struct list_head head;
+ hda_nid_t nid;
+ int num_mux_nids;
+ hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
+};
+
+struct hdac_hdmi_dai_pin_map {
+ int dai_id;
+ struct hdac_hdmi_pin *pin;
+ struct hdac_hdmi_cvt *cvt;
+};
+
+struct hdac_hdmi_priv {
+ struct hdac_hdmi_dai_pin_map dai_map[3];
+ struct list_head pin_list;
+ struct list_head cvt_list;
+ int num_pin;
+ int num_cvt;
+};
+
+static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev)
+{
+ struct hdac_device *hdac = dev_to_hdac_dev(dev);
+
+ return to_ehdac_device(hdac);
+}
+
+static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac,
+ hda_nid_t cvt_nid, hda_nid_t pin_nid,
+ u32 stream_tag, int format)
+{
+ unsigned int val;
+
+ dev_dbg(&hdac->hdac.dev, "cvt nid %d pnid %d stream %d format 0x%x\n",
+ cvt_nid, pin_nid, stream_tag, format);
+
+ val = (stream_tag << 4);
+
+ snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0,
+ AC_VERB_SET_CHANNEL_STREAMID, val);
+ snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0,
+ AC_VERB_SET_STREAM_FORMAT, format);
+
+ return 0;
+}
+
+static void
+hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid,
+ int packet_index, int byte_index)
+{
+ int val;
+
+ val = (packet_index << 5) | (byte_index & 0x1f);
+
+ snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
+ AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
+ hda_nid_t cvt_nid, hda_nid_t pin_nid)
+{
+ uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
+ struct hdmi_audio_infoframe frame;
+ u8 *dip = (u8 *)&frame;
+ int ret;
+ int i;
+
+ hdmi_audio_infoframe_init(&frame);
+
+ /* Default stereo for now */
+ frame.channels = 2;
+
+ /* setup channel count */
+ snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0,
+ AC_VERB_SET_CVT_CHAN_COUNT, frame.channels - 1);
+
+ ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
+ if (ret < 0)
+ return ret;
+
+ /* stop infoframe transmission */
+ hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
+ snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
+ AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_DISABLE);
+
+
+ /* Fill infoframe. Index auto-incremented */
+ hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
+ for (i = 0; i < sizeof(frame); i++)
+ snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
+ AC_VERB_SET_HDMI_DIP_DATA, dip[i]);
+
+ /* Start infoframe */
+ hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
+ snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
+ AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_BEST);
+
+ return 0;
+}
+
+static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev,
+ struct hdac_hdmi_dai_pin_map *dai_map, unsigned int pwr_state)
+{
+ /* Power up pin widget */
+ if (!snd_hdac_check_power_state(&edev->hdac, dai_map->pin->nid,
+ pwr_state))
+ snd_hdac_codec_write(&edev->hdac, dai_map->pin->nid, 0,
+ AC_VERB_SET_POWER_STATE, pwr_state);
+
+ /* Power up converter */
+ if (!snd_hdac_check_power_state(&edev->hdac, dai_map->cvt->nid,
+ pwr_state))
+ snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
+ AC_VERB_SET_POWER_STATE, pwr_state);
+}
+
+static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
+ struct hdac_hdmi_priv *hdmi = hdac->private_data;
+ struct hdac_hdmi_dai_pin_map *dai_map;
+ struct hdac_ext_dma_params *dd;
+ int ret;
+
+ if (dai->id > 0) {
+ dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n");
+ return -ENODEV;
+ }
+
+ dai_map = &hdmi->dai_map[dai->id];
+
+ dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
+ dev_dbg(&hdac->hdac.dev, "stream tag from cpu dai %d format in cvt 0x%x\n",
+ dd->stream_tag, dd->format);
+
+ ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt->nid,
+ dai_map->pin->nid);
+ if (ret < 0)
+ return ret;
+
+ return hdac_hdmi_setup_stream(hdac, dai_map->cvt->nid,
+ dai_map->pin->nid, dd->stream_tag, dd->format);
+}
+
+static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hparams, struct snd_soc_dai *dai)
+{
+ struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
+ struct hdac_ext_dma_params *dd;
+
+ if (dai->id > 0) {
+ dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n");
+ return -ENODEV;
+ }
+
+ dd = kzalloc(sizeof(*dd), GFP_KERNEL);
+ if (!dd)
+ return -ENOMEM;
+ dd->format = snd_hdac_calc_stream_format(params_rate(hparams),
+ params_channels(hparams), params_format(hparams),
+ 24, 0);
+
+ snd_soc_dai_set_dma_data(dai, substream, (void *)dd);
+
+ return 0;
+}
+
+static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai);
+ struct hdac_ext_dma_params *dd;
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct hdac_hdmi_dai_pin_map *dai_map;
+
+ dai_map = &hdmi->dai_map[dai->id];
+
+ snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
+ AC_VERB_SET_CHANNEL_STREAMID, 0);
+ snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
+ AC_VERB_SET_STREAM_FORMAT, 0);
+
+ dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
+ snd_soc_dai_set_dma_data(dai, substream, NULL);
+
+ kfree(dd);
+
+ return 0;
+}
+
+static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
+ struct hdac_hdmi_priv *hdmi = hdac->private_data;
+ struct hdac_hdmi_dai_pin_map *dai_map;
+ int val;
+
+ if (dai->id > 0) {
+ dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n");
+ return -ENODEV;
+ }
+
+ dai_map = &hdmi->dai_map[dai->id];
+
+ val = snd_hdac_codec_read(&hdac->hdac, dai_map->pin->nid, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ dev_info(&hdac->hdac.dev, "Val for AC_VERB_GET_PIN_SENSE: %x\n", val);
+
+ if ((!(val & AC_PINSENSE_PRESENCE)) || (!(val & AC_PINSENSE_ELDV))) {
+ dev_err(&hdac->hdac.dev, "Monitor presence invalid with val: %x\n", val);
+ return -ENODEV;
+ }
+
+ hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0);
+
+ snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+
+ return 0;
+}
+
+static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
+ struct hdac_hdmi_priv *hdmi = hdac->private_data;
+ struct hdac_hdmi_dai_pin_map *dai_map;
+
+ dai_map = &hdmi->dai_map[dai->id];
+
+ hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3);
+
+ snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+}
+
+static int
+hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt)
+{
+ int err;
+
+ /* Only stereo supported as of now */
+ cvt->params.channels_min = cvt->params.channels_max = 2;
+
+ err = snd_hdac_query_supported_pcm(hdac, cvt->nid,
+ &cvt->params.rates,
+ &cvt->params.formats,
+ &cvt->params.maxbps);
+ if (err < 0)
+ dev_err(&hdac->dev,
+ "Failed to query pcm params for nid %d: %d\n",
+ cvt->nid, err);
+
+ return err;
+}
+
+static void hdac_hdmi_fill_widget_info(struct snd_soc_dapm_widget *w,
+ enum snd_soc_dapm_type id,
+ const char *wname, const char *stream)
+{
+ w->id = id;
+ w->name = wname;
+ w->sname = stream;
+ w->reg = SND_SOC_NOPM;
+ w->shift = 0;
+ w->kcontrol_news = NULL;
+ w->num_kcontrols = 0;
+ w->priv = NULL;
+}
+
+static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route,
+ const char *sink, const char *control, const char *src)
+{
+ route->sink = sink;
+ route->source = src;
+ route->control = control;
+ route->connected = NULL;
+}
+
+static void create_fill_widget_route_map(struct snd_soc_dapm_context *dapm,
+ struct hdac_hdmi_dai_pin_map *dai_map)
+{
+ struct snd_soc_dapm_route route[1];
+ struct snd_soc_dapm_widget widgets[2] = { {0} };
+
+ memset(&route, 0, sizeof(route));
+
+ hdac_hdmi_fill_widget_info(&widgets[0], snd_soc_dapm_output,
+ "hif1 Output", NULL);
+ hdac_hdmi_fill_widget_info(&widgets[1], snd_soc_dapm_aif_in,
+ "Coverter 1", "hif1");
+
+ hdac_hdmi_fill_route(&route[0], "hif1 Output", NULL, "Coverter 1");
+
+ snd_soc_dapm_new_controls(dapm, widgets, ARRAY_SIZE(widgets));
+ snd_soc_dapm_add_routes(dapm, route, ARRAY_SIZE(route));
+}
+
+static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
+{
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct hdac_hdmi_dai_pin_map *dai_map = &hdmi->dai_map[0];
+ struct hdac_hdmi_cvt *cvt;
+ struct hdac_hdmi_pin *pin;
+
+ if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list))
+ return -EINVAL;
+
+ /*
+ * Currently on board only 1 pin and 1 converter is enabled for
+ * simplification, more will be added eventually
+ * So using fixed map for dai_id:pin:cvt
+ */
+ cvt = list_first_entry(&hdmi->cvt_list, struct hdac_hdmi_cvt, head);
+ pin = list_first_entry(&hdmi->pin_list, struct hdac_hdmi_pin, head);
+
+ dai_map->dai_id = 0;
+ dai_map->pin = pin;
+
+ dai_map->cvt = cvt;
+
+ /* Enable out path for this pin widget */
+ snd_hdac_codec_write(&edev->hdac, pin->nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+
+ /* Enable transmission */
+ snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
+ AC_VERB_SET_DIGI_CONVERT_1, 1);
+
+ /* Category Code (CC) to zero */
+ snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
+ AC_VERB_SET_DIGI_CONVERT_2, 0);
+
+ snd_hdac_codec_write(&edev->hdac, pin->nid, 0,
+ AC_VERB_SET_CONNECT_SEL, 0);
+
+ return 0;
+}
+
+static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
+{
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct hdac_hdmi_cvt *cvt;
+
+ cvt = kzalloc(sizeof(*cvt), GFP_KERNEL);
+ if (!cvt)
+ return -ENOMEM;
+
+ cvt->nid = nid;
+
+ list_add_tail(&cvt->head, &hdmi->cvt_list);
+ hdmi->num_cvt++;
+
+ return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
+}
+
+static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
+{
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct hdac_hdmi_pin *pin;
+
+ pin = kzalloc(sizeof(*pin), GFP_KERNEL);
+ if (!pin)
+ return -ENOMEM;
+
+ pin->nid = nid;
+
+ list_add_tail(&pin->head, &hdmi->pin_list);
+ hdmi->num_pin++;
+
+ return 0;
+}
+
+/*
+ * Parse all nodes and store the cvt/pin nids in array
+ * Add one time initialization for pin and cvt widgets
+ */
+static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
+{
+ hda_nid_t nid;
+ int i, num_nodes;
+ struct hdac_device *hdac = &edev->hdac;
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ int ret;
+
+ num_nodes = snd_hdac_get_sub_nodes(hdac, hdac->afg, &nid);
+ if (!nid || num_nodes <= 0) {
+ dev_warn(&hdac->dev, "HDMI: failed to get afg sub nodes\n");
+ return -EINVAL;
+ }
+
+ hdac->num_nodes = num_nodes;
+ hdac->start_nid = nid;
+
+ for (i = 0; i < hdac->num_nodes; i++, nid++) {
+ unsigned int caps;
+ unsigned int type;
+
+ caps = get_wcaps(hdac, nid);
+ type = get_wcaps_type(caps);
+
+ if (!(caps & AC_WCAP_DIGITAL))
+ continue;
+
+ switch (type) {
+
+ case AC_WID_AUD_OUT:
+ ret = hdac_hdmi_add_cvt(edev, nid);
+ if (ret < 0)
+ return ret;
+ break;
+
+ case AC_WID_PIN:
+ ret = hdac_hdmi_add_pin(edev, nid);
+ if (ret < 0)
+ return ret;
+ break;
+ }
+ }
+
+ hdac->end_nid = nid;
+
+ if (!hdmi->num_pin || !hdmi->num_cvt)
+ return -EIO;
+
+ return hdac_hdmi_init_dai_map(edev);
+}
+
+static int hdmi_codec_probe(struct snd_soc_codec *codec)
+{
+ struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(&codec->component);
+
+ edev->scodec = codec;
+
+ create_fill_widget_route_map(dapm, &hdmi->dai_map[0]);
+
+ /* Imp: Store the card pointer in hda_codec */
+ edev->card = dapm->card->snd_card;
+
+ /*
+ * hdac_device core already sets the state to active and calls
+ * get_noresume. So enable runtime and set the device to suspend.
+ */
+ pm_runtime_enable(&edev->hdac.dev);
+ pm_runtime_put(&edev->hdac.dev);
+ pm_runtime_suspend(&edev->hdac.dev);
+
+ return 0;
+}
+
+static int hdmi_codec_remove(struct snd_soc_codec *codec)
+{
+ struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
+
+ pm_runtime_disable(&edev->hdac.dev);
+ return 0;
+}
+
+static struct snd_soc_codec_driver hdmi_hda_codec = {
+ .probe = hdmi_codec_probe,
+ .remove = hdmi_codec_remove,
+ .idle_bias_off = true,
+};
+
+static struct snd_soc_dai_ops hdmi_dai_ops = {
+ .startup = hdac_hdmi_pcm_open,
+ .shutdown = hdac_hdmi_pcm_close,
+ .hw_params = hdac_hdmi_set_hw_params,
+ .prepare = hdac_hdmi_playback_prepare,
+ .hw_free = hdac_hdmi_playback_cleanup,
+};
+
+static struct snd_soc_dai_driver hdmi_dais[] = {
+ { .name = "intel-hdmi-hif1",
+ .playback = {
+ .stream_name = "hif1",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+
+ },
+ .ops = &hdmi_dai_ops,
+ },
+};
+
+static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
+{
+ struct hdac_device *codec = &edev->hdac;
+ struct hdac_hdmi_priv *hdmi_priv;
+ int ret = 0;
+
+ hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL);
+ if (hdmi_priv == NULL)
+ return -ENOMEM;
+
+ edev->private_data = hdmi_priv;
+
+ dev_set_drvdata(&codec->dev, edev);
+
+ INIT_LIST_HEAD(&hdmi_priv->pin_list);
+ INIT_LIST_HEAD(&hdmi_priv->cvt_list);
+
+ ret = hdac_hdmi_parse_and_map_nid(edev);
+ if (ret < 0)
+ return ret;
+
+ /* ASoC specific initialization */
+ return snd_soc_register_codec(&codec->dev, &hdmi_hda_codec,
+ hdmi_dais, ARRAY_SIZE(hdmi_dais));
+}
+
+static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
+{
+ struct hdac_hdmi_priv *hdmi = edev->private_data;
+ struct hdac_hdmi_pin *pin, *pin_next;
+ struct hdac_hdmi_cvt *cvt, *cvt_next;
+
+ snd_soc_unregister_codec(&edev->hdac.dev);
+
+ list_for_each_entry_safe(cvt, cvt_next, &hdmi->cvt_list, head) {
+ list_del(&cvt->head);
+ kfree(cvt);
+ }
+
+ list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) {
+ list_del(&pin->head);
+ kfree(pin);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int hdac_hdmi_runtime_suspend(struct device *dev)
+{
+ struct hdac_ext_device *edev = to_hda_ext_device(dev);
+ struct hdac_device *hdac = &edev->hdac;
+ struct hdac_bus *bus = hdac->bus;
+ int err;
+
+ dev_dbg(dev, "Enter: %s\n", __func__);
+
+ /* controller may not have been initialized for the first time */
+ if (!bus)
+ return 0;
+
+ /* Power down afg */
+ if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3))
+ snd_hdac_codec_write(hdac, hdac->afg, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+
+ err = snd_hdac_display_power(bus, false);
+ if (err < 0) {
+ dev_err(bus->dev, "Cannot turn on display power on i915\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int hdac_hdmi_runtime_resume(struct device *dev)
+{
+ struct hdac_ext_device *edev = to_hda_ext_device(dev);
+ struct hdac_device *hdac = &edev->hdac;
+ struct hdac_bus *bus = hdac->bus;
+ int err;
+
+ dev_dbg(dev, "Enter: %s\n", __func__);
+
+ /* controller may not have been initialized for the first time */
+ if (!bus)
+ return 0;
+
+ err = snd_hdac_display_power(bus, true);
+ if (err < 0) {
+ dev_err(bus->dev, "Cannot turn on display power on i915\n");
+ return err;
+ }
+
+ /* Power up afg */
+ if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0))
+ snd_hdac_codec_write(hdac, hdac->afg, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+ return 0;
+}
+#else
+#define hdac_hdmi_runtime_suspend NULL
+#define hdac_hdmi_runtime_resume NULL
+#endif
+
+static const struct dev_pm_ops hdac_hdmi_pm = {
+ SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
+};
+
+static const struct hda_device_id hdmi_list[] = {
+ HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0),
+ {}
+};
+
+MODULE_DEVICE_TABLE(hdaudio, hdmi_list);
+
+static struct hdac_ext_driver hdmi_driver = {
+ . hdac = {
+ .driver = {
+ .name = "HDMI HDA Codec",
+ .pm = &hdac_hdmi_pm,
+ },
+ .id_table = hdmi_list,
+ },
+ .probe = hdac_hdmi_dev_probe,
+ .remove = hdac_hdmi_dev_remove,
+};
+
+static int __init hdmi_init(void)
+{
+ return snd_hda_ext_driver_register(&hdmi_driver);
+}
+
+static void __exit hdmi_exit(void)
+{
+ snd_hda_ext_driver_unregister(&hdmi_driver);
+}
+
+module_init(hdmi_init);
+module_exit(hdmi_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HDMI HD codec");
+MODULE_AUTHOR("Samreen Nilofer<samreen.nilofer@intel.com>");
+MODULE_AUTHOR("Subhransu S. Prusty<subhransu.s.prusty@intel.com>");
diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c
new file mode 100644
index 000000000000..9b6e8840a1b5
--- /dev/null
+++ b/sound/soc/codecs/inno_rk3036.c
@@ -0,0 +1,490 @@
+/*
+ * Driver of Inno codec for rk3036 by Rockchip Inc.
+ *
+ * Author: Rockchip Inc.
+ * Author: Zheng ShunQian<zhengsq@rock-chips.com>
+ */
+
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc-dai.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include "inno_rk3036.h"
+
+struct rk3036_codec_priv {
+ void __iomem *base;
+ struct clk *pclk;
+ struct regmap *regmap;
+ struct device *dev;
+};
+
+static const DECLARE_TLV_DB_MINMAX(rk3036_codec_hp_tlv, -39, 0);
+
+static int rk3036_codec_antipop_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+
+ return 0;
+}
+
+static int rk3036_codec_antipop_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ int val, ret, regval;
+
+ ret = snd_soc_component_read(component, INNO_R09, &regval);
+ if (ret)
+ return ret;
+ val = ((regval >> INNO_R09_HPL_ANITPOP_SHIFT) &
+ INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON;
+ ucontrol->value.integer.value[0] = val;
+
+ val = ((regval >> INNO_R09_HPR_ANITPOP_SHIFT) &
+ INNO_R09_HP_ANTIPOP_MSK) == INNO_R09_HP_ANTIPOP_ON;
+ ucontrol->value.integer.value[1] = val;
+
+ return 0;
+}
+
+static int rk3036_codec_antipop_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ int val, ret, regmsk;
+
+ val = (ucontrol->value.integer.value[0] ?
+ INNO_R09_HP_ANTIPOP_ON : INNO_R09_HP_ANTIPOP_OFF) <<
+ INNO_R09_HPL_ANITPOP_SHIFT;
+ val |= (ucontrol->value.integer.value[1] ?
+ INNO_R09_HP_ANTIPOP_ON : INNO_R09_HP_ANTIPOP_OFF) <<
+ INNO_R09_HPR_ANITPOP_SHIFT;
+
+ regmsk = INNO_R09_HP_ANTIPOP_MSK << INNO_R09_HPL_ANITPOP_SHIFT |
+ INNO_R09_HP_ANTIPOP_MSK << INNO_R09_HPR_ANITPOP_SHIFT;
+
+ ret = snd_soc_component_update_bits(component, INNO_R09,
+ regmsk, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+#define SOC_RK3036_CODEC_ANTIPOP_DECL(xname) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = rk3036_codec_antipop_info, .get = rk3036_codec_antipop_get, \
+ .put = rk3036_codec_antipop_put, }
+
+static const struct snd_kcontrol_new rk3036_codec_dapm_controls[] = {
+ SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", INNO_R07, INNO_R08,
+ INNO_HP_GAIN_SHIFT, INNO_HP_GAIN_N39DB,
+ INNO_HP_GAIN_0DB, 0, rk3036_codec_hp_tlv),
+ SOC_DOUBLE("Zero Cross Switch", INNO_R06, INNO_R06_VOUTL_CZ_SHIFT,
+ INNO_R06_VOUTR_CZ_SHIFT, 1, 0),
+ SOC_DOUBLE("Headphone Switch", INNO_R09, INNO_R09_HPL_MUTE_SHIFT,
+ INNO_R09_HPR_MUTE_SHIFT, 1, 0),
+ SOC_RK3036_CODEC_ANTIPOP_DECL("Anti-pop Switch"),
+};
+
+static const struct snd_kcontrol_new rk3036_codec_hpl_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DAC Left Out Switch", INNO_R09,
+ INNO_R09_DACL_SWITCH_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new rk3036_codec_hpr_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DAC Right Out Switch", INNO_R09,
+ INNO_R09_DACR_SWITCH_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new rk3036_codec_hpl_switch_controls[] = {
+ SOC_DAPM_SINGLE("HP Left Out Switch", INNO_R05,
+ INNO_R05_HPL_WORK_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new rk3036_codec_hpr_switch_controls[] = {
+ SOC_DAPM_SINGLE("HP Right Out Switch", INNO_R05,
+ INNO_R05_HPR_WORK_SHIFT, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget rk3036_codec_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY_S("DAC PWR", 1, INNO_R06,
+ INNO_R06_DAC_EN_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DACL VREF", 2, INNO_R04,
+ INNO_R04_DACL_VREF_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DACR VREF", 2, INNO_R04,
+ INNO_R04_DACR_VREF_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DACL HiLo VREF", 3, INNO_R06,
+ INNO_R06_DACL_HILO_VREF_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DACR HiLo VREF", 3, INNO_R06,
+ INNO_R06_DACR_HILO_VREF_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DACR CLK", 3, INNO_R04,
+ INNO_R04_DACR_CLK_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DACL CLK", 3, INNO_R04,
+ INNO_R04_DACL_CLK_SHIFT, 0, NULL, 0),
+
+ SND_SOC_DAPM_DAC("DACL", "Left Playback", INNO_R04,
+ INNO_R04_DACL_SW_SHIFT, 0),
+ SND_SOC_DAPM_DAC("DACR", "Right Playback", INNO_R04,
+ INNO_R04_DACR_SW_SHIFT, 0),
+
+ SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
+ rk3036_codec_hpl_mixer_controls,
+ ARRAY_SIZE(rk3036_codec_hpl_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Right Headphone Mixer", SND_SOC_NOPM, 0, 0,
+ rk3036_codec_hpr_mixer_controls,
+ ARRAY_SIZE(rk3036_codec_hpr_mixer_controls)),
+
+ SND_SOC_DAPM_PGA("HP Left Out", INNO_R05,
+ INNO_R05_HPL_EN_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HP Right Out", INNO_R05,
+ INNO_R05_HPR_EN_SHIFT, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("HP Left Switch", SND_SOC_NOPM, 0, 0,
+ rk3036_codec_hpl_switch_controls,
+ ARRAY_SIZE(rk3036_codec_hpl_switch_controls)),
+ SND_SOC_DAPM_MIXER("HP Right Switch", SND_SOC_NOPM, 0, 0,
+ rk3036_codec_hpr_switch_controls,
+ ARRAY_SIZE(rk3036_codec_hpr_switch_controls)),
+
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+};
+
+static const struct snd_soc_dapm_route rk3036_codec_dapm_routes[] = {
+ {"DACL VREF", NULL, "DAC PWR"},
+ {"DACR VREF", NULL, "DAC PWR"},
+ {"DACL HiLo VREF", NULL, "DAC PWR"},
+ {"DACR HiLo VREF", NULL, "DAC PWR"},
+ {"DACL CLK", NULL, "DAC PWR"},
+ {"DACR CLK", NULL, "DAC PWR"},
+
+ {"DACL", NULL, "DACL VREF"},
+ {"DACL", NULL, "DACL HiLo VREF"},
+ {"DACL", NULL, "DACL CLK"},
+ {"DACR", NULL, "DACR VREF"},
+ {"DACR", NULL, "DACR HiLo VREF"},
+ {"DACR", NULL, "DACR CLK"},
+
+ {"Left Headphone Mixer", "DAC Left Out Switch", "DACL"},
+ {"Right Headphone Mixer", "DAC Right Out Switch", "DACR"},
+ {"HP Left Out", NULL, "Left Headphone Mixer"},
+ {"HP Right Out", NULL, "Right Headphone Mixer"},
+
+ {"HP Left Switch", "HP Left Out Switch", "HP Left Out"},
+ {"HP Right Switch", "HP Right Out Switch", "HP Right Out"},
+
+ {"HPL", NULL, "HP Left Switch"},
+ {"HPR", NULL, "HP Right Switch"},
+};
+
+static int rk3036_codec_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int reg01_val = 0, reg02_val = 0, reg03_val = 0;
+
+ dev_dbg(codec->dev, "rk3036_codec dai set fmt : %08x\n", fmt);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ reg01_val |= INNO_R01_PINDIR_IN_SLAVE |
+ INNO_R01_I2SMODE_SLAVE;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ reg01_val |= INNO_R01_PINDIR_OUT_MASTER |
+ INNO_R01_I2SMODE_MASTER;
+ break;
+ default:
+ dev_err(codec->dev, "invalid fmt\n");
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ reg02_val |= INNO_R02_DACM_PCM;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ reg02_val |= INNO_R02_DACM_I2S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ reg02_val |= INNO_R02_DACM_RJM;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ reg02_val |= INNO_R02_DACM_LJM;
+ break;
+ default:
+ dev_err(codec->dev, "set dai format failed\n");
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ reg02_val |= INNO_R02_LRCP_NORMAL;
+ reg03_val |= INNO_R03_BCP_NORMAL;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ reg02_val |= INNO_R02_LRCP_REVERSAL;
+ reg03_val |= INNO_R03_BCP_REVERSAL;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ reg02_val |= INNO_R02_LRCP_REVERSAL;
+ reg03_val |= INNO_R03_BCP_NORMAL;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ reg02_val |= INNO_R02_LRCP_NORMAL;
+ reg03_val |= INNO_R03_BCP_REVERSAL;
+ break;
+ default:
+ dev_err(codec->dev, "set dai format failed\n");
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, INNO_R01, INNO_R01_I2SMODE_MSK |
+ INNO_R01_PINDIR_MSK, reg01_val);
+ snd_soc_update_bits(codec, INNO_R02, INNO_R02_LRCP_MSK |
+ INNO_R02_DACM_MSK, reg02_val);
+ snd_soc_update_bits(codec, INNO_R03, INNO_R03_BCP_MSK, reg03_val);
+
+ return 0;
+}
+
+static int rk3036_codec_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int reg02_val = 0, reg03_val = 0;
+
+ switch (params_format(hw_params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ reg02_val |= INNO_R02_VWL_16BIT;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ reg02_val |= INNO_R02_VWL_20BIT;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ reg02_val |= INNO_R02_VWL_24BIT;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ reg02_val |= INNO_R02_VWL_32BIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ reg02_val |= INNO_R02_LRCP_NORMAL;
+ reg03_val |= INNO_R03_FWL_32BIT | INNO_R03_DACR_WORK;
+
+ snd_soc_update_bits(codec, INNO_R02, INNO_R02_LRCP_MSK |
+ INNO_R02_VWL_MSK, reg02_val);
+ snd_soc_update_bits(codec, INNO_R03, INNO_R03_DACR_MSK |
+ INNO_R03_FWL_MSK, reg03_val);
+ return 0;
+}
+
+#define RK3036_CODEC_RATES (SNDRV_PCM_RATE_8000 | \
+ SNDRV_PCM_RATE_16000 | \
+ SNDRV_PCM_RATE_32000 | \
+ SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_96000)
+
+#define RK3036_CODEC_FMTS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops rk3036_codec_dai_ops = {
+ .set_fmt = rk3036_codec_dai_set_fmt,
+ .hw_params = rk3036_codec_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver rk3036_codec_dai_driver[] = {
+ {
+ .name = "rk3036-codec-dai",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RK3036_CODEC_RATES,
+ .formats = RK3036_CODEC_FMTS,
+ },
+ .ops = &rk3036_codec_dai_ops,
+ .symmetric_rates = 1,
+ },
+};
+
+static void rk3036_codec_reset(struct snd_soc_codec *codec)
+{
+ snd_soc_write(codec, INNO_R00,
+ INNO_R00_CSR_RESET | INNO_R00_CDCR_RESET);
+ snd_soc_write(codec, INNO_R00,
+ INNO_R00_CSR_WORK | INNO_R00_CDCR_WORK);
+}
+
+static int rk3036_codec_probe(struct snd_soc_codec *codec)
+{
+ rk3036_codec_reset(codec);
+ return 0;
+}
+
+static int rk3036_codec_remove(struct snd_soc_codec *codec)
+{
+ rk3036_codec_reset(codec);
+ return 0;
+}
+
+static int rk3036_codec_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_STANDBY:
+ /* set a big current for capacitor charging. */
+ snd_soc_write(codec, INNO_R10, INNO_R10_MAX_CUR);
+ /* start precharge */
+ snd_soc_write(codec, INNO_R06, INNO_R06_DAC_PRECHARGE);
+
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ /* set a big current for capacitor discharging. */
+ snd_soc_write(codec, INNO_R10, INNO_R10_MAX_CUR);
+ /* start discharge. */
+ snd_soc_write(codec, INNO_R06, INNO_R06_DAC_DISCHARGE);
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver rk3036_codec_driver = {
+ .probe = rk3036_codec_probe,
+ .remove = rk3036_codec_remove,
+ .set_bias_level = rk3036_codec_set_bias_level,
+ .controls = rk3036_codec_dapm_controls,
+ .num_controls = ARRAY_SIZE(rk3036_codec_dapm_controls),
+ .dapm_routes = rk3036_codec_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(rk3036_codec_dapm_routes),
+ .dapm_widgets = rk3036_codec_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rk3036_codec_dapm_widgets),
+};
+
+static const struct regmap_config rk3036_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+};
+
+#define GRF_SOC_CON0 0x00140
+#define GRF_ACODEC_SEL (BIT(10) | BIT(16 + 10))
+
+static int rk3036_codec_platform_probe(struct platform_device *pdev)
+{
+ struct rk3036_codec_priv *priv;
+ struct device_node *of_node = pdev->dev.of_node;
+ struct resource *res;
+ void __iomem *base;
+ struct regmap *grf;
+ int ret;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ priv->base = base;
+ priv->regmap = devm_regmap_init_mmio(&pdev->dev, priv->base,
+ &rk3036_codec_regmap_config);
+ if (IS_ERR(priv->regmap)) {
+ dev_err(&pdev->dev, "init regmap failed\n");
+ return PTR_ERR(priv->regmap);
+ }
+
+ grf = syscon_regmap_lookup_by_phandle(of_node, "rockchip,grf");
+ if (IS_ERR(grf)) {
+ dev_err(&pdev->dev, "needs 'rockchip,grf' property\n");
+ return PTR_ERR(grf);
+ }
+ ret = regmap_write(grf, GRF_SOC_CON0, GRF_ACODEC_SEL);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not write to GRF: %d\n", ret);
+ return ret;
+ }
+
+ priv->pclk = devm_clk_get(&pdev->dev, "acodec_pclk");
+ if (IS_ERR(priv->pclk))
+ return PTR_ERR(priv->pclk);
+
+ ret = clk_prepare_enable(priv->pclk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to enable clk\n");
+ return ret;
+ }
+
+ priv->dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, priv);
+
+ ret = snd_soc_register_codec(&pdev->dev, &rk3036_codec_driver,
+ rk3036_codec_dai_driver,
+ ARRAY_SIZE(rk3036_codec_dai_driver));
+ if (ret) {
+ clk_disable_unprepare(priv->pclk);
+ dev_set_drvdata(&pdev->dev, NULL);
+ }
+
+ return ret;
+}
+
+static int rk3036_codec_platform_remove(struct platform_device *pdev)
+{
+ struct rk3036_codec_priv *priv = dev_get_drvdata(&pdev->dev);
+
+ snd_soc_unregister_codec(&pdev->dev);
+ clk_disable_unprepare(priv->pclk);
+
+ return 0;
+}
+
+static const struct of_device_id rk3036_codec_of_match[] = {
+ { .compatible = "rockchip,rk3036-codec", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, rk3036_codec_of_match);
+
+static struct platform_driver rk3036_codec_platform_driver = {
+ .driver = {
+ .name = "rk3036-codec-platform",
+ .of_match_table = of_match_ptr(rk3036_codec_of_match),
+ },
+ .probe = rk3036_codec_platform_probe,
+ .remove = rk3036_codec_platform_remove,
+};
+
+module_platform_driver(rk3036_codec_platform_driver);
+
+MODULE_AUTHOR("Rockchip Inc.");
+MODULE_DESCRIPTION("Rockchip rk3036 codec driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/inno_rk3036.h b/sound/soc/codecs/inno_rk3036.h
new file mode 100644
index 000000000000..da759c6c7501
--- /dev/null
+++ b/sound/soc/codecs/inno_rk3036.h
@@ -0,0 +1,123 @@
+/*
+ * Driver of Inno Codec for rk3036 by Rockchip Inc.
+ *
+ * Author: Zheng ShunQian<zhengsq@rock-chips.com>
+ */
+
+#ifndef _INNO_RK3036_CODEC_H
+#define _INNO_RK3036_CODEC_H
+
+/* codec registers */
+#define INNO_R00 0x00
+#define INNO_R01 0x0c
+#define INNO_R02 0x10
+#define INNO_R03 0x14
+#define INNO_R04 0x88
+#define INNO_R05 0x8c
+#define INNO_R06 0x90
+#define INNO_R07 0x94
+#define INNO_R08 0x98
+#define INNO_R09 0x9c
+#define INNO_R10 0xa0
+
+/* register bit filed */
+#define INNO_R00_CSR_RESET (0x0 << 0) /*codec system reset*/
+#define INNO_R00_CSR_WORK (0x1 << 0)
+#define INNO_R00_CDCR_RESET (0x0 << 1) /*codec digital core reset*/
+#define INNO_R00_CDCR_WORK (0x1 << 1)
+#define INNO_R00_PRB_DISABLE (0x0 << 6) /*power reset bypass*/
+#define INNO_R00_PRB_ENABLE (0x1 << 6)
+
+#define INNO_R01_I2SMODE_MSK (0x1 << 4)
+#define INNO_R01_I2SMODE_SLAVE (0x0 << 4)
+#define INNO_R01_I2SMODE_MASTER (0x1 << 4)
+#define INNO_R01_PINDIR_MSK (0x1 << 5)
+#define INNO_R01_PINDIR_IN_SLAVE (0x0 << 5) /*direction of pin*/
+#define INNO_R01_PINDIR_OUT_MASTER (0x1 << 5)
+
+#define INNO_R02_LRS_MSK (0x1 << 2)
+#define INNO_R02_LRS_NORMAL (0x0 << 2) /*DAC Left Right Swap*/
+#define INNO_R02_LRS_SWAP (0x1 << 2)
+#define INNO_R02_DACM_MSK (0x3 << 3)
+#define INNO_R02_DACM_PCM (0x3 << 3) /*DAC Mode*/
+#define INNO_R02_DACM_I2S (0x2 << 3)
+#define INNO_R02_DACM_LJM (0x1 << 3)
+#define INNO_R02_DACM_RJM (0x0 << 3)
+#define INNO_R02_VWL_MSK (0x3 << 5)
+#define INNO_R02_VWL_32BIT (0x3 << 5) /*1/2Frame Valid Word Len*/
+#define INNO_R02_VWL_24BIT (0x2 << 5)
+#define INNO_R02_VWL_20BIT (0x1 << 5)
+#define INNO_R02_VWL_16BIT (0x0 << 5)
+#define INNO_R02_LRCP_MSK (0x1 << 7)
+#define INNO_R02_LRCP_NORMAL (0x0 << 7) /*Left Right Polarity*/
+#define INNO_R02_LRCP_REVERSAL (0x1 << 7)
+
+#define INNO_R03_BCP_MSK (0x1 << 0)
+#define INNO_R03_BCP_NORMAL (0x0 << 0) /*DAC bit clock polarity*/
+#define INNO_R03_BCP_REVERSAL (0x1 << 0)
+#define INNO_R03_DACR_MSK (0x1 << 1)
+#define INNO_R03_DACR_RESET (0x0 << 1) /*DAC Reset*/
+#define INNO_R03_DACR_WORK (0x1 << 1)
+#define INNO_R03_FWL_MSK (0x3 << 2)
+#define INNO_R03_FWL_32BIT (0x3 << 2) /*1/2Frame Word Length*/
+#define INNO_R03_FWL_24BIT (0x2 << 2)
+#define INNO_R03_FWL_20BIT (0x1 << 2)
+#define INNO_R03_FWL_16BIT (0x0 << 2)
+
+#define INNO_R04_DACR_SW_SHIFT 0
+#define INNO_R04_DACL_SW_SHIFT 1
+#define INNO_R04_DACR_CLK_SHIFT 2
+#define INNO_R04_DACL_CLK_SHIFT 3
+#define INNO_R04_DACR_VREF_SHIFT 4
+#define INNO_R04_DACL_VREF_SHIFT 5
+
+#define INNO_R05_HPR_EN_SHIFT 0
+#define INNO_R05_HPL_EN_SHIFT 1
+#define INNO_R05_HPR_WORK_SHIFT 2
+#define INNO_R05_HPL_WORK_SHIFT 3
+
+#define INNO_R06_VOUTR_CZ_SHIFT 0
+#define INNO_R06_VOUTL_CZ_SHIFT 1
+#define INNO_R06_DACR_HILO_VREF_SHIFT 2
+#define INNO_R06_DACL_HILO_VREF_SHIFT 3
+#define INNO_R06_DAC_EN_SHIFT 5
+
+#define INNO_R06_DAC_PRECHARGE (0x0 << 4) /*PreCharge control for DAC*/
+#define INNO_R06_DAC_DISCHARGE (0x1 << 4)
+
+#define INNO_HP_GAIN_SHIFT 0
+/* Gain of output, 1.5db step: -39db(0x0) ~ 0db(0x1a) ~ 6db(0x1f) */
+#define INNO_HP_GAIN_0DB 0x1a
+#define INNO_HP_GAIN_N39DB 0x0
+
+#define INNO_R09_HP_ANTIPOP_MSK 0x3
+#define INNO_R09_HP_ANTIPOP_OFF 0x1
+#define INNO_R09_HP_ANTIPOP_ON 0x2
+#define INNO_R09_HPR_ANITPOP_SHIFT 0
+#define INNO_R09_HPL_ANITPOP_SHIFT 2
+#define INNO_R09_HPR_MUTE_SHIFT 4
+#define INNO_R09_HPL_MUTE_SHIFT 5
+#define INNO_R09_DACR_SWITCH_SHIFT 6
+#define INNO_R09_DACL_SWITCH_SHIFT 7
+
+#define INNO_R10_CHARGE_SEL_CUR_400I_YES (0x0 << 0)
+#define INNO_R10_CHARGE_SEL_CUR_400I_NO (0x1 << 0)
+#define INNO_R10_CHARGE_SEL_CUR_260I_YES (0x0 << 1)
+#define INNO_R10_CHARGE_SEL_CUR_260I_NO (0x1 << 1)
+#define INNO_R10_CHARGE_SEL_CUR_130I_YES (0x0 << 2)
+#define INNO_R10_CHARGE_SEL_CUR_130I_NO (0x1 << 2)
+#define INNO_R10_CHARGE_SEL_CUR_100I_YES (0x0 << 3)
+#define INNO_R10_CHARGE_SEL_CUR_100I_NO (0x1 << 3)
+#define INNO_R10_CHARGE_SEL_CUR_050I_YES (0x0 << 4)
+#define INNO_R10_CHARGE_SEL_CUR_050I_NO (0x1 << 4)
+#define INNO_R10_CHARGE_SEL_CUR_027I_YES (0x0 << 5)
+#define INNO_R10_CHARGE_SEL_CUR_027I_NO (0x1 << 5)
+
+#define INNO_R10_MAX_CUR (INNO_R10_CHARGE_SEL_CUR_400I_YES | \
+ INNO_R10_CHARGE_SEL_CUR_260I_YES | \
+ INNO_R10_CHARGE_SEL_CUR_130I_YES | \
+ INNO_R10_CHARGE_SEL_CUR_100I_YES | \
+ INNO_R10_CHARGE_SEL_CUR_050I_YES | \
+ INNO_R10_CHARGE_SEL_CUR_027I_YES)
+
+#endif
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
index f5e3dce2633a..5b1dfb1518fb 100644
--- a/sound/soc/codecs/max98357a.c
+++ b/sound/soc/codecs/max98357a.c
@@ -12,6 +12,7 @@
* max98357a.c -- MAX98357A ALSA SoC Codec driver
*/
+#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio.h>
@@ -123,10 +124,19 @@ static const struct of_device_id max98357a_device_id[] = {
MODULE_DEVICE_TABLE(of, max98357a_device_id);
#endif
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id max98357a_acpi_match[] = {
+ { "MX98357A", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, max98357a_acpi_match);
+#endif
+
static struct platform_driver max98357a_platform_driver = {
.driver = {
.name = "max98357a",
.of_match_table = of_match_ptr(max98357a_device_id),
+ .acpi_match_table = ACPI_PTR(max98357a_acpi_match),
},
.probe = max98357a_platform_probe,
.remove = max98357a_platform_remove,
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c
deleted file mode 100644
index 08bb4863e96f..000000000000
--- a/sound/soc/codecs/pcm1792a.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * PCM1792A ASoC codec driver
- *
- * Copyright (c) Amarula Solutions B.V. 2013
- *
- * Michael Trimarchi <michael@amarulasolutions.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; either version 2
- * of the License, or (at your option) any later version.
- *
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/spi/spi.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-#include <sound/tlv.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-
-#include "pcm1792a.h"
-
-#define PCM1792A_DAC_VOL_LEFT 0x10
-#define PCM1792A_DAC_VOL_RIGHT 0x11
-#define PCM1792A_FMT_CONTROL 0x12
-#define PCM1792A_MODE_CONTROL 0x13
-#define PCM1792A_SOFT_MUTE PCM1792A_FMT_CONTROL
-
-#define PCM1792A_FMT_MASK 0x70
-#define PCM1792A_FMT_SHIFT 4
-#define PCM1792A_MUTE_MASK 0x01
-#define PCM1792A_MUTE_SHIFT 0
-#define PCM1792A_ATLD_ENABLE (1 << 7)
-
-static const struct reg_default pcm1792a_reg_defaults[] = {
- { 0x10, 0xff },
- { 0x11, 0xff },
- { 0x12, 0x50 },
- { 0x13, 0x00 },
- { 0x14, 0x00 },
- { 0x15, 0x01 },
- { 0x16, 0x00 },
- { 0x17, 0x00 },
-};
-
-static bool pcm1792a_accessible_reg(struct device *dev, unsigned int reg)
-{
- return reg >= 0x10 && reg <= 0x17;
-}
-
-static bool pcm1792a_writeable_reg(struct device *dev, unsigned register reg)
-{
- bool accessible;
-
- accessible = pcm1792a_accessible_reg(dev, reg);
-
- return accessible && reg != 0x16 && reg != 0x17;
-}
-
-struct pcm1792a_private {
- struct regmap *regmap;
- unsigned int format;
- unsigned int rate;
-};
-
-static int pcm1792a_set_dai_fmt(struct snd_soc_dai *codec_dai,
- unsigned int format)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
-
- priv->format = format;
-
- return 0;
-}
-
-static int pcm1792a_digital_mute(struct snd_soc_dai *dai, int mute)
-{
- struct snd_soc_codec *codec = dai->codec;
- struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- ret = regmap_update_bits(priv->regmap, PCM1792A_SOFT_MUTE,
- PCM1792A_MUTE_MASK, !!mute);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int pcm1792a_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_codec *codec = dai->codec;
- struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec);
- int val = 0, ret;
-
- priv->rate = params_rate(params);
-
- switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_RIGHT_J:
- switch (params_width(params)) {
- case 24:
- case 32:
- val = 2;
- break;
- case 16:
- val = 0;
- break;
- default:
- return -EINVAL;
- }
- break;
- case SND_SOC_DAIFMT_I2S:
- switch (params_width(params)) {
- case 24:
- case 32:
- val = 5;
- break;
- case 16:
- val = 4;
- break;
- default:
- return -EINVAL;
- }
- break;
- default:
- dev_err(codec->dev, "Invalid DAI format\n");
- return -EINVAL;
- }
-
- val = val << PCM1792A_FMT_SHIFT | PCM1792A_ATLD_ENABLE;
-
- ret = regmap_update_bits(priv->regmap, PCM1792A_FMT_CONTROL,
- PCM1792A_FMT_MASK | PCM1792A_ATLD_ENABLE, val);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static const struct snd_soc_dai_ops pcm1792a_dai_ops = {
- .set_fmt = pcm1792a_set_dai_fmt,
- .hw_params = pcm1792a_hw_params,
- .digital_mute = pcm1792a_digital_mute,
-};
-
-static const DECLARE_TLV_DB_SCALE(pcm1792a_dac_tlv, -12000, 50, 1);
-
-static const struct snd_kcontrol_new pcm1792a_controls[] = {
- SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM1792A_DAC_VOL_LEFT,
- PCM1792A_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0,
- pcm1792a_dac_tlv),
- SOC_SINGLE("DAC Invert Output Switch", PCM1792A_MODE_CONTROL, 7, 1, 0),
- SOC_SINGLE("DAC Rolloff Filter Switch", PCM1792A_MODE_CONTROL, 1, 1, 0),
-};
-
-static const struct snd_soc_dapm_widget pcm1792a_dapm_widgets[] = {
-SND_SOC_DAPM_OUTPUT("IOUTL+"),
-SND_SOC_DAPM_OUTPUT("IOUTL-"),
-SND_SOC_DAPM_OUTPUT("IOUTR+"),
-SND_SOC_DAPM_OUTPUT("IOUTR-"),
-};
-
-static const struct snd_soc_dapm_route pcm1792a_dapm_routes[] = {
- { "IOUTL+", NULL, "Playback" },
- { "IOUTL-", NULL, "Playback" },
- { "IOUTR+", NULL, "Playback" },
- { "IOUTR-", NULL, "Playback" },
-};
-
-static struct snd_soc_dai_driver pcm1792a_dai = {
- .name = "pcm1792a-hifi",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 2,
- .channels_max = 2,
- .rates = PCM1792A_RATES,
- .formats = PCM1792A_FORMATS, },
- .ops = &pcm1792a_dai_ops,
-};
-
-static const struct of_device_id pcm1792a_of_match[] = {
- { .compatible = "ti,pcm1792a", },
- { }
-};
-MODULE_DEVICE_TABLE(of, pcm1792a_of_match);
-
-static const struct regmap_config pcm1792a_regmap = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = 23,
- .reg_defaults = pcm1792a_reg_defaults,
- .num_reg_defaults = ARRAY_SIZE(pcm1792a_reg_defaults),
- .writeable_reg = pcm1792a_writeable_reg,
- .readable_reg = pcm1792a_accessible_reg,
-};
-
-static struct snd_soc_codec_driver soc_codec_dev_pcm1792a = {
- .controls = pcm1792a_controls,
- .num_controls = ARRAY_SIZE(pcm1792a_controls),
- .dapm_widgets = pcm1792a_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(pcm1792a_dapm_widgets),
- .dapm_routes = pcm1792a_dapm_routes,
- .num_dapm_routes = ARRAY_SIZE(pcm1792a_dapm_routes),
-};
-
-static int pcm1792a_spi_probe(struct spi_device *spi)
-{
- struct pcm1792a_private *pcm1792a;
- int ret;
-
- pcm1792a = devm_kzalloc(&spi->dev, sizeof(struct pcm1792a_private),
- GFP_KERNEL);
- if (!pcm1792a)
- return -ENOMEM;
-
- spi_set_drvdata(spi, pcm1792a);
-
- pcm1792a->regmap = devm_regmap_init_spi(spi, &pcm1792a_regmap);
- if (IS_ERR(pcm1792a->regmap)) {
- ret = PTR_ERR(pcm1792a->regmap);
- dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
- return ret;
- }
-
- return snd_soc_register_codec(&spi->dev,
- &soc_codec_dev_pcm1792a, &pcm1792a_dai, 1);
-}
-
-static int pcm1792a_spi_remove(struct spi_device *spi)
-{
- snd_soc_unregister_codec(&spi->dev);
- return 0;
-}
-
-static const struct spi_device_id pcm1792a_spi_ids[] = {
- { "pcm1792a", 0 },
- { },
-};
-MODULE_DEVICE_TABLE(spi, pcm1792a_spi_ids);
-
-static struct spi_driver pcm1792a_codec_driver = {
- .driver = {
- .name = "pcm1792a",
- .of_match_table = of_match_ptr(pcm1792a_of_match),
- },
- .id_table = pcm1792a_spi_ids,
- .probe = pcm1792a_spi_probe,
- .remove = pcm1792a_spi_remove,
-};
-
-module_spi_driver(pcm1792a_codec_driver);
-
-MODULE_DESCRIPTION("ASoC PCM1792A driver");
-MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm179x.c b/sound/soc/codecs/pcm179x.c
new file mode 100644
index 000000000000..a56c7b767d90
--- /dev/null
+++ b/sound/soc/codecs/pcm179x.c
@@ -0,0 +1,271 @@
+/*
+ * PCM179X ASoC codec driver
+ *
+ * Copyright (c) Amarula Solutions B.V. 2013
+ *
+ * Michael Trimarchi <michael@amarulasolutions.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; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include "pcm179x.h"
+
+#define PCM179X_DAC_VOL_LEFT 0x10
+#define PCM179X_DAC_VOL_RIGHT 0x11
+#define PCM179X_FMT_CONTROL 0x12
+#define PCM179X_MODE_CONTROL 0x13
+#define PCM179X_SOFT_MUTE PCM179X_FMT_CONTROL
+
+#define PCM179X_FMT_MASK 0x70
+#define PCM179X_FMT_SHIFT 4
+#define PCM179X_MUTE_MASK 0x01
+#define PCM179X_MUTE_SHIFT 0
+#define PCM179X_ATLD_ENABLE (1 << 7)
+
+static const struct reg_default pcm179x_reg_defaults[] = {
+ { 0x10, 0xff },
+ { 0x11, 0xff },
+ { 0x12, 0x50 },
+ { 0x13, 0x00 },
+ { 0x14, 0x00 },
+ { 0x15, 0x01 },
+ { 0x16, 0x00 },
+ { 0x17, 0x00 },
+};
+
+static bool pcm179x_accessible_reg(struct device *dev, unsigned int reg)
+{
+ return reg >= 0x10 && reg <= 0x17;
+}
+
+static bool pcm179x_writeable_reg(struct device *dev, unsigned register reg)
+{
+ bool accessible;
+
+ accessible = pcm179x_accessible_reg(dev, reg);
+
+ return accessible && reg != 0x16 && reg != 0x17;
+}
+
+struct pcm179x_private {
+ struct regmap *regmap;
+ unsigned int format;
+ unsigned int rate;
+};
+
+static int pcm179x_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int format)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct pcm179x_private *priv = snd_soc_codec_get_drvdata(codec);
+
+ priv->format = format;
+
+ return 0;
+}
+
+static int pcm179x_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct pcm179x_private *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = regmap_update_bits(priv->regmap, PCM179X_SOFT_MUTE,
+ PCM179X_MUTE_MASK, !!mute);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int pcm179x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct pcm179x_private *priv = snd_soc_codec_get_drvdata(codec);
+ int val = 0, ret;
+
+ priv->rate = params_rate(params);
+
+ switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_RIGHT_J:
+ switch (params_width(params)) {
+ case 24:
+ case 32:
+ val = 2;
+ break;
+ case 16:
+ val = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ switch (params_width(params)) {
+ case 24:
+ case 32:
+ val = 5;
+ break;
+ case 16:
+ val = 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err(codec->dev, "Invalid DAI format\n");
+ return -EINVAL;
+ }
+
+ val = val << PCM179X_FMT_SHIFT | PCM179X_ATLD_ENABLE;
+
+ ret = regmap_update_bits(priv->regmap, PCM179X_FMT_CONTROL,
+ PCM179X_FMT_MASK | PCM179X_ATLD_ENABLE, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops pcm179x_dai_ops = {
+ .set_fmt = pcm179x_set_dai_fmt,
+ .hw_params = pcm179x_hw_params,
+ .digital_mute = pcm179x_digital_mute,
+};
+
+static const DECLARE_TLV_DB_SCALE(pcm179x_dac_tlv, -12000, 50, 1);
+
+static const struct snd_kcontrol_new pcm179x_controls[] = {
+ SOC_DOUBLE_R_RANGE_TLV("DAC Playback Volume", PCM179X_DAC_VOL_LEFT,
+ PCM179X_DAC_VOL_RIGHT, 0, 0xf, 0xff, 0,
+ pcm179x_dac_tlv),
+ SOC_SINGLE("DAC Invert Output Switch", PCM179X_MODE_CONTROL, 7, 1, 0),
+ SOC_SINGLE("DAC Rolloff Filter Switch", PCM179X_MODE_CONTROL, 1, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget pcm179x_dapm_widgets[] = {
+SND_SOC_DAPM_OUTPUT("IOUTL+"),
+SND_SOC_DAPM_OUTPUT("IOUTL-"),
+SND_SOC_DAPM_OUTPUT("IOUTR+"),
+SND_SOC_DAPM_OUTPUT("IOUTR-"),
+};
+
+static const struct snd_soc_dapm_route pcm179x_dapm_routes[] = {
+ { "IOUTL+", NULL, "Playback" },
+ { "IOUTL-", NULL, "Playback" },
+ { "IOUTR+", NULL, "Playback" },
+ { "IOUTR-", NULL, "Playback" },
+};
+
+static struct snd_soc_dai_driver pcm179x_dai = {
+ .name = "pcm179x-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = PCM1792A_RATES,
+ .formats = PCM1792A_FORMATS, },
+ .ops = &pcm179x_dai_ops,
+};
+
+static const struct of_device_id pcm179x_of_match[] = {
+ { .compatible = "ti,pcm1792a", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pcm179x_of_match);
+
+static const struct regmap_config pcm179x_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 23,
+ .reg_defaults = pcm179x_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(pcm179x_reg_defaults),
+ .writeable_reg = pcm179x_writeable_reg,
+ .readable_reg = pcm179x_accessible_reg,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_pcm179x = {
+ .controls = pcm179x_controls,
+ .num_controls = ARRAY_SIZE(pcm179x_controls),
+ .dapm_widgets = pcm179x_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(pcm179x_dapm_widgets),
+ .dapm_routes = pcm179x_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(pcm179x_dapm_routes),
+};
+
+static int pcm179x_spi_probe(struct spi_device *spi)
+{
+ struct pcm179x_private *pcm179x;
+ int ret;
+
+ pcm179x = devm_kzalloc(&spi->dev, sizeof(struct pcm179x_private),
+ GFP_KERNEL);
+ if (!pcm179x)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, pcm179x);
+
+ pcm179x->regmap = devm_regmap_init_spi(spi, &pcm179x_regmap);
+ if (IS_ERR(pcm179x->regmap)) {
+ ret = PTR_ERR(pcm179x->regmap);
+ dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
+ return ret;
+ }
+
+ return snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_pcm179x, &pcm179x_dai, 1);
+}
+
+static int pcm179x_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static const struct spi_device_id pcm179x_spi_ids[] = {
+ { "pcm179x", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, pcm179x_spi_ids);
+
+static struct spi_driver pcm179x_codec_driver = {
+ .driver = {
+ .name = "pcm179x",
+ .of_match_table = of_match_ptr(pcm179x_of_match),
+ },
+ .id_table = pcm179x_spi_ids,
+ .probe = pcm179x_spi_probe,
+ .remove = pcm179x_spi_remove,
+};
+
+module_spi_driver(pcm179x_codec_driver);
+
+MODULE_DESCRIPTION("ASoC PCM179X driver");
+MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm1792a.h b/sound/soc/codecs/pcm179x.h
index 51d5470fee16..c6fdc062a497 100644
--- a/sound/soc/codecs/pcm1792a.h
+++ b/sound/soc/codecs/pcm179x.h
@@ -1,5 +1,5 @@
/*
- * definitions for PCM1792A
+ * definitions for PCM179X
*
* Copyright 2013 Amarula Solutions
*
@@ -14,8 +14,8 @@
* GNU General Public License for more details.
*/
-#ifndef __PCM1792A_H__
-#define __PCM1792A_H__
+#ifndef __PCM179X_H__
+#define __PCM179X_H__
#define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
diff --git a/sound/soc/codecs/pcm3168a-i2c.c b/sound/soc/codecs/pcm3168a-i2c.c
new file mode 100644
index 000000000000..6feb0901dfeb
--- /dev/null
+++ b/sound/soc/codecs/pcm3168a-i2c.c
@@ -0,0 +1,66 @@
+/*
+ * PCM3168A codec i2c driver
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <sound/soc.h>
+
+#include "pcm3168a.h"
+
+static int pcm3168a_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_i2c(i2c, &pcm3168a_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return pcm3168a_probe(&i2c->dev, regmap);
+}
+
+static int pcm3168a_i2c_remove(struct i2c_client *i2c)
+{
+ pcm3168a_remove(&i2c->dev);
+
+ return 0;
+}
+
+static const struct i2c_device_id pcm3168a_i2c_id[] = {
+ { "pcm3168a", },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pcm3168a_i2c_id);
+
+static const struct of_device_id pcm3168a_of_match[] = {
+ { .compatible = "ti,pcm3168a", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pcm3168a_of_match);
+
+static struct i2c_driver pcm3168a_i2c_driver = {
+ .probe = pcm3168a_i2c_probe,
+ .remove = pcm3168a_i2c_remove,
+ .id_table = pcm3168a_i2c_id,
+ .driver = {
+ .name = "pcm3168a",
+ .of_match_table = pcm3168a_of_match,
+ .pm = &pcm3168a_pm_ops,
+ },
+};
+module_i2c_driver(pcm3168a_i2c_driver);
+
+MODULE_DESCRIPTION("PCM3168A I2C codec driver");
+MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3168a-spi.c b/sound/soc/codecs/pcm3168a-spi.c
new file mode 100644
index 000000000000..03945a27ae40
--- /dev/null
+++ b/sound/soc/codecs/pcm3168a-spi.c
@@ -0,0 +1,65 @@
+/*
+ * PCM3168A codec spi driver
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include <sound/soc.h>
+
+#include "pcm3168a.h"
+
+static int pcm3168a_spi_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_spi(spi, &pcm3168a_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return pcm3168a_probe(&spi->dev, regmap);
+}
+
+static int pcm3168a_spi_remove(struct spi_device *spi)
+{
+ pcm3168a_remove(&spi->dev);
+
+ return 0;
+}
+
+static const struct spi_device_id pcm3168a_spi_id[] = {
+ { "pcm3168a", },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, pcm3168a_spi_id);
+
+static const struct of_device_id pcm3168a_of_match[] = {
+ { .compatible = "ti,pcm3168a", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pcm3168a_of_match);
+
+static struct spi_driver pcm3168a_spi_driver = {
+ .probe = pcm3168a_spi_probe,
+ .remove = pcm3168a_spi_remove,
+ .id_table = pcm3168a_spi_id,
+ .driver = {
+ .name = "pcm3168a",
+ .of_match_table = pcm3168a_of_match,
+ .pm = &pcm3168a_pm_ops,
+ },
+};
+module_spi_driver(pcm3168a_spi_driver);
+
+MODULE_DESCRIPTION("PCM3168A SPI codec driver");
+MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c
new file mode 100644
index 000000000000..44b268aa4dd8
--- /dev/null
+++ b/sound/soc/codecs/pcm3168a.c
@@ -0,0 +1,767 @@
+/*
+ * PCM3168A codec driver
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "pcm3168a.h"
+
+#define PCM3168A_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define PCM3168A_FMT_I2S 0x0
+#define PCM3168A_FMT_LEFT_J 0x1
+#define PCM3168A_FMT_RIGHT_J 0x2
+#define PCM3168A_FMT_RIGHT_J_16 0x3
+#define PCM3168A_FMT_DSP_A 0x4
+#define PCM3168A_FMT_DSP_B 0x5
+#define PCM3168A_FMT_DSP_MASK 0x4
+
+#define PCM3168A_NUM_SUPPLIES 6
+static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = {
+ "VDD1",
+ "VDD2",
+ "VCCAD1",
+ "VCCAD2",
+ "VCCDA1",
+ "VCCDA2"
+};
+
+struct pcm3168a_priv {
+ struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES];
+ struct regmap *regmap;
+ struct clk *scki;
+ bool adc_master_mode;
+ bool dac_master_mode;
+ unsigned long sysclk;
+ unsigned int adc_fmt;
+ unsigned int dac_fmt;
+};
+
+static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" };
+
+static SOC_ENUM_SINGLE_DECL(pcm3168a_d1_roll_off, PCM3168A_DAC_OP_FLT,
+ PCM3168A_DAC_FLT_SHIFT, pcm3168a_roll_off);
+static SOC_ENUM_SINGLE_DECL(pcm3168a_d2_roll_off, PCM3168A_DAC_OP_FLT,
+ PCM3168A_DAC_FLT_SHIFT + 1, pcm3168a_roll_off);
+static SOC_ENUM_SINGLE_DECL(pcm3168a_d3_roll_off, PCM3168A_DAC_OP_FLT,
+ PCM3168A_DAC_FLT_SHIFT + 2, pcm3168a_roll_off);
+static SOC_ENUM_SINGLE_DECL(pcm3168a_d4_roll_off, PCM3168A_DAC_OP_FLT,
+ PCM3168A_DAC_FLT_SHIFT + 3, pcm3168a_roll_off);
+
+static const char *const pcm3168a_volume_type[] = {
+ "Individual", "Master + Individual" };
+
+static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_volume_type, PCM3168A_DAC_ATT_DEMP_ZF,
+ PCM3168A_DAC_ATMDDA_SHIFT, pcm3168a_volume_type);
+
+static const char *const pcm3168a_att_speed_mult[] = { "2048", "4096" };
+
+static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_att_mult, PCM3168A_DAC_ATT_DEMP_ZF,
+ PCM3168A_DAC_ATSPDA_SHIFT, pcm3168a_att_speed_mult);
+
+static const char *const pcm3168a_demp[] = {
+ "Disabled", "48khz", "44.1khz", "32khz" };
+
+static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_demp, PCM3168A_DAC_ATT_DEMP_ZF,
+ PCM3168A_DAC_DEMP_SHIFT, pcm3168a_demp);
+
+static const char *const pcm3168a_zf_func[] = {
+ "DAC 1/2/3/4 AND", "DAC 1/2/3/4 OR", "DAC 1/2/3 AND",
+ "DAC 1/2/3 OR", "DAC 4 AND", "DAC 4 OR" };
+
+static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_zf_func, PCM3168A_DAC_ATT_DEMP_ZF,
+ PCM3168A_DAC_AZRO_SHIFT, pcm3168a_zf_func);
+
+static const char *const pcm3168a_pol[] = { "Active High", "Active Low" };
+
+static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_zf_pol, PCM3168A_DAC_ATT_DEMP_ZF,
+ PCM3168A_DAC_ATSPDA_SHIFT, pcm3168a_pol);
+
+static const char *const pcm3168a_con[] = { "Differential", "Single-Ended" };
+
+static SOC_ENUM_DOUBLE_DECL(pcm3168a_adc1_con, PCM3168A_ADC_SEAD,
+ 0, 1, pcm3168a_con);
+static SOC_ENUM_DOUBLE_DECL(pcm3168a_adc2_con, PCM3168A_ADC_SEAD,
+ 2, 3, pcm3168a_con);
+static SOC_ENUM_DOUBLE_DECL(pcm3168a_adc3_con, PCM3168A_ADC_SEAD,
+ 4, 5, pcm3168a_con);
+
+static SOC_ENUM_SINGLE_DECL(pcm3168a_adc_volume_type, PCM3168A_ADC_ATT_OVF,
+ PCM3168A_ADC_ATMDAD_SHIFT, pcm3168a_volume_type);
+
+static SOC_ENUM_SINGLE_DECL(pcm3168a_adc_att_mult, PCM3168A_ADC_ATT_OVF,
+ PCM3168A_ADC_ATSPAD_SHIFT, pcm3168a_att_speed_mult);
+
+static SOC_ENUM_SINGLE_DECL(pcm3168a_adc_ov_pol, PCM3168A_ADC_ATT_OVF,
+ PCM3168A_ADC_OVFP_SHIFT, pcm3168a_pol);
+
+/* -100db to 0db, register values 0-54 cause mute */
+static const DECLARE_TLV_DB_SCALE(pcm3168a_dac_tlv, -10050, 50, 1);
+
+/* -100db to 20db, register values 0-14 cause mute */
+static const DECLARE_TLV_DB_SCALE(pcm3168a_adc_tlv, -10050, 50, 1);
+
+static const struct snd_kcontrol_new pcm3168a_snd_controls[] = {
+ SOC_SINGLE("DAC Power-Save Switch", PCM3168A_DAC_PWR_MST_FMT,
+ PCM3168A_DAC_PSMDA_SHIFT, 1, 1),
+ SOC_ENUM("DAC1 Digital Filter roll-off", pcm3168a_d1_roll_off),
+ SOC_ENUM("DAC2 Digital Filter roll-off", pcm3168a_d2_roll_off),
+ SOC_ENUM("DAC3 Digital Filter roll-off", pcm3168a_d3_roll_off),
+ SOC_ENUM("DAC4 Digital Filter roll-off", pcm3168a_d4_roll_off),
+ SOC_DOUBLE("DAC1 Invert Switch", PCM3168A_DAC_INV, 0, 1, 1, 0),
+ SOC_DOUBLE("DAC2 Invert Switch", PCM3168A_DAC_INV, 2, 3, 1, 0),
+ SOC_DOUBLE("DAC3 Invert Switch", PCM3168A_DAC_INV, 4, 5, 1, 0),
+ SOC_DOUBLE("DAC4 Invert Switch", PCM3168A_DAC_INV, 6, 7, 1, 0),
+ SOC_DOUBLE_STS("DAC1 Zero Flag", PCM3168A_DAC_ZERO, 0, 1, 1, 0),
+ SOC_DOUBLE_STS("DAC2 Zero Flag", PCM3168A_DAC_ZERO, 2, 3, 1, 0),
+ SOC_DOUBLE_STS("DAC3 Zero Flag", PCM3168A_DAC_ZERO, 4, 5, 1, 0),
+ SOC_DOUBLE_STS("DAC4 Zero Flag", PCM3168A_DAC_ZERO, 6, 7, 1, 0),
+ SOC_ENUM("DAC Volume Control Type", pcm3168a_dac_volume_type),
+ SOC_ENUM("DAC Volume Rate Multiplier", pcm3168a_dac_att_mult),
+ SOC_ENUM("DAC De-Emphasis", pcm3168a_dac_demp),
+ SOC_ENUM("DAC Zero Flag Function", pcm3168a_dac_zf_func),
+ SOC_ENUM("DAC Zero Flag Polarity", pcm3168a_dac_zf_pol),
+ SOC_SINGLE_RANGE_TLV("Master Playback Volume",
+ PCM3168A_DAC_VOL_MASTER, 0, 54, 255, 0,
+ pcm3168a_dac_tlv),
+ SOC_DOUBLE_R_RANGE_TLV("DAC1 Playback Volume",
+ PCM3168A_DAC_VOL_CHAN_START,
+ PCM3168A_DAC_VOL_CHAN_START + 1,
+ 0, 54, 255, 0, pcm3168a_dac_tlv),
+ SOC_DOUBLE_R_RANGE_TLV("DAC2 Playback Volume",
+ PCM3168A_DAC_VOL_CHAN_START + 2,
+ PCM3168A_DAC_VOL_CHAN_START + 3,
+ 0, 54, 255, 0, pcm3168a_dac_tlv),
+ SOC_DOUBLE_R_RANGE_TLV("DAC3 Playback Volume",
+ PCM3168A_DAC_VOL_CHAN_START + 4,
+ PCM3168A_DAC_VOL_CHAN_START + 5,
+ 0, 54, 255, 0, pcm3168a_dac_tlv),
+ SOC_DOUBLE_R_RANGE_TLV("DAC4 Playback Volume",
+ PCM3168A_DAC_VOL_CHAN_START + 6,
+ PCM3168A_DAC_VOL_CHAN_START + 7,
+ 0, 54, 255, 0, pcm3168a_dac_tlv),
+ SOC_SINGLE("ADC1 High-Pass Filter Switch", PCM3168A_ADC_PWR_HPFB,
+ PCM3168A_ADC_BYP_SHIFT, 1, 1),
+ SOC_SINGLE("ADC2 High-Pass Filter Switch", PCM3168A_ADC_PWR_HPFB,
+ PCM3168A_ADC_BYP_SHIFT + 1, 1, 1),
+ SOC_SINGLE("ADC3 High-Pass Filter Switch", PCM3168A_ADC_PWR_HPFB,
+ PCM3168A_ADC_BYP_SHIFT + 2, 1, 1),
+ SOC_ENUM("ADC1 Connection Type", pcm3168a_adc1_con),
+ SOC_ENUM("ADC2 Connection Type", pcm3168a_adc2_con),
+ SOC_ENUM("ADC3 Connection Type", pcm3168a_adc3_con),
+ SOC_DOUBLE("ADC1 Invert Switch", PCM3168A_ADC_INV, 0, 1, 1, 0),
+ SOC_DOUBLE("ADC2 Invert Switch", PCM3168A_ADC_INV, 2, 3, 1, 0),
+ SOC_DOUBLE("ADC3 Invert Switch", PCM3168A_ADC_INV, 4, 5, 1, 0),
+ SOC_DOUBLE("ADC1 Mute Switch", PCM3168A_ADC_MUTE, 0, 1, 1, 0),
+ SOC_DOUBLE("ADC2 Mute Switch", PCM3168A_ADC_MUTE, 2, 3, 1, 0),
+ SOC_DOUBLE("ADC3 Mute Switch", PCM3168A_ADC_MUTE, 4, 5, 1, 0),
+ SOC_DOUBLE_STS("ADC1 Overflow Flag", PCM3168A_ADC_OV, 0, 1, 1, 0),
+ SOC_DOUBLE_STS("ADC2 Overflow Flag", PCM3168A_ADC_OV, 2, 3, 1, 0),
+ SOC_DOUBLE_STS("ADC3 Overflow Flag", PCM3168A_ADC_OV, 4, 5, 1, 0),
+ SOC_ENUM("ADC Volume Control Type", pcm3168a_adc_volume_type),
+ SOC_ENUM("ADC Volume Rate Multiplier", pcm3168a_adc_att_mult),
+ SOC_ENUM("ADC Overflow Flag Polarity", pcm3168a_adc_ov_pol),
+ SOC_SINGLE_RANGE_TLV("Master Capture Volume",
+ PCM3168A_ADC_VOL_MASTER, 0, 14, 255, 0,
+ pcm3168a_adc_tlv),
+ SOC_DOUBLE_R_RANGE_TLV("ADC1 Capture Volume",
+ PCM3168A_ADC_VOL_CHAN_START,
+ PCM3168A_ADC_VOL_CHAN_START + 1,
+ 0, 14, 255, 0, pcm3168a_adc_tlv),
+ SOC_DOUBLE_R_RANGE_TLV("ADC2 Capture Volume",
+ PCM3168A_ADC_VOL_CHAN_START + 2,
+ PCM3168A_ADC_VOL_CHAN_START + 3,
+ 0, 14, 255, 0, pcm3168a_adc_tlv),
+ SOC_DOUBLE_R_RANGE_TLV("ADC3 Capture Volume",
+ PCM3168A_ADC_VOL_CHAN_START + 4,
+ PCM3168A_ADC_VOL_CHAN_START + 5,
+ 0, 14, 255, 0, pcm3168a_adc_tlv)
+};
+
+static const struct snd_soc_dapm_widget pcm3168a_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("DAC1", "Playback", PCM3168A_DAC_OP_FLT,
+ PCM3168A_DAC_OPEDA_SHIFT, 1),
+ SND_SOC_DAPM_DAC("DAC2", "Playback", PCM3168A_DAC_OP_FLT,
+ PCM3168A_DAC_OPEDA_SHIFT + 1, 1),
+ SND_SOC_DAPM_DAC("DAC3", "Playback", PCM3168A_DAC_OP_FLT,
+ PCM3168A_DAC_OPEDA_SHIFT + 2, 1),
+ SND_SOC_DAPM_DAC("DAC4", "Playback", PCM3168A_DAC_OP_FLT,
+ PCM3168A_DAC_OPEDA_SHIFT + 3, 1),
+
+ SND_SOC_DAPM_OUTPUT("AOUT1L"),
+ SND_SOC_DAPM_OUTPUT("AOUT1R"),
+ SND_SOC_DAPM_OUTPUT("AOUT2L"),
+ SND_SOC_DAPM_OUTPUT("AOUT2R"),
+ SND_SOC_DAPM_OUTPUT("AOUT3L"),
+ SND_SOC_DAPM_OUTPUT("AOUT3R"),
+ SND_SOC_DAPM_OUTPUT("AOUT4L"),
+ SND_SOC_DAPM_OUTPUT("AOUT4R"),
+
+ SND_SOC_DAPM_ADC("ADC1", "Capture", PCM3168A_ADC_PWR_HPFB,
+ PCM3168A_ADC_PSVAD_SHIFT, 1),
+ SND_SOC_DAPM_ADC("ADC2", "Capture", PCM3168A_ADC_PWR_HPFB,
+ PCM3168A_ADC_PSVAD_SHIFT + 1, 1),
+ SND_SOC_DAPM_ADC("ADC3", "Capture", PCM3168A_ADC_PWR_HPFB,
+ PCM3168A_ADC_PSVAD_SHIFT + 2, 1),
+
+ SND_SOC_DAPM_INPUT("AIN1L"),
+ SND_SOC_DAPM_INPUT("AIN1R"),
+ SND_SOC_DAPM_INPUT("AIN2L"),
+ SND_SOC_DAPM_INPUT("AIN2R"),
+ SND_SOC_DAPM_INPUT("AIN3L"),
+ SND_SOC_DAPM_INPUT("AIN3R")
+};
+
+static const struct snd_soc_dapm_route pcm3168a_dapm_routes[] = {
+ /* Playback */
+ { "AOUT1L", NULL, "DAC1" },
+ { "AOUT1R", NULL, "DAC1" },
+
+ { "AOUT2L", NULL, "DAC2" },
+ { "AOUT2R", NULL, "DAC2" },
+
+ { "AOUT3L", NULL, "DAC3" },
+ { "AOUT3R", NULL, "DAC3" },
+
+ { "AOUT4L", NULL, "DAC4" },
+ { "AOUT4R", NULL, "DAC4" },
+
+ /* Capture */
+ { "ADC1", NULL, "AIN1L" },
+ { "ADC1", NULL, "AIN1R" },
+
+ { "ADC2", NULL, "AIN2L" },
+ { "ADC2", NULL, "AIN2R" },
+
+ { "ADC3", NULL, "AIN3L" },
+ { "ADC3", NULL, "AIN3R" }
+};
+
+static unsigned int pcm3168a_scki_ratios[] = {
+ 768,
+ 512,
+ 384,
+ 256,
+ 192,
+ 128
+};
+
+#define PCM3168A_NUM_SCKI_RATIOS_DAC ARRAY_SIZE(pcm3168a_scki_ratios)
+#define PCM3168A_NUM_SCKI_RATIOS_ADC (ARRAY_SIZE(pcm3168a_scki_ratios) - 2)
+
+#define PCM1368A_MAX_SYSCLK 36864000
+
+static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a)
+{
+ int ret;
+
+ ret = regmap_write(pcm3168a->regmap, PCM3168A_RST_SMODE, 0);
+ if (ret)
+ return ret;
+
+ /* Internal reset is de-asserted after 3846 SCKI cycles */
+ msleep(DIV_ROUND_UP(3846 * 1000, pcm3168a->sysclk));
+
+ return regmap_write(pcm3168a->regmap, PCM3168A_RST_SMODE,
+ PCM3168A_MRST_MASK | PCM3168A_SRST_MASK);
+}
+
+static int pcm3168a_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec);
+
+ regmap_write(pcm3168a->regmap, PCM3168A_DAC_MUTE, mute ? 0xff : 0);
+
+ return 0;
+}
+
+static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(dai->codec);
+
+ if (freq > PCM1368A_MAX_SYSCLK)
+ return -EINVAL;
+
+ pcm3168a->sysclk = freq;
+
+ return 0;
+}
+
+static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai,
+ unsigned int format, bool dac)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec);
+ u32 fmt, reg, mask, shift;
+ bool master_mode;
+
+ switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_LEFT_J:
+ fmt = PCM3168A_FMT_LEFT_J;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ fmt = PCM3168A_FMT_I2S;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ fmt = PCM3168A_FMT_RIGHT_J;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ fmt = PCM3168A_FMT_DSP_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ fmt = PCM3168A_FMT_DSP_B;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported dai format\n");
+ return -EINVAL;
+ }
+
+ switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ master_mode = false;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ master_mode = true;
+ break;
+ default:
+ dev_err(codec->dev, "unsupported master/slave mode\n");
+ return -EINVAL;
+ }
+
+ switch (format & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (dac) {
+ reg = PCM3168A_DAC_PWR_MST_FMT;
+ mask = PCM3168A_DAC_FMT_MASK;
+ shift = PCM3168A_DAC_FMT_SHIFT;
+ pcm3168a->dac_master_mode = master_mode;
+ pcm3168a->dac_fmt = fmt;
+ } else {
+ reg = PCM3168A_ADC_MST_FMT;
+ mask = PCM3168A_ADC_FMTAD_MASK;
+ shift = PCM3168A_ADC_FMTAD_SHIFT;
+ pcm3168a->adc_master_mode = master_mode;
+ pcm3168a->adc_fmt = fmt;
+ }
+
+ regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift);
+
+ return 0;
+}
+
+static int pcm3168a_set_dai_fmt_dac(struct snd_soc_dai *dai,
+ unsigned int format)
+{
+ return pcm3168a_set_dai_fmt(dai, format, true);
+}
+
+static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai,
+ unsigned int format)
+{
+ return pcm3168a_set_dai_fmt(dai, format, false);
+}
+
+static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec);
+ bool tx, master_mode;
+ u32 val, mask, shift, reg;
+ unsigned int rate, channels, fmt, ratio, max_ratio;
+ int i, min_frame_size;
+ snd_pcm_format_t format;
+
+ rate = params_rate(params);
+ format = params_format(params);
+ channels = params_channels(params);
+
+ ratio = pcm3168a->sysclk / rate;
+
+ tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ if (tx) {
+ max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC;
+ reg = PCM3168A_DAC_PWR_MST_FMT;
+ mask = PCM3168A_DAC_MSDA_MASK;
+ shift = PCM3168A_DAC_MSDA_SHIFT;
+ master_mode = pcm3168a->dac_master_mode;
+ fmt = pcm3168a->dac_fmt;
+ } else {
+ max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC;
+ reg = PCM3168A_ADC_MST_FMT;
+ mask = PCM3168A_ADC_MSAD_MASK;
+ shift = PCM3168A_ADC_MSAD_SHIFT;
+ master_mode = pcm3168a->adc_master_mode;
+ fmt = pcm3168a->adc_fmt;
+ }
+
+ for (i = 0; i < max_ratio; i++) {
+ if (pcm3168a_scki_ratios[i] == ratio)
+ break;
+ }
+
+ if (i == max_ratio) {
+ dev_err(codec->dev, "unsupported sysclk ratio\n");
+ return -EINVAL;
+ }
+
+ min_frame_size = params_width(params) * 2;
+ switch (min_frame_size) {
+ case 32:
+ if (master_mode || (fmt != PCM3168A_FMT_RIGHT_J)) {
+ dev_err(codec->dev, "32-bit frames are supported only for slave mode using right justified\n");
+ return -EINVAL;
+ }
+ fmt = PCM3168A_FMT_RIGHT_J_16;
+ break;
+ case 48:
+ if (master_mode || (fmt & PCM3168A_FMT_DSP_MASK)) {
+ dev_err(codec->dev, "48-bit frames not supported in master mode, or slave mode using DSP\n");
+ return -EINVAL;
+ }
+ break;
+ case 64:
+ break;
+ default:
+ dev_err(codec->dev, "unsupported frame size: %d\n", min_frame_size);
+ return -EINVAL;
+ }
+
+ if (master_mode)
+ val = ((i + 1) << shift);
+ else
+ val = 0;
+
+ regmap_update_bits(pcm3168a->regmap, reg, mask, val);
+
+ if (tx) {
+ mask = PCM3168A_DAC_FMT_MASK;
+ shift = PCM3168A_DAC_FMT_SHIFT;
+ } else {
+ mask = PCM3168A_ADC_FMTAD_MASK;
+ shift = PCM3168A_ADC_FMTAD_SHIFT;
+ }
+
+ regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = {
+ .set_fmt = pcm3168a_set_dai_fmt_dac,
+ .set_sysclk = pcm3168a_set_dai_sysclk,
+ .hw_params = pcm3168a_hw_params,
+ .digital_mute = pcm3168a_digital_mute
+};
+
+static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = {
+ .set_fmt = pcm3168a_set_dai_fmt_adc,
+ .set_sysclk = pcm3168a_set_dai_sysclk,
+ .hw_params = pcm3168a_hw_params
+};
+
+static struct snd_soc_dai_driver pcm3168a_dais[] = {
+ {
+ .name = "pcm3168a-dac",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = PCM3168A_FORMATS
+ },
+ .ops = &pcm3168a_dac_dai_ops
+ },
+ {
+ .name = "pcm3168a-adc",
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 6,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = PCM3168A_FORMATS
+ },
+ .ops = &pcm3168a_adc_dai_ops
+ },
+};
+
+static const struct reg_default pcm3168a_reg_default[] = {
+ { PCM3168A_RST_SMODE, PCM3168A_MRST_MASK | PCM3168A_SRST_MASK },
+ { PCM3168A_DAC_PWR_MST_FMT, 0x00 },
+ { PCM3168A_DAC_OP_FLT, 0x00 },
+ { PCM3168A_DAC_INV, 0x00 },
+ { PCM3168A_DAC_MUTE, 0x00 },
+ { PCM3168A_DAC_ZERO, 0x00 },
+ { PCM3168A_DAC_ATT_DEMP_ZF, 0x00 },
+ { PCM3168A_DAC_VOL_MASTER, 0xff },
+ { PCM3168A_DAC_VOL_CHAN_START, 0xff },
+ { PCM3168A_DAC_VOL_CHAN_START + 1, 0xff },
+ { PCM3168A_DAC_VOL_CHAN_START + 2, 0xff },
+ { PCM3168A_DAC_VOL_CHAN_START + 3, 0xff },
+ { PCM3168A_DAC_VOL_CHAN_START + 4, 0xff },
+ { PCM3168A_DAC_VOL_CHAN_START + 5, 0xff },
+ { PCM3168A_DAC_VOL_CHAN_START + 6, 0xff },
+ { PCM3168A_DAC_VOL_CHAN_START + 7, 0xff },
+ { PCM3168A_ADC_SMODE, 0x00 },
+ { PCM3168A_ADC_MST_FMT, 0x00 },
+ { PCM3168A_ADC_PWR_HPFB, 0x00 },
+ { PCM3168A_ADC_SEAD, 0x00 },
+ { PCM3168A_ADC_INV, 0x00 },
+ { PCM3168A_ADC_MUTE, 0x00 },
+ { PCM3168A_ADC_OV, 0x00 },
+ { PCM3168A_ADC_ATT_OVF, 0x00 },
+ { PCM3168A_ADC_VOL_MASTER, 0xd3 },
+ { PCM3168A_ADC_VOL_CHAN_START, 0xd3 },
+ { PCM3168A_ADC_VOL_CHAN_START + 1, 0xd3 },
+ { PCM3168A_ADC_VOL_CHAN_START + 2, 0xd3 },
+ { PCM3168A_ADC_VOL_CHAN_START + 3, 0xd3 },
+ { PCM3168A_ADC_VOL_CHAN_START + 4, 0xd3 },
+ { PCM3168A_ADC_VOL_CHAN_START + 5, 0xd3 }
+};
+
+static bool pcm3168a_readable_register(struct device *dev, unsigned int reg)
+{
+ if (reg >= PCM3168A_RST_SMODE)
+ return true;
+ else
+ return false;
+}
+
+static bool pcm3168a_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case PCM3168A_DAC_ZERO:
+ case PCM3168A_ADC_OV:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool pcm3168a_writeable_register(struct device *dev, unsigned int reg)
+{
+ if (reg < PCM3168A_RST_SMODE)
+ return false;
+
+ switch (reg) {
+ case PCM3168A_DAC_ZERO:
+ case PCM3168A_ADC_OV:
+ return false;
+ default:
+ return true;
+ }
+}
+
+const struct regmap_config pcm3168a_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = PCM3168A_ADC_VOL_CHAN_START + 5,
+ .reg_defaults = pcm3168a_reg_default,
+ .num_reg_defaults = ARRAY_SIZE(pcm3168a_reg_default),
+ .readable_reg = pcm3168a_readable_register,
+ .volatile_reg = pcm3168a_volatile_register,
+ .writeable_reg = pcm3168a_writeable_register,
+ .cache_type = REGCACHE_FLAT
+};
+EXPORT_SYMBOL_GPL(pcm3168a_regmap);
+
+static const struct snd_soc_codec_driver pcm3168a_driver = {
+ .idle_bias_off = true,
+ .controls = pcm3168a_snd_controls,
+ .num_controls = ARRAY_SIZE(pcm3168a_snd_controls),
+ .dapm_widgets = pcm3168a_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(pcm3168a_dapm_widgets),
+ .dapm_routes = pcm3168a_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(pcm3168a_dapm_routes)
+};
+
+int pcm3168a_probe(struct device *dev, struct regmap *regmap)
+{
+ struct pcm3168a_priv *pcm3168a;
+ int ret, i;
+
+ pcm3168a = devm_kzalloc(dev, sizeof(*pcm3168a), GFP_KERNEL);
+ if (pcm3168a == NULL)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, pcm3168a);
+
+ pcm3168a->scki = devm_clk_get(dev, "scki");
+ if (IS_ERR(pcm3168a->scki)) {
+ ret = PTR_ERR(pcm3168a->scki);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to acquire clock 'scki': %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(pcm3168a->scki);
+ if (ret) {
+ dev_err(dev, "Failed to enable mclk: %d\n", ret);
+ return ret;
+ }
+
+ pcm3168a->sysclk = clk_get_rate(pcm3168a->scki);
+
+ for (i = 0; i < ARRAY_SIZE(pcm3168a->supplies); i++)
+ pcm3168a->supplies[i].supply = pcm3168a_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev,
+ ARRAY_SIZE(pcm3168a->supplies), pcm3168a->supplies);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to request supplies: %d\n", ret);
+ goto err_clk;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(pcm3168a->supplies),
+ pcm3168a->supplies);
+ if (ret) {
+ dev_err(dev, "failed to enable supplies: %d\n", ret);
+ goto err_clk;
+ }
+
+ pcm3168a->regmap = regmap;
+ if (IS_ERR(pcm3168a->regmap)) {
+ ret = PTR_ERR(pcm3168a->regmap);
+ dev_err(dev, "failed to allocate regmap: %d\n", ret);
+ goto err_regulator;
+ }
+
+ ret = pcm3168a_reset(pcm3168a);
+ if (ret) {
+ dev_err(dev, "Failed to reset device: %d\n", ret);
+ goto err_regulator;
+ }
+
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_idle(dev);
+
+ ret = snd_soc_register_codec(dev, &pcm3168a_driver, pcm3168a_dais,
+ ARRAY_SIZE(pcm3168a_dais));
+ if (ret) {
+ dev_err(dev, "failed to register codec: %d\n", ret);
+ goto err_regulator;
+ }
+
+ return 0;
+
+err_regulator:
+ regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies),
+ pcm3168a->supplies);
+err_clk:
+ clk_disable_unprepare(pcm3168a->scki);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcm3168a_probe);
+
+void pcm3168a_remove(struct device *dev)
+{
+ struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev);
+
+ snd_soc_unregister_codec(dev);
+ pm_runtime_disable(dev);
+ regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies),
+ pcm3168a->supplies);
+ clk_disable_unprepare(pcm3168a->scki);
+}
+EXPORT_SYMBOL_GPL(pcm3168a_remove);
+
+#ifdef CONFIG_PM
+static int pcm3168a_rt_resume(struct device *dev)
+{
+ struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(pcm3168a->scki);
+ if (ret) {
+ dev_err(dev, "Failed to enable mclk: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(pcm3168a->supplies),
+ pcm3168a->supplies);
+ if (ret) {
+ dev_err(dev, "Failed to enable supplies: %d\n", ret);
+ goto err_clk;
+ }
+
+ ret = pcm3168a_reset(pcm3168a);
+ if (ret) {
+ dev_err(dev, "Failed to reset device: %d\n", ret);
+ goto err_regulator;
+ }
+
+ regcache_cache_only(pcm3168a->regmap, false);
+
+ regcache_mark_dirty(pcm3168a->regmap);
+
+ ret = regcache_sync(pcm3168a->regmap);
+ if (ret) {
+ dev_err(dev, "Failed to sync regmap: %d\n", ret);
+ goto err_regulator;
+ }
+
+ return 0;
+
+err_regulator:
+ regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies),
+ pcm3168a->supplies);
+err_clk:
+ clk_disable_unprepare(pcm3168a->scki);
+
+ return ret;
+}
+
+static int pcm3168a_rt_suspend(struct device *dev)
+{
+ struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev);
+
+ regcache_cache_only(pcm3168a->regmap, true);
+
+ regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies),
+ pcm3168a->supplies);
+
+ clk_disable_unprepare(pcm3168a->scki);
+
+ return 0;
+}
+#endif
+
+const struct dev_pm_ops pcm3168a_pm_ops = {
+ SET_RUNTIME_PM_OPS(pcm3168a_rt_suspend, pcm3168a_rt_resume, NULL)
+};
+EXPORT_SYMBOL_GPL(pcm3168a_pm_ops);
+
+MODULE_DESCRIPTION("PCM3168A codec driver");
+MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3168a.h b/sound/soc/codecs/pcm3168a.h
new file mode 100644
index 000000000000..56c8332d82fb
--- /dev/null
+++ b/sound/soc/codecs/pcm3168a.h
@@ -0,0 +1,100 @@
+/*
+ * PCM3168A codec driver header
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef __PCM3168A_H__
+#define __PCM3168A_H__
+
+extern const struct dev_pm_ops pcm3168a_pm_ops;
+extern const struct regmap_config pcm3168a_regmap;
+
+extern int pcm3168a_probe(struct device *dev, struct regmap *regmap);
+extern void pcm3168a_remove(struct device *dev);
+
+#define PCM3168A_RST_SMODE 0x40
+#define PCM3168A_MRST_MASK 0x80
+#define PCM3168A_SRST_MASK 0x40
+#define PCM3168A_DAC_SRDA_SHIFT 0
+#define PCM3168A_DAC_SRDA_MASK 0x3
+
+#define PCM3168A_DAC_PWR_MST_FMT 0x41
+#define PCM3168A_DAC_PSMDA_SHIFT 7
+#define PCM3168A_DAC_PSMDA_MASK 0x80
+#define PCM3168A_DAC_MSDA_SHIFT 4
+#define PCM3168A_DAC_MSDA_MASK 0x70
+#define PCM3168A_DAC_FMT_SHIFT 0
+#define PCM3168A_DAC_FMT_MASK 0xf
+
+#define PCM3168A_DAC_OP_FLT 0x42
+#define PCM3168A_DAC_OPEDA_SHIFT 4
+#define PCM3168A_DAC_OPEDA_MASK 0xf0
+#define PCM3168A_DAC_FLT_SHIFT 0
+#define PCM3168A_DAC_FLT_MASK 0xf
+
+#define PCM3168A_DAC_INV 0x43
+
+#define PCM3168A_DAC_MUTE 0x44
+
+#define PCM3168A_DAC_ZERO 0x45
+
+#define PCM3168A_DAC_ATT_DEMP_ZF 0x46
+#define PCM3168A_DAC_ATMDDA_MASK 0x80
+#define PCM3168A_DAC_ATMDDA_SHIFT 7
+#define PCM3168A_DAC_ATSPDA_MASK 0x40
+#define PCM3168A_DAC_ATSPDA_SHIFT 6
+#define PCM3168A_DAC_DEMP_SHIFT 4
+#define PCM3168A_DAC_DEMP_MASK 0x30
+#define PCM3168A_DAC_AZRO_SHIFT 1
+#define PCM3168A_DAC_AZRO_MASK 0xe
+#define PCM3168A_DAC_ZREV_MASK 0x1
+#define PCM3168A_DAC_ZREV_SHIFT 0
+
+#define PCM3168A_DAC_VOL_MASTER 0x47
+
+#define PCM3168A_DAC_VOL_CHAN_START 0x48
+
+#define PCM3168A_ADC_SMODE 0x50
+#define PCM3168A_ADC_SRAD_SHIFT 0
+#define PCM3168A_ADC_SRAD_MASK 0x3
+
+#define PCM3168A_ADC_MST_FMT 0x51
+#define PCM3168A_ADC_MSAD_SHIFT 4
+#define PCM3168A_ADC_MSAD_MASK 0x70
+#define PCM3168A_ADC_FMTAD_SHIFT 0
+#define PCM3168A_ADC_FMTAD_MASK 0x7
+
+#define PCM3168A_ADC_PWR_HPFB 0x52
+#define PCM3168A_ADC_PSVAD_SHIFT 4
+#define PCM3168A_ADC_PSVAD_MASK 0x70
+#define PCM3168A_ADC_BYP_SHIFT 0
+#define PCM3168A_ADC_BYP_MASK 0x7
+
+#define PCM3168A_ADC_SEAD 0x53
+
+#define PCM3168A_ADC_INV 0x54
+
+#define PCM3168A_ADC_MUTE 0x55
+
+#define PCM3168A_ADC_OV 0x56
+
+#define PCM3168A_ADC_ATT_OVF 0x57
+#define PCM3168A_ADC_ATMDAD_MASK 0x80
+#define PCM3168A_ADC_ATMDAD_SHIFT 7
+#define PCM3168A_ADC_ATSPAD_MASK 0x40
+#define PCM3168A_ADC_ATSPAD_SHIFT 6
+#define PCM3168A_ADC_OVFP_MASK 0x1
+#define PCM3168A_ADC_OVFP_SHIFT 0
+
+#define PCM3168A_ADC_VOL_MASTER 0x58
+
+#define PCM3168A_ADC_VOL_CHAN_START 0x59
+
+#endif
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index af2ed774b552..bc08f0c5a5f6 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -1114,6 +1114,12 @@ static const struct dmi_system_id force_combo_jack_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "Wilson Beach SDS")
}
},
+ {
+ .ident = "Intel Skylake RVP",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Skylake Client platform")
+ }
+ },
{ }
};
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c
index b3f795c60749..30c6de62ae6c 100644
--- a/sound/soc/codecs/rt298.c
+++ b/sound/soc/codecs/rt298.c
@@ -855,8 +855,6 @@ static int rt298_set_dai_sysclk(struct snd_soc_dai *dai,
snd_soc_update_bits(codec,
RT298_I2S_CTRL2, 0x0100, 0x0100);
snd_soc_update_bits(codec,
- RT298_PLL_CTRL, 0x4, 0x4);
- snd_soc_update_bits(codec,
RT298_PLL_CTRL1, 0x20, 0x0);
}
diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c
new file mode 100644
index 000000000000..1c10d8ed39d2
--- /dev/null
+++ b/sound/soc/codecs/rt5616.c
@@ -0,0 +1,1381 @@
+/*
+ * rt5616.c -- RT5616 ALSA SoC audio codec driver
+ *
+ * Copyright 2015 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "rl6231.h"
+#include "rt5616.h"
+
+#define RT5616_PR_RANGE_BASE (0xff + 1)
+#define RT5616_PR_SPACING 0x100
+
+#define RT5616_PR_BASE (RT5616_PR_RANGE_BASE + (0 * RT5616_PR_SPACING))
+
+static const struct regmap_range_cfg rt5616_ranges[] = {
+ {
+ .name = "PR",
+ .range_min = RT5616_PR_BASE,
+ .range_max = RT5616_PR_BASE + 0xf8,
+ .selector_reg = RT5616_PRIV_INDEX,
+ .selector_mask = 0xff,
+ .selector_shift = 0x0,
+ .window_start = RT5616_PRIV_DATA,
+ .window_len = 0x1,
+ },
+};
+
+static const struct reg_sequence init_list[] = {
+ {RT5616_PR_BASE + 0x3d, 0x3e00},
+ {RT5616_PR_BASE + 0x25, 0x6110},
+ {RT5616_PR_BASE + 0x20, 0x611f},
+ {RT5616_PR_BASE + 0x21, 0x4040},
+ {RT5616_PR_BASE + 0x23, 0x0004},
+};
+#define RT5616_INIT_REG_LEN ARRAY_SIZE(init_list)
+
+static const struct reg_default rt5616_reg[] = {
+ { 0x00, 0x0021 },
+ { 0x02, 0xc8c8 },
+ { 0x03, 0xc8c8 },
+ { 0x05, 0x0000 },
+ { 0x0d, 0x0000 },
+ { 0x0f, 0x0808 },
+ { 0x19, 0xafaf },
+ { 0x1c, 0x2f2f },
+ { 0x1e, 0x0000 },
+ { 0x27, 0x7860 },
+ { 0x29, 0x8080 },
+ { 0x2a, 0x5252 },
+ { 0x3b, 0x0000 },
+ { 0x3c, 0x006f },
+ { 0x3d, 0x0000 },
+ { 0x3e, 0x006f },
+ { 0x45, 0x6000 },
+ { 0x4d, 0x0000 },
+ { 0x4e, 0x0000 },
+ { 0x4f, 0x0279 },
+ { 0x50, 0x0000 },
+ { 0x51, 0x0000 },
+ { 0x52, 0x0279 },
+ { 0x53, 0xf000 },
+ { 0x61, 0x0000 },
+ { 0x62, 0x0000 },
+ { 0x63, 0x00c0 },
+ { 0x64, 0x0000 },
+ { 0x65, 0x0000 },
+ { 0x66, 0x0000 },
+ { 0x70, 0x8000 },
+ { 0x73, 0x1104 },
+ { 0x74, 0x0c00 },
+ { 0x80, 0x0000 },
+ { 0x81, 0x0000 },
+ { 0x82, 0x0000 },
+ { 0x8b, 0x0600 },
+ { 0x8e, 0x0004 },
+ { 0x8f, 0x1100 },
+ { 0x90, 0x0000 },
+ { 0x91, 0x0000 },
+ { 0x92, 0x0000 },
+ { 0x93, 0x2000 },
+ { 0x94, 0x0200 },
+ { 0x95, 0x0000 },
+ { 0xb0, 0x2080 },
+ { 0xb1, 0x0000 },
+ { 0xb2, 0x0000 },
+ { 0xb4, 0x2206 },
+ { 0xb5, 0x1f00 },
+ { 0xb6, 0x0000 },
+ { 0xb7, 0x0000 },
+ { 0xbb, 0x0000 },
+ { 0xbc, 0x0000 },
+ { 0xbd, 0x0000 },
+ { 0xbe, 0x0000 },
+ { 0xbf, 0x0000 },
+ { 0xc0, 0x0100 },
+ { 0xc1, 0x0000 },
+ { 0xc2, 0x0000 },
+ { 0xc8, 0x0000 },
+ { 0xc9, 0x0000 },
+ { 0xca, 0x0000 },
+ { 0xcb, 0x0000 },
+ { 0xcc, 0x0000 },
+ { 0xcd, 0x0000 },
+ { 0xce, 0x0000 },
+ { 0xcf, 0x0013 },
+ { 0xd0, 0x0680 },
+ { 0xd1, 0x1c17 },
+ { 0xd3, 0xb320 },
+ { 0xd4, 0x0000 },
+ { 0xd6, 0x0000 },
+ { 0xd7, 0x0000 },
+ { 0xd9, 0x0809 },
+ { 0xda, 0x0000 },
+ { 0xfa, 0x0010 },
+ { 0xfb, 0x0000 },
+ { 0xfc, 0x0000 },
+ { 0xfe, 0x10ec },
+ { 0xff, 0x6281 },
+};
+
+struct rt5616_priv {
+ struct snd_soc_codec *codec;
+ struct delayed_work patch_work;
+ struct regmap *regmap;
+
+ int sysclk;
+ int sysclk_src;
+ int lrck[RT5616_AIFS];
+ int bclk[RT5616_AIFS];
+ int master[RT5616_AIFS];
+
+ int pll_src;
+ int pll_in;
+ int pll_out;
+
+};
+
+static bool rt5616_volatile_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5616_ranges); i++) {
+ if (reg >= rt5616_ranges[i].range_min &&
+ reg <= rt5616_ranges[i].range_max) {
+ return true;
+ }
+ }
+
+ switch (reg) {
+ case RT5616_RESET:
+ case RT5616_PRIV_DATA:
+ case RT5616_EQ_CTRL1:
+ case RT5616_DRC_AGC_1:
+ case RT5616_IRQ_CTRL2:
+ case RT5616_INT_IRQ_ST:
+ case RT5616_PGM_REG_ARR1:
+ case RT5616_PGM_REG_ARR3:
+ case RT5616_VENDOR_ID:
+ case RT5616_DEVICE_ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rt5616_readable_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5616_ranges); i++) {
+ if (reg >= rt5616_ranges[i].range_min &&
+ reg <= rt5616_ranges[i].range_max) {
+ return true;
+ }
+ }
+
+ switch (reg) {
+ case RT5616_RESET:
+ case RT5616_VERSION_ID:
+ case RT5616_VENDOR_ID:
+ case RT5616_DEVICE_ID:
+ case RT5616_HP_VOL:
+ case RT5616_LOUT_CTRL1:
+ case RT5616_LOUT_CTRL2:
+ case RT5616_IN1_IN2:
+ case RT5616_INL1_INR1_VOL:
+ case RT5616_DAC1_DIG_VOL:
+ case RT5616_ADC_DIG_VOL:
+ case RT5616_ADC_BST_VOL:
+ case RT5616_STO1_ADC_MIXER:
+ case RT5616_AD_DA_MIXER:
+ case RT5616_STO_DAC_MIXER:
+ case RT5616_REC_L1_MIXER:
+ case RT5616_REC_L2_MIXER:
+ case RT5616_REC_R1_MIXER:
+ case RT5616_REC_R2_MIXER:
+ case RT5616_HPO_MIXER:
+ case RT5616_OUT_L1_MIXER:
+ case RT5616_OUT_L2_MIXER:
+ case RT5616_OUT_L3_MIXER:
+ case RT5616_OUT_R1_MIXER:
+ case RT5616_OUT_R2_MIXER:
+ case RT5616_OUT_R3_MIXER:
+ case RT5616_LOUT_MIXER:
+ case RT5616_PWR_DIG1:
+ case RT5616_PWR_DIG2:
+ case RT5616_PWR_ANLG1:
+ case RT5616_PWR_ANLG2:
+ case RT5616_PWR_MIXER:
+ case RT5616_PWR_VOL:
+ case RT5616_PRIV_INDEX:
+ case RT5616_PRIV_DATA:
+ case RT5616_I2S1_SDP:
+ case RT5616_ADDA_CLK1:
+ case RT5616_ADDA_CLK2:
+ case RT5616_GLB_CLK:
+ case RT5616_PLL_CTRL1:
+ case RT5616_PLL_CTRL2:
+ case RT5616_HP_OVCD:
+ case RT5616_DEPOP_M1:
+ case RT5616_DEPOP_M2:
+ case RT5616_DEPOP_M3:
+ case RT5616_CHARGE_PUMP:
+ case RT5616_PV_DET_SPK_G:
+ case RT5616_MICBIAS:
+ case RT5616_A_JD_CTL1:
+ case RT5616_A_JD_CTL2:
+ case RT5616_EQ_CTRL1:
+ case RT5616_EQ_CTRL2:
+ case RT5616_WIND_FILTER:
+ case RT5616_DRC_AGC_1:
+ case RT5616_DRC_AGC_2:
+ case RT5616_DRC_AGC_3:
+ case RT5616_SVOL_ZC:
+ case RT5616_JD_CTRL1:
+ case RT5616_JD_CTRL2:
+ case RT5616_IRQ_CTRL1:
+ case RT5616_IRQ_CTRL2:
+ case RT5616_INT_IRQ_ST:
+ case RT5616_GPIO_CTRL1:
+ case RT5616_GPIO_CTRL2:
+ case RT5616_GPIO_CTRL3:
+ case RT5616_PGM_REG_ARR1:
+ case RT5616_PGM_REG_ARR2:
+ case RT5616_PGM_REG_ARR3:
+ case RT5616_PGM_REG_ARR4:
+ case RT5616_PGM_REG_ARR5:
+ case RT5616_SCB_FUNC:
+ case RT5616_SCB_CTRL:
+ case RT5616_BASE_BACK:
+ case RT5616_MP3_PLUS1:
+ case RT5616_MP3_PLUS2:
+ case RT5616_ADJ_HPF_CTRL1:
+ case RT5616_ADJ_HPF_CTRL2:
+ case RT5616_HP_CALIB_AMP_DET:
+ case RT5616_HP_CALIB2:
+ case RT5616_SV_ZCD1:
+ case RT5616_SV_ZCD2:
+ case RT5616_D_MISC:
+ case RT5616_DUMMY2:
+ case RT5616_DUMMY3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
+
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
+static unsigned int bst_tlv[] = {
+ TLV_DB_RANGE_HEAD(7),
+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+ 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+ 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+static const struct snd_kcontrol_new rt5616_snd_controls[] = {
+ /* Headphone Output Volume */
+ SOC_DOUBLE("HP Playback Switch", RT5616_HP_VOL,
+ RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE_TLV("HP Playback Volume", RT5616_HP_VOL,
+ RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv),
+ /* OUTPUT Control */
+ SOC_DOUBLE("OUT Playback Switch", RT5616_LOUT_CTRL1,
+ RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE("OUT Channel Switch", RT5616_LOUT_CTRL1,
+ RT5616_VOL_L_SFT, RT5616_VOL_R_SFT, 1, 1),
+ SOC_DOUBLE_TLV("OUT Playback Volume", RT5616_LOUT_CTRL1,
+ RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+ /* DAC Digital Volume */
+ SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5616_DAC1_DIG_VOL,
+ RT5616_L_VOL_SFT, RT5616_R_VOL_SFT,
+ 175, 0, dac_vol_tlv),
+ /* IN1/IN2 Control */
+ SOC_SINGLE_TLV("IN1 Boost Volume", RT5616_IN1_IN2,
+ RT5616_BST_SFT1, 8, 0, bst_tlv),
+ SOC_SINGLE_TLV("IN2 Boost Volume", RT5616_IN1_IN2,
+ RT5616_BST_SFT2, 8, 0, bst_tlv),
+ /* INL/INR Volume Control */
+ SOC_DOUBLE_TLV("IN Capture Volume", RT5616_INL1_INR1_VOL,
+ RT5616_INL_VOL_SFT, RT5616_INR_VOL_SFT,
+ 31, 1, in_vol_tlv),
+ /* ADC Digital Volume Control */
+ SOC_DOUBLE("ADC Capture Switch", RT5616_ADC_DIG_VOL,
+ RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE_TLV("ADC Capture Volume", RT5616_ADC_DIG_VOL,
+ RT5616_L_VOL_SFT, RT5616_R_VOL_SFT,
+ 127, 0, adc_vol_tlv),
+
+ /* ADC Boost Volume Control */
+ SOC_DOUBLE_TLV("ADC Boost Volume", RT5616_ADC_BST_VOL,
+ RT5616_ADC_L_BST_SFT, RT5616_ADC_R_BST_SFT,
+ 3, 0, adc_bst_tlv),
+};
+
+static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int val;
+
+ val = snd_soc_read(snd_soc_dapm_to_codec(source->dapm), RT5616_GLB_CLK);
+ val &= RT5616_SCLK_SRC_MASK;
+ if (val == RT5616_SCLK_SRC_PLL1)
+ return 1;
+ else
+ return 0;
+}
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt5616_sto1_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5616_STO1_ADC_MIXER,
+ RT5616_M_STO1_ADC_L1_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5616_sto1_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5616_STO1_ADC_MIXER,
+ RT5616_M_STO1_ADC_R1_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5616_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5616_AD_DA_MIXER,
+ RT5616_M_ADCMIX_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INF1 Switch", RT5616_AD_DA_MIXER,
+ RT5616_M_IF1_DAC_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5616_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5616_AD_DA_MIXER,
+ RT5616_M_ADCMIX_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INF1 Switch", RT5616_AD_DA_MIXER,
+ RT5616_M_IF1_DAC_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5616_sto_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_STO_DAC_MIXER,
+ RT5616_M_DAC_L1_MIXL_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_STO_DAC_MIXER,
+ RT5616_M_DAC_R1_MIXL_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5616_sto_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_STO_DAC_MIXER,
+ RT5616_M_DAC_R1_MIXR_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_STO_DAC_MIXER,
+ RT5616_M_DAC_L1_MIXR_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt5616_rec_l_mix[] = {
+ SOC_DAPM_SINGLE("INL1 Switch", RT5616_REC_L2_MIXER,
+ RT5616_M_IN1_L_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5616_REC_L2_MIXER,
+ RT5616_M_BST2_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5616_REC_L2_MIXER,
+ RT5616_M_BST1_RM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5616_rec_r_mix[] = {
+ SOC_DAPM_SINGLE("INR1 Switch", RT5616_REC_R2_MIXER,
+ RT5616_M_IN1_R_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5616_REC_R2_MIXER,
+ RT5616_M_BST2_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5616_REC_R2_MIXER,
+ RT5616_M_BST1_RM_R_SFT, 1, 1),
+};
+
+/* Analog Output Mixer */
+
+static const struct snd_kcontrol_new rt5616_out_l_mix[] = {
+ SOC_DAPM_SINGLE("BST1 Switch", RT5616_OUT_L3_MIXER,
+ RT5616_M_BST1_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5616_OUT_L3_MIXER,
+ RT5616_M_BST2_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL1 Switch", RT5616_OUT_L3_MIXER,
+ RT5616_M_IN1_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("REC MIXL Switch", RT5616_OUT_L3_MIXER,
+ RT5616_M_RM_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_OUT_L3_MIXER,
+ RT5616_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5616_out_r_mix[] = {
+ SOC_DAPM_SINGLE("BST2 Switch", RT5616_OUT_R3_MIXER,
+ RT5616_M_BST2_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5616_OUT_R3_MIXER,
+ RT5616_M_BST1_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR1 Switch", RT5616_OUT_R3_MIXER,
+ RT5616_M_IN1_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("REC MIXR Switch", RT5616_OUT_R3_MIXER,
+ RT5616_M_RM_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_OUT_R3_MIXER,
+ RT5616_M_DAC_R1_OM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5616_hpo_mix[] = {
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5616_HPO_MIXER,
+ RT5616_M_DAC1_HM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("HPVOL Switch", RT5616_HPO_MIXER,
+ RT5616_M_HPVOL_HM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5616_lout_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5616_LOUT_MIXER,
+ RT5616_M_DAC_L1_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5616_LOUT_MIXER,
+ RT5616_M_DAC_R1_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL L Switch", RT5616_LOUT_MIXER,
+ RT5616_M_OV_L_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL R Switch", RT5616_LOUT_MIXER,
+ RT5616_M_OV_R_LM_SFT, 1, 1),
+};
+
+static int rt5616_adc_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5616_ADC_DIG_VOL,
+ RT5616_L_MUTE | RT5616_R_MUTE, 0);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, RT5616_ADC_DIG_VOL,
+ RT5616_L_MUTE | RT5616_R_MUTE,
+ RT5616_L_MUTE | RT5616_R_MUTE);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5616_charge_pump_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* depop parameters */
+ snd_soc_update_bits(codec, RT5616_DEPOP_M2,
+ RT5616_DEPOP_MASK, RT5616_DEPOP_MAN);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_HP_CP_MASK | RT5616_HP_SG_MASK |
+ RT5616_HP_CB_MASK, RT5616_HP_CP_PU |
+ RT5616_HP_SG_DIS | RT5616_HP_CB_PU);
+ snd_soc_write(codec, RT5616_PR_BASE +
+ RT5616_HP_DCC_INT1, 0x9f00);
+ /* headphone amp power on */
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
+ RT5616_PWR_FV1 | RT5616_PWR_FV2, 0);
+ snd_soc_update_bits(codec, RT5616_PWR_VOL,
+ RT5616_PWR_HV_L | RT5616_PWR_HV_R,
+ RT5616_PWR_HV_L | RT5616_PWR_HV_R);
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
+ RT5616_PWR_HP_L | RT5616_PWR_HP_R |
+ RT5616_PWR_HA, RT5616_PWR_HP_L |
+ RT5616_PWR_HP_R | RT5616_PWR_HA);
+ msleep(50);
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
+ RT5616_PWR_FV1 | RT5616_PWR_FV2,
+ RT5616_PWR_FV1 | RT5616_PWR_FV2);
+
+ snd_soc_update_bits(codec, RT5616_CHARGE_PUMP,
+ RT5616_PM_HP_MASK, RT5616_PM_HP_HV);
+ snd_soc_update_bits(codec, RT5616_PR_BASE +
+ RT5616_CHOP_DAC_ADC, 0x0200, 0x0200);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_HP_CO_MASK | RT5616_HP_SG_MASK,
+ RT5616_HP_CO_EN | RT5616_HP_SG_EN);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5616_PR_BASE +
+ RT5616_CHOP_DAC_ADC, 0x0200, 0x0);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK |
+ RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS |
+ RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS);
+ /* headphone amp power down */
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_SMT_TRIG_MASK | RT5616_HP_CD_PD_MASK |
+ RT5616_HP_CO_MASK | RT5616_HP_CP_MASK |
+ RT5616_HP_SG_MASK | RT5616_HP_CB_MASK,
+ RT5616_SMT_TRIG_DIS | RT5616_HP_CD_PD_EN |
+ RT5616_HP_CO_DIS | RT5616_HP_CP_PD |
+ RT5616_HP_SG_EN | RT5616_HP_CB_PD);
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
+ RT5616_PWR_HP_L | RT5616_PWR_HP_R |
+ RT5616_PWR_HA, 0);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5616_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* headphone unmute sequence */
+ snd_soc_update_bits(codec, RT5616_DEPOP_M3,
+ RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK |
+ RT5616_CP_FQ3_MASK,
+ (RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ1_SFT) |
+ (RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT) |
+ (RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ3_SFT));
+ snd_soc_write(codec, RT5616_PR_BASE +
+ RT5616_MAMP_INT_REG2, 0xfc00);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_SMT_TRIG_MASK, RT5616_SMT_TRIG_EN);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_RSTN_MASK, RT5616_RSTN_EN);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_RSTN_MASK | RT5616_HP_L_SMT_MASK |
+ RT5616_HP_R_SMT_MASK, RT5616_RSTN_DIS |
+ RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN);
+ snd_soc_update_bits(codec, RT5616_HP_VOL,
+ RT5616_L_MUTE | RT5616_R_MUTE, 0);
+ msleep(100);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK |
+ RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS |
+ RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS);
+ msleep(20);
+ snd_soc_update_bits(codec, RT5616_HP_CALIB_AMP_DET,
+ RT5616_HPD_PS_MASK, RT5616_HPD_PS_EN);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ /* headphone mute sequence */
+ snd_soc_update_bits(codec, RT5616_DEPOP_M3,
+ RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK |
+ RT5616_CP_FQ3_MASK,
+ (RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ1_SFT) |
+ (RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT) |
+ (RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ3_SFT));
+ snd_soc_write(codec, RT5616_PR_BASE +
+ RT5616_MAMP_INT_REG2, 0xfc00);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_HP_SG_MASK, RT5616_HP_SG_EN);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_RSTP_MASK, RT5616_RSTP_EN);
+ snd_soc_update_bits(codec, RT5616_DEPOP_M1,
+ RT5616_RSTP_MASK | RT5616_HP_L_SMT_MASK |
+ RT5616_HP_R_SMT_MASK, RT5616_RSTP_DIS |
+ RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN);
+ snd_soc_update_bits(codec, RT5616_HP_CALIB_AMP_DET,
+ RT5616_HPD_PS_MASK, RT5616_HPD_PS_DIS);
+ msleep(90);
+ snd_soc_update_bits(codec, RT5616_HP_VOL,
+ RT5616_L_MUTE | RT5616_R_MUTE,
+ RT5616_L_MUTE | RT5616_R_MUTE);
+ msleep(30);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5616_lout_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
+ RT5616_PWR_LM, RT5616_PWR_LM);
+ snd_soc_update_bits(codec, RT5616_LOUT_CTRL1,
+ RT5616_L_MUTE | RT5616_R_MUTE, 0);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5616_LOUT_CTRL1,
+ RT5616_L_MUTE | RT5616_R_MUTE,
+ RT5616_L_MUTE | RT5616_R_MUTE);
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
+ RT5616_PWR_LM, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5616_bst1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG2,
+ RT5616_PWR_BST1_OP2, RT5616_PWR_BST1_OP2);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG2,
+ RT5616_PWR_BST1_OP2, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int rt5616_bst2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG2,
+ RT5616_PWR_BST2_OP2, RT5616_PWR_BST2_OP2);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG2,
+ RT5616_PWR_BST2_OP2, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget rt5616_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("PLL1", RT5616_PWR_ANLG2,
+ RT5616_PWR_PLL_BIT, 0, NULL, 0),
+ /* Input Side */
+ /* micbias */
+ SND_SOC_DAPM_SUPPLY("LDO", RT5616_PWR_ANLG1,
+ RT5616_PWR_LDO_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("micbias1", RT5616_PWR_ANLG2,
+ RT5616_PWR_MB1_BIT, 0, NULL, 0),
+
+ /* Input Lines */
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_INPUT("MIC2"),
+
+ SND_SOC_DAPM_INPUT("IN1P"),
+ SND_SOC_DAPM_INPUT("IN2P"),
+ SND_SOC_DAPM_INPUT("IN2N"),
+
+ /* Boost */
+ SND_SOC_DAPM_PGA_E("BST1", RT5616_PWR_ANLG2,
+ RT5616_PWR_BST1_BIT, 0, NULL, 0, rt5616_bst1_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("BST2", RT5616_PWR_ANLG2,
+ RT5616_PWR_BST2_BIT, 0, NULL, 0, rt5616_bst2_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ /* Input Volume */
+ SND_SOC_DAPM_PGA("INL1 VOL", RT5616_PWR_VOL,
+ RT5616_PWR_IN1_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR1 VOL", RT5616_PWR_VOL,
+ RT5616_PWR_IN1_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INL2 VOL", RT5616_PWR_VOL,
+ RT5616_PWR_IN2_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR2 VOL", RT5616_PWR_VOL,
+ RT5616_PWR_IN2_R_BIT, 0, NULL, 0),
+
+ /* REC Mixer */
+ SND_SOC_DAPM_MIXER("RECMIXL", RT5616_PWR_MIXER, RT5616_PWR_RM_L_BIT, 0,
+ rt5616_rec_l_mix, ARRAY_SIZE(rt5616_rec_l_mix)),
+ SND_SOC_DAPM_MIXER("RECMIXR", RT5616_PWR_MIXER, RT5616_PWR_RM_R_BIT, 0,
+ rt5616_rec_r_mix, ARRAY_SIZE(rt5616_rec_r_mix)),
+ /* ADCs */
+ SND_SOC_DAPM_ADC_E("ADC L", NULL, RT5616_PWR_DIG1,
+ RT5616_PWR_ADC_L_BIT, 0, rt5616_adc_event,
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_ADC_E("ADC R", NULL, RT5616_PWR_DIG1,
+ RT5616_PWR_ADC_R_BIT, 0, rt5616_adc_event,
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+
+ /* ADC Mixer */
+ SND_SOC_DAPM_SUPPLY("stereo1 filter", RT5616_PWR_DIG2,
+ RT5616_PWR_ADC_STO1_F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5616_sto1_adc_l_mix, ARRAY_SIZE(rt5616_sto1_adc_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5616_sto1_adc_r_mix, ARRAY_SIZE(rt5616_sto1_adc_r_mix)),
+
+ /* Digital Interface */
+ SND_SOC_DAPM_SUPPLY("I2S1", RT5616_PWR_DIG1,
+ RT5616_PWR_I2S1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Digital Interface Select */
+
+ /* Audio Interface */
+ SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ /* Audio DSP */
+ SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Output Side */
+ /* DAC mixer before sound effect */
+ SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5616_dac_l_mix, ARRAY_SIZE(rt5616_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5616_dac_r_mix, ARRAY_SIZE(rt5616_dac_r_mix)),
+
+ SND_SOC_DAPM_SUPPLY("Stero1 DAC Power", RT5616_PWR_DIG2,
+ RT5616_PWR_DAC_STO1_F_BIT, 0, NULL, 0),
+
+ /* DAC Mixer */
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5616_sto_dac_l_mix, ARRAY_SIZE(rt5616_sto_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5616_sto_dac_r_mix, ARRAY_SIZE(rt5616_sto_dac_r_mix)),
+
+ /* DACs */
+ SND_SOC_DAPM_DAC("DAC L1", NULL, RT5616_PWR_DIG1,
+ RT5616_PWR_DAC_L1_BIT, 0),
+ SND_SOC_DAPM_DAC("DAC R1", NULL, RT5616_PWR_DIG1,
+ RT5616_PWR_DAC_R1_BIT, 0),
+ /* OUT Mixer */
+ SND_SOC_DAPM_MIXER("OUT MIXL", RT5616_PWR_MIXER, RT5616_PWR_OM_L_BIT,
+ 0, rt5616_out_l_mix, ARRAY_SIZE(rt5616_out_l_mix)),
+ SND_SOC_DAPM_MIXER("OUT MIXR", RT5616_PWR_MIXER, RT5616_PWR_OM_R_BIT,
+ 0, rt5616_out_r_mix, ARRAY_SIZE(rt5616_out_r_mix)),
+ /* Output Volume */
+ SND_SOC_DAPM_PGA("OUTVOL L", RT5616_PWR_VOL,
+ RT5616_PWR_OV_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("OUTVOL R", RT5616_PWR_VOL,
+ RT5616_PWR_OV_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HPOVOL L", RT5616_PWR_VOL,
+ RT5616_PWR_HV_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HPOVOL R", RT5616_PWR_VOL,
+ RT5616_PWR_HV_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DAC 2", SND_SOC_NOPM,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HPOVOL", SND_SOC_NOPM,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INL1", RT5616_PWR_VOL,
+ RT5616_PWR_IN1_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR1", RT5616_PWR_VOL,
+ RT5616_PWR_IN1_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INL2", RT5616_PWR_VOL,
+ RT5616_PWR_IN2_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR2", RT5616_PWR_VOL,
+ RT5616_PWR_IN2_R_BIT, 0, NULL, 0),
+ /* HPO/LOUT/Mono Mixer */
+ SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0,
+ rt5616_hpo_mix, ARRAY_SIZE(rt5616_hpo_mix)),
+ SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0,
+ rt5616_lout_mix, ARRAY_SIZE(rt5616_lout_mix)),
+
+ SND_SOC_DAPM_PGA_S("HP amp", 1, SND_SOC_NOPM, 0, 0,
+ rt5616_hp_event, SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_S("LOUT amp", 1, SND_SOC_NOPM, 0, 0,
+ rt5616_lout_event, SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_SUPPLY_S("Charge Pump", 1, SND_SOC_NOPM, 0, 0,
+ rt5616_charge_pump_event, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+
+ /* Output Lines */
+ SND_SOC_DAPM_OUTPUT("HPOL"),
+ SND_SOC_DAPM_OUTPUT("HPOR"),
+ SND_SOC_DAPM_OUTPUT("LOUTL"),
+ SND_SOC_DAPM_OUTPUT("LOUTR"),
+};
+
+static const struct snd_soc_dapm_route rt5616_dapm_routes[] = {
+ {"IN1P", NULL, "LDO"},
+ {"IN2P", NULL, "LDO"},
+
+ {"IN1P", NULL, "MIC1"},
+ {"IN2P", NULL, "MIC2"},
+ {"IN2N", NULL, "MIC2"},
+
+ {"BST1", NULL, "IN1P"},
+ {"BST2", NULL, "IN2P"},
+ {"BST2", NULL, "IN2N"},
+ {"BST1", NULL, "micbias1"},
+ {"BST2", NULL, "micbias1"},
+
+ {"INL1 VOL", NULL, "IN2P"},
+ {"INR1 VOL", NULL, "IN2N"},
+
+ {"RECMIXL", "INL1 Switch", "INL1 VOL"},
+ {"RECMIXL", "BST2 Switch", "BST2"},
+ {"RECMIXL", "BST1 Switch", "BST1"},
+
+ {"RECMIXR", "INR1 Switch", "INR1 VOL"},
+ {"RECMIXR", "BST2 Switch", "BST2"},
+ {"RECMIXR", "BST1 Switch", "BST1"},
+
+ {"ADC L", NULL, "RECMIXL"},
+ {"ADC R", NULL, "RECMIXR"},
+
+ {"Stereo1 ADC MIXL", "ADC1 Switch", "ADC L"},
+ {"Stereo1 ADC MIXL", NULL, "stereo1 filter"},
+ {"stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll},
+
+ {"Stereo1 ADC MIXR", "ADC1 Switch", "ADC R"},
+ {"Stereo1 ADC MIXR", NULL, "stereo1 filter"},
+ {"stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll},
+
+ {"IF1 ADC1", NULL, "Stereo1 ADC MIXL"},
+ {"IF1 ADC1", NULL, "Stereo1 ADC MIXR"},
+ {"IF1 ADC1", NULL, "I2S1"},
+
+ {"AIF1TX", NULL, "IF1 ADC1"},
+
+ {"IF1 DAC", NULL, "AIF1RX"},
+ {"IF1 DAC", NULL, "I2S1"},
+
+ {"IF1 DAC1 L", NULL, "IF1 DAC"},
+ {"IF1 DAC1 R", NULL, "IF1 DAC"},
+
+ {"DAC MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL"},
+ {"DAC MIXL", "INF1 Switch", "IF1 DAC1 L"},
+ {"DAC MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR"},
+ {"DAC MIXR", "INF1 Switch", "IF1 DAC1 R"},
+
+ {"Audio DSP", NULL, "DAC MIXL"},
+ {"Audio DSP", NULL, "DAC MIXR"},
+
+ {"Stereo DAC MIXL", "DAC L1 Switch", "Audio DSP"},
+ {"Stereo DAC MIXL", "DAC R1 Switch", "DAC MIXR"},
+ {"Stereo DAC MIXL", NULL, "Stero1 DAC Power"},
+ {"Stereo DAC MIXR", "DAC R1 Switch", "Audio DSP"},
+ {"Stereo DAC MIXR", "DAC L1 Switch", "DAC MIXL"},
+ {"Stereo DAC MIXR", NULL, "Stero1 DAC Power"},
+
+ {"DAC L1", NULL, "Stereo DAC MIXL"},
+ {"DAC L1", NULL, "PLL1", is_sys_clk_from_pll},
+ {"DAC R1", NULL, "Stereo DAC MIXR"},
+ {"DAC R1", NULL, "PLL1", is_sys_clk_from_pll},
+
+ {"OUT MIXL", "BST1 Switch", "BST1"},
+ {"OUT MIXL", "BST2 Switch", "BST2"},
+ {"OUT MIXL", "INL1 Switch", "INL1 VOL"},
+ {"OUT MIXL", "REC MIXL Switch", "RECMIXL"},
+ {"OUT MIXL", "DAC L1 Switch", "DAC L1"},
+
+ {"OUT MIXR", "BST2 Switch", "BST2"},
+ {"OUT MIXR", "BST1 Switch", "BST1"},
+ {"OUT MIXR", "INR1 Switch", "INR1 VOL"},
+ {"OUT MIXR", "REC MIXR Switch", "RECMIXR"},
+ {"OUT MIXR", "DAC R1 Switch", "DAC R1"},
+
+ {"HPOVOL L", NULL, "OUT MIXL"},
+ {"HPOVOL R", NULL, "OUT MIXR"},
+ {"OUTVOL L", NULL, "OUT MIXL"},
+ {"OUTVOL R", NULL, "OUT MIXR"},
+
+ {"DAC 1", NULL, "DAC L1"},
+ {"DAC 1", NULL, "DAC R1"},
+ {"HPOVOL", NULL, "HPOVOL L"},
+ {"HPOVOL", NULL, "HPOVOL R"},
+ {"HPO MIX", "DAC1 Switch", "DAC 1"},
+ {"HPO MIX", "HPVOL Switch", "HPOVOL"},
+
+ {"LOUT MIX", "DAC L1 Switch", "DAC L1"},
+ {"LOUT MIX", "DAC R1 Switch", "DAC R1"},
+ {"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"},
+ {"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"},
+
+ {"HP amp", NULL, "HPO MIX"},
+ {"HP amp", NULL, "Charge Pump"},
+ {"HPOL", NULL, "HP amp"},
+ {"HPOR", NULL, "HP amp"},
+
+ {"LOUT amp", NULL, "LOUT MIX"},
+ {"LOUT amp", NULL, "Charge Pump"},
+ {"LOUTL", NULL, "LOUT amp"},
+ {"LOUTR", NULL, "LOUT amp"},
+
+};
+
+static int rt5616_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
+ unsigned int val_len = 0, val_clk, mask_clk;
+ int pre_div, bclk_ms, frame_size;
+
+ rt5616->lrck[dai->id] = params_rate(params);
+
+ pre_div = rl6231_get_clk_info(rt5616->sysclk, rt5616->lrck[dai->id]);
+
+ if (pre_div < 0) {
+ dev_err(codec->dev, "Unsupported clock setting\n");
+ return -EINVAL;
+ }
+ frame_size = snd_soc_params_to_frame_size(params);
+ if (frame_size < 0) {
+ dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
+ return -EINVAL;
+ }
+ bclk_ms = frame_size > 32 ? 1 : 0;
+ rt5616->bclk[dai->id] = rt5616->lrck[dai->id] * (32 << bclk_ms);
+
+ dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
+ rt5616->bclk[dai->id], rt5616->lrck[dai->id]);
+ dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
+ bclk_ms, pre_div, dai->id);
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ val_len |= RT5616_I2S_DL_20;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val_len |= RT5616_I2S_DL_24;
+ break;
+ case SNDRV_PCM_FORMAT_S8:
+ val_len |= RT5616_I2S_DL_8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mask_clk = RT5616_I2S_PD1_MASK;
+ val_clk = pre_div << RT5616_I2S_PD1_SFT;
+ snd_soc_update_bits(codec, RT5616_I2S1_SDP,
+ RT5616_I2S_DL_MASK, val_len);
+ snd_soc_update_bits(codec, RT5616_ADDA_CLK1, mask_clk, val_clk);
+
+
+ return 0;
+}
+
+static int rt5616_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ rt5616->master[dai->id] = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ reg_val |= RT5616_I2S_MS_S;
+ rt5616->master[dai->id] = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ reg_val |= RT5616_I2S_BP_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ reg_val |= RT5616_I2S_DF_LEFT;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ reg_val |= RT5616_I2S_DF_PCM_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ reg_val |= RT5616_I2S_DF_PCM_B;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, RT5616_I2S1_SDP,
+ RT5616_I2S_MS_MASK | RT5616_I2S_BP_MASK |
+ RT5616_I2S_DF_MASK, reg_val);
+
+
+ return 0;
+}
+
+static int rt5616_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ if (freq == rt5616->sysclk && clk_id == rt5616->sysclk_src)
+ return 0;
+
+ switch (clk_id) {
+ case RT5616_SCLK_S_MCLK:
+ reg_val |= RT5616_SCLK_SRC_MCLK;
+ break;
+ case RT5616_SCLK_S_PLL1:
+ reg_val |= RT5616_SCLK_SRC_PLL1;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, RT5616_GLB_CLK,
+ RT5616_SCLK_SRC_MASK, reg_val);
+ rt5616->sysclk = freq;
+ rt5616->sysclk_src = clk_id;
+
+ dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
+
+ return 0;
+}
+
+static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
+ unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
+ struct rl6231_pll_code pll_code;
+ int ret;
+
+ if (source == rt5616->pll_src && freq_in == rt5616->pll_in &&
+ freq_out == rt5616->pll_out)
+ return 0;
+
+ if (!freq_in || !freq_out) {
+ dev_dbg(codec->dev, "PLL disabled\n");
+
+ rt5616->pll_in = 0;
+ rt5616->pll_out = 0;
+ snd_soc_update_bits(codec, RT5616_GLB_CLK,
+ RT5616_SCLK_SRC_MASK, RT5616_SCLK_SRC_MCLK);
+ return 0;
+ }
+
+ switch (source) {
+ case RT5616_PLL1_S_MCLK:
+ snd_soc_update_bits(codec, RT5616_GLB_CLK,
+ RT5616_PLL1_SRC_MASK, RT5616_PLL1_SRC_MCLK);
+ break;
+ case RT5616_PLL1_S_BCLK1:
+ case RT5616_PLL1_S_BCLK2:
+ snd_soc_update_bits(codec, RT5616_GLB_CLK,
+ RT5616_PLL1_SRC_MASK, RT5616_PLL1_SRC_BCLK1);
+ break;
+ default:
+ dev_err(codec->dev, "Unknown PLL source %d\n", source);
+ return -EINVAL;
+ }
+
+ ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
+ if (ret < 0) {
+ dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
+ return ret;
+ }
+
+ dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
+ pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+ pll_code.n_code, pll_code.k_code);
+
+ snd_soc_write(codec, RT5616_PLL_CTRL1,
+ pll_code.n_code << RT5616_PLL_N_SFT | pll_code.k_code);
+ snd_soc_write(codec, RT5616_PLL_CTRL2,
+ (pll_code.m_bp ? 0 : pll_code.m_code) << RT5616_PLL_M_SFT |
+ pll_code.m_bp << RT5616_PLL_M_BP_SFT);
+
+ rt5616->pll_in = freq_in;
+ rt5616->pll_out = freq_out;
+ rt5616->pll_src = source;
+
+ return 0;
+}
+
+static int rt5616_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_STANDBY:
+ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
+ RT5616_PWR_VREF1 | RT5616_PWR_MB |
+ RT5616_PWR_BG | RT5616_PWR_VREF2,
+ RT5616_PWR_VREF1 | RT5616_PWR_MB |
+ RT5616_PWR_BG | RT5616_PWR_VREF2);
+ mdelay(10);
+ snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
+ RT5616_PWR_FV1 | RT5616_PWR_FV2,
+ RT5616_PWR_FV1 | RT5616_PWR_FV2);
+ snd_soc_update_bits(codec, RT5616_D_MISC,
+ RT5616_D_GATE_EN, RT5616_D_GATE_EN);
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, RT5616_D_MISC, RT5616_D_GATE_EN, 0);
+ snd_soc_write(codec, RT5616_PWR_DIG1, 0x0000);
+ snd_soc_write(codec, RT5616_PWR_DIG2, 0x0000);
+ snd_soc_write(codec, RT5616_PWR_VOL, 0x0000);
+ snd_soc_write(codec, RT5616_PWR_MIXER, 0x0000);
+ snd_soc_write(codec, RT5616_PWR_ANLG1, 0x0000);
+ snd_soc_write(codec, RT5616_PWR_ANLG2, 0x0000);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int rt5616_probe(struct snd_soc_codec *codec)
+{
+ struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
+
+ rt5616->codec = codec;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5616_suspend(struct snd_soc_codec *codec)
+{
+ struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5616->regmap, true);
+ regcache_mark_dirty(rt5616->regmap);
+
+ return 0;
+}
+
+static int rt5616_resume(struct snd_soc_codec *codec)
+{
+ struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5616->regmap, false);
+ regcache_sync(rt5616->regmap);
+ return 0;
+}
+#else
+#define rt5616_suspend NULL
+#define rt5616_resume NULL
+#endif
+
+#define RT5616_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5616_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+
+struct snd_soc_dai_ops rt5616_aif_dai_ops = {
+ .hw_params = rt5616_hw_params,
+ .set_fmt = rt5616_set_dai_fmt,
+ .set_sysclk = rt5616_set_dai_sysclk,
+ .set_pll = rt5616_set_dai_pll,
+};
+
+struct snd_soc_dai_driver rt5616_dai[] = {
+ {
+ .name = "rt5616-aif1",
+ .id = RT5616_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5616_STEREO_RATES,
+ .formats = RT5616_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5616_STEREO_RATES,
+ .formats = RT5616_FORMATS,
+ },
+ .ops = &rt5616_aif_dai_ops,
+ },
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5616 = {
+ .probe = rt5616_probe,
+ .suspend = rt5616_suspend,
+ .resume = rt5616_resume,
+ .set_bias_level = rt5616_set_bias_level,
+ .idle_bias_off = true,
+ .controls = rt5616_snd_controls,
+ .num_controls = ARRAY_SIZE(rt5616_snd_controls),
+ .dapm_widgets = rt5616_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt5616_dapm_widgets),
+ .dapm_routes = rt5616_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(rt5616_dapm_routes),
+};
+
+static const struct regmap_config rt5616_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .use_single_rw = true,
+ .max_register = RT5616_DEVICE_ID + 1 + (ARRAY_SIZE(rt5616_ranges) *
+ RT5616_PR_SPACING),
+ .volatile_reg = rt5616_volatile_register,
+ .readable_reg = rt5616_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5616_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt5616_reg),
+ .ranges = rt5616_ranges,
+ .num_ranges = ARRAY_SIZE(rt5616_ranges),
+};
+
+static const struct i2c_device_id rt5616_i2c_id[] = {
+ { "rt5616", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rt5616_i2c_id);
+
+#if defined(CONFIG_OF)
+static const struct of_device_id rt5616_of_match[] = {
+ { .compatible = "realtek,rt5616", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rt5616_of_match);
+#endif
+
+static int rt5616_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt5616_priv *rt5616;
+ unsigned int val;
+ int ret;
+
+ rt5616 = devm_kzalloc(&i2c->dev, sizeof(struct rt5616_priv),
+ GFP_KERNEL);
+ if (rt5616 == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, rt5616);
+
+ rt5616->regmap = devm_regmap_init_i2c(i2c, &rt5616_regmap);
+ if (IS_ERR(rt5616->regmap)) {
+ ret = PTR_ERR(rt5616->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ regmap_read(rt5616->regmap, RT5616_DEVICE_ID, &val);
+ if (val != 0x6281) {
+ dev_err(&i2c->dev,
+ "Device with ID register %#x is not rt5616\n",
+ val);
+ return -ENODEV;
+ }
+ regmap_write(rt5616->regmap, RT5616_RESET, 0);
+ regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1,
+ RT5616_PWR_VREF1 | RT5616_PWR_MB |
+ RT5616_PWR_BG | RT5616_PWR_VREF2,
+ RT5616_PWR_VREF1 | RT5616_PWR_MB |
+ RT5616_PWR_BG | RT5616_PWR_VREF2);
+ mdelay(10);
+ regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1,
+ RT5616_PWR_FV1 | RT5616_PWR_FV2,
+ RT5616_PWR_FV1 | RT5616_PWR_FV2);
+
+ ret = regmap_register_patch(rt5616->regmap, init_list,
+ ARRAY_SIZE(init_list));
+ if (ret != 0)
+ dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
+
+ regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1,
+ RT5616_PWR_LDO_DVO_MASK, RT5616_PWR_LDO_DVO_1_2V);
+
+ return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5616,
+ rt5616_dai, ARRAY_SIZE(rt5616_dai));
+
+}
+
+static int rt5616_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+
+ return 0;
+}
+
+static void rt5616_i2c_shutdown(struct i2c_client *client)
+{
+ struct rt5616_priv *rt5616 = i2c_get_clientdata(client);
+
+ regmap_write(rt5616->regmap, RT5616_HP_VOL, 0xc8c8);
+ regmap_write(rt5616->regmap, RT5616_LOUT_CTRL1, 0xc8c8);
+
+}
+
+static struct i2c_driver rt5616_i2c_driver = {
+ .driver = {
+ .name = "rt5616",
+ .of_match_table = of_match_ptr(rt5616_of_match),
+ },
+ .probe = rt5616_i2c_probe,
+ .remove = rt5616_i2c_remove,
+ .shutdown = rt5616_i2c_shutdown,
+ .id_table = rt5616_i2c_id,
+};
+module_i2c_driver(rt5616_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT5616 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt5616.h b/sound/soc/codecs/rt5616.h
new file mode 100644
index 000000000000..f88cdddbc34a
--- /dev/null
+++ b/sound/soc/codecs/rt5616.h
@@ -0,0 +1,1819 @@
+/*
+ * rt5616.h -- RT5616 ALSA SoC audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ * Author: Johnny Hsu <johnnyhsu@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __RT5616_H__
+#define __RT5616_H__
+
+/* Info */
+#define RT5616_RESET 0x00
+#define RT5616_VERSION_ID 0xfd
+#define RT5616_VENDOR_ID 0xfe
+#define RT5616_DEVICE_ID 0xff
+/* I/O - Output */
+#define RT5616_HP_VOL 0x02
+#define RT5616_LOUT_CTRL1 0x03
+#define RT5616_LOUT_CTRL2 0x05
+/* I/O - Input */
+#define RT5616_IN1_IN2 0x0d
+#define RT5616_INL1_INR1_VOL 0x0f
+/* I/O - ADC/DAC/DMIC */
+#define RT5616_DAC1_DIG_VOL 0x19
+#define RT5616_ADC_DIG_VOL 0x1c
+#define RT5616_ADC_BST_VOL 0x1e
+/* Mixer - D-D */
+#define RT5616_STO1_ADC_MIXER 0x27
+#define RT5616_AD_DA_MIXER 0x29
+#define RT5616_STO_DAC_MIXER 0x2a
+
+/* Mixer - ADC */
+#define RT5616_REC_L1_MIXER 0x3b
+#define RT5616_REC_L2_MIXER 0x3c
+#define RT5616_REC_R1_MIXER 0x3d
+#define RT5616_REC_R2_MIXER 0x3e
+/* Mixer - DAC */
+#define RT5616_HPO_MIXER 0x45
+#define RT5616_OUT_L1_MIXER 0x4d
+#define RT5616_OUT_L2_MIXER 0x4e
+#define RT5616_OUT_L3_MIXER 0x4f
+#define RT5616_OUT_R1_MIXER 0x50
+#define RT5616_OUT_R2_MIXER 0x51
+#define RT5616_OUT_R3_MIXER 0x52
+#define RT5616_LOUT_MIXER 0x53
+/* Power */
+#define RT5616_PWR_DIG1 0x61
+#define RT5616_PWR_DIG2 0x62
+#define RT5616_PWR_ANLG1 0x63
+#define RT5616_PWR_ANLG2 0x64
+#define RT5616_PWR_MIXER 0x65
+#define RT5616_PWR_VOL 0x66
+/* Private Register Control */
+#define RT5616_PRIV_INDEX 0x6a
+#define RT5616_PRIV_DATA 0x6c
+/* Format - ADC/DAC */
+#define RT5616_I2S1_SDP 0x70
+#define RT5616_ADDA_CLK1 0x73
+#define RT5616_ADDA_CLK2 0x74
+
+/* Function - Analog */
+#define RT5616_GLB_CLK 0x80
+#define RT5616_PLL_CTRL1 0x81
+#define RT5616_PLL_CTRL2 0x82
+#define RT5616_HP_OVCD 0x8b
+#define RT5616_DEPOP_M1 0x8e
+#define RT5616_DEPOP_M2 0x8f
+#define RT5616_DEPOP_M3 0x90
+#define RT5616_CHARGE_PUMP 0x91
+#define RT5616_PV_DET_SPK_G 0x92
+#define RT5616_MICBIAS 0x93
+#define RT5616_A_JD_CTL1 0x94
+#define RT5616_A_JD_CTL2 0x95
+/* Function - Digital */
+#define RT5616_EQ_CTRL1 0xb0
+#define RT5616_EQ_CTRL2 0xb1
+#define RT5616_WIND_FILTER 0xb2
+#define RT5616_DRC_AGC_1 0xb4
+#define RT5616_DRC_AGC_2 0xb5
+#define RT5616_DRC_AGC_3 0xb6
+#define RT5616_SVOL_ZC 0xb7
+#define RT5616_JD_CTRL1 0xbb
+#define RT5616_JD_CTRL2 0xbc
+#define RT5616_IRQ_CTRL1 0xbd
+#define RT5616_IRQ_CTRL2 0xbe
+#define RT5616_INT_IRQ_ST 0xbf
+#define RT5616_GPIO_CTRL1 0xc0
+#define RT5616_GPIO_CTRL2 0xc1
+#define RT5616_GPIO_CTRL3 0xc2
+#define RT5616_PGM_REG_ARR1 0xc8
+#define RT5616_PGM_REG_ARR2 0xc9
+#define RT5616_PGM_REG_ARR3 0xca
+#define RT5616_PGM_REG_ARR4 0xcb
+#define RT5616_PGM_REG_ARR5 0xcc
+#define RT5616_SCB_FUNC 0xcd
+#define RT5616_SCB_CTRL 0xce
+#define RT5616_BASE_BACK 0xcf
+#define RT5616_MP3_PLUS1 0xd0
+#define RT5616_MP3_PLUS2 0xd1
+#define RT5616_ADJ_HPF_CTRL1 0xd3
+#define RT5616_ADJ_HPF_CTRL2 0xd4
+#define RT5616_HP_CALIB_AMP_DET 0xd6
+#define RT5616_HP_CALIB2 0xd7
+#define RT5616_SV_ZCD1 0xd9
+#define RT5616_SV_ZCD2 0xda
+#define RT5616_D_MISC 0xfa
+/* Dummy Register */
+#define RT5616_DUMMY2 0xfb
+#define RT5616_DUMMY3 0xfc
+
+
+/* Index of Codec Private Register definition */
+#define RT5616_BIAS_CUR1 0x12
+#define RT5616_BIAS_CUR3 0x14
+#define RT5616_CLSD_INT_REG1 0x1c
+#define RT5616_MAMP_INT_REG2 0x37
+#define RT5616_CHOP_DAC_ADC 0x3d
+#define RT5616_3D_SPK 0x63
+#define RT5616_WND_1 0x6c
+#define RT5616_WND_2 0x6d
+#define RT5616_WND_3 0x6e
+#define RT5616_WND_4 0x6f
+#define RT5616_WND_5 0x70
+#define RT5616_WND_8 0x73
+#define RT5616_DIP_SPK_INF 0x75
+#define RT5616_HP_DCC_INT1 0x77
+#define RT5616_EQ_BW_LOP 0xa0
+#define RT5616_EQ_GN_LOP 0xa1
+#define RT5616_EQ_FC_BP1 0xa2
+#define RT5616_EQ_BW_BP1 0xa3
+#define RT5616_EQ_GN_BP1 0xa4
+#define RT5616_EQ_FC_BP2 0xa5
+#define RT5616_EQ_BW_BP2 0xa6
+#define RT5616_EQ_GN_BP2 0xa7
+#define RT5616_EQ_FC_BP3 0xa8
+#define RT5616_EQ_BW_BP3 0xa9
+#define RT5616_EQ_GN_BP3 0xaa
+#define RT5616_EQ_FC_BP4 0xab
+#define RT5616_EQ_BW_BP4 0xac
+#define RT5616_EQ_GN_BP4 0xad
+#define RT5616_EQ_FC_HIP1 0xae
+#define RT5616_EQ_GN_HIP1 0xaf
+#define RT5616_EQ_FC_HIP2 0xb0
+#define RT5616_EQ_BW_HIP2 0xb1
+#define RT5616_EQ_GN_HIP2 0xb2
+#define RT5616_EQ_PRE_VOL 0xb3
+#define RT5616_EQ_PST_VOL 0xb4
+
+
+/* global definition */
+#define RT5616_L_MUTE (0x1 << 15)
+#define RT5616_L_MUTE_SFT 15
+#define RT5616_VOL_L_MUTE (0x1 << 14)
+#define RT5616_VOL_L_SFT 14
+#define RT5616_R_MUTE (0x1 << 7)
+#define RT5616_R_MUTE_SFT 7
+#define RT5616_VOL_R_MUTE (0x1 << 6)
+#define RT5616_VOL_R_SFT 6
+#define RT5616_L_VOL_MASK (0x3f << 8)
+#define RT5616_L_VOL_SFT 8
+#define RT5616_R_VOL_MASK (0x3f)
+#define RT5616_R_VOL_SFT 0
+
+/* LOUT Control 2(0x05) */
+#define RT5616_EN_DFO (0x1 << 15)
+
+/* IN1 and IN2 Control (0x0d) */
+/* IN3 and IN4 Control (0x0e) */
+#define RT5616_BST_MASK1 (0xf<<12)
+#define RT5616_BST_SFT1 12
+#define RT5616_BST_MASK2 (0xf<<8)
+#define RT5616_BST_SFT2 8
+#define RT5616_IN_DF1 (0x1 << 7)
+#define RT5616_IN_SFT1 7
+#define RT5616_IN_DF2 (0x1 << 6)
+#define RT5616_IN_SFT2 6
+
+/* INL1 and INR1 Volume Control (0x0f) */
+#define RT5616_INL_VOL_MASK (0x1f << 8)
+#define RT5616_INL_VOL_SFT 8
+#define RT5616_INR_SEL_MASK (0x1 << 7)
+#define RT5616_INR_SEL_SFT 7
+#define RT5616_INR_SEL_IN4N (0x0 << 7)
+#define RT5616_INR_SEL_MONON (0x1 << 7)
+#define RT5616_INR_VOL_MASK (0x1f)
+#define RT5616_INR_VOL_SFT 0
+
+/* DAC1 Digital Volume (0x19) */
+#define RT5616_DAC_L1_VOL_MASK (0xff << 8)
+#define RT5616_DAC_L1_VOL_SFT 8
+#define RT5616_DAC_R1_VOL_MASK (0xff)
+#define RT5616_DAC_R1_VOL_SFT 0
+
+/* DAC2 Digital Volume (0x1a) */
+#define RT5616_DAC_L2_VOL_MASK (0xff << 8)
+#define RT5616_DAC_L2_VOL_SFT 8
+#define RT5616_DAC_R2_VOL_MASK (0xff)
+#define RT5616_DAC_R2_VOL_SFT 0
+
+/* ADC Digital Volume Control (0x1c) */
+#define RT5616_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5616_ADC_L_VOL_SFT 8
+#define RT5616_ADC_R_VOL_MASK (0x7f)
+#define RT5616_ADC_R_VOL_SFT 0
+
+/* Mono ADC Digital Volume Control (0x1d) */
+#define RT5616_M_MONO_ADC_L (0x1 << 15)
+#define RT5616_M_MONO_ADC_L_SFT 15
+#define RT5616_MONO_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5616_MONO_ADC_L_VOL_SFT 8
+#define RT5616_M_MONO_ADC_R (0x1 << 7)
+#define RT5616_M_MONO_ADC_R_SFT 7
+#define RT5616_MONO_ADC_R_VOL_MASK (0x7f)
+#define RT5616_MONO_ADC_R_VOL_SFT 0
+
+/* ADC Boost Volume Control (0x1e) */
+#define RT5616_ADC_L_BST_MASK (0x3 << 14)
+#define RT5616_ADC_L_BST_SFT 14
+#define RT5616_ADC_R_BST_MASK (0x3 << 12)
+#define RT5616_ADC_R_BST_SFT 12
+#define RT5616_ADC_COMP_MASK (0x3 << 10)
+#define RT5616_ADC_COMP_SFT 10
+
+/* Stereo ADC1 Mixer Control (0x27) */
+#define RT5616_M_STO1_ADC_L1 (0x1 << 14)
+#define RT5616_M_STO1_ADC_L1_SFT 14
+#define RT5616_M_STO1_ADC_R1 (0x1 << 6)
+#define RT5616_M_STO1_ADC_R1_SFT 6
+
+/* ADC Mixer to DAC Mixer Control (0x29) */
+#define RT5616_M_ADCMIX_L (0x1 << 15)
+#define RT5616_M_ADCMIX_L_SFT 15
+#define RT5616_M_IF1_DAC_L (0x1 << 14)
+#define RT5616_M_IF1_DAC_L_SFT 14
+#define RT5616_M_ADCMIX_R (0x1 << 7)
+#define RT5616_M_ADCMIX_R_SFT 7
+#define RT5616_M_IF1_DAC_R (0x1 << 6)
+#define RT5616_M_IF1_DAC_R_SFT 6
+
+/* Stereo DAC Mixer Control (0x2a) */
+#define RT5616_M_DAC_L1_MIXL (0x1 << 14)
+#define RT5616_M_DAC_L1_MIXL_SFT 14
+#define RT5616_DAC_L1_STO_L_VOL_MASK (0x1 << 13)
+#define RT5616_DAC_L1_STO_L_VOL_SFT 13
+#define RT5616_M_DAC_R1_MIXL (0x1 << 9)
+#define RT5616_M_DAC_R1_MIXL_SFT 9
+#define RT5616_DAC_R1_STO_L_VOL_MASK (0x1 << 8)
+#define RT5616_DAC_R1_STO_L_VOL_SFT 8
+#define RT5616_M_DAC_R1_MIXR (0x1 << 6)
+#define RT5616_M_DAC_R1_MIXR_SFT 6
+#define RT5616_DAC_R1_STO_R_VOL_MASK (0x1 << 5)
+#define RT5616_DAC_R1_STO_R_VOL_SFT 5
+#define RT5616_M_DAC_L1_MIXR (0x1 << 1)
+#define RT5616_M_DAC_L1_MIXR_SFT 1
+#define RT5616_DAC_L1_STO_R_VOL_MASK (0x1)
+#define RT5616_DAC_L1_STO_R_VOL_SFT 0
+
+/* DD Mixer Control (0x2b) */
+#define RT5616_M_STO_DD_L1 (0x1 << 14)
+#define RT5616_M_STO_DD_L1_SFT 14
+#define RT5616_STO_DD_L1_VOL_MASK (0x1 << 13)
+#define RT5616_DAC_DD_L1_VOL_SFT 13
+#define RT5616_M_STO_DD_L2 (0x1 << 12)
+#define RT5616_M_STO_DD_L2_SFT 12
+#define RT5616_STO_DD_L2_VOL_MASK (0x1 << 11)
+#define RT5616_STO_DD_L2_VOL_SFT 11
+#define RT5616_M_STO_DD_R2_L (0x1 << 10)
+#define RT5616_M_STO_DD_R2_L_SFT 10
+#define RT5616_STO_DD_R2_L_VOL_MASK (0x1 << 9)
+#define RT5616_STO_DD_R2_L_VOL_SFT 9
+#define RT5616_M_STO_DD_R1 (0x1 << 6)
+#define RT5616_M_STO_DD_R1_SFT 6
+#define RT5616_STO_DD_R1_VOL_MASK (0x1 << 5)
+#define RT5616_STO_DD_R1_VOL_SFT 5
+#define RT5616_M_STO_DD_R2 (0x1 << 4)
+#define RT5616_M_STO_DD_R2_SFT 4
+#define RT5616_STO_DD_R2_VOL_MASK (0x1 << 3)
+#define RT5616_STO_DD_R2_VOL_SFT 3
+#define RT5616_M_STO_DD_L2_R (0x1 << 2)
+#define RT5616_M_STO_DD_L2_R_SFT 2
+#define RT5616_STO_DD_L2_R_VOL_MASK (0x1 << 1)
+#define RT5616_STO_DD_L2_R_VOL_SFT 1
+
+/* Digital Mixer Control (0x2c) */
+#define RT5616_M_STO_L_DAC_L (0x1 << 15)
+#define RT5616_M_STO_L_DAC_L_SFT 15
+#define RT5616_STO_L_DAC_L_VOL_MASK (0x1 << 14)
+#define RT5616_STO_L_DAC_L_VOL_SFT 14
+#define RT5616_M_DAC_L2_DAC_L (0x1 << 13)
+#define RT5616_M_DAC_L2_DAC_L_SFT 13
+#define RT5616_DAC_L2_DAC_L_VOL_MASK (0x1 << 12)
+#define RT5616_DAC_L2_DAC_L_VOL_SFT 12
+#define RT5616_M_STO_R_DAC_R (0x1 << 11)
+#define RT5616_M_STO_R_DAC_R_SFT 11
+#define RT5616_STO_R_DAC_R_VOL_MASK (0x1 << 10)
+#define RT5616_STO_R_DAC_R_VOL_SFT 10
+#define RT5616_M_DAC_R2_DAC_R (0x1 << 9)
+#define RT5616_M_DAC_R2_DAC_R_SFT 9
+#define RT5616_DAC_R2_DAC_R_VOL_MASK (0x1 << 8)
+#define RT5616_DAC_R2_DAC_R_VOL_SFT 8
+
+/* DSP Path Control 1 (0x2d) */
+#define RT5616_RXDP_SRC_MASK (0x1 << 15)
+#define RT5616_RXDP_SRC_SFT 15
+#define RT5616_RXDP_SRC_NOR (0x0 << 15)
+#define RT5616_RXDP_SRC_DIV3 (0x1 << 15)
+#define RT5616_TXDP_SRC_MASK (0x1 << 14)
+#define RT5616_TXDP_SRC_SFT 14
+#define RT5616_TXDP_SRC_NOR (0x0 << 14)
+#define RT5616_TXDP_SRC_DIV3 (0x1 << 14)
+
+/* DSP Path Control 2 (0x2e) */
+#define RT5616_DAC_L2_SEL_MASK (0x3 << 14)
+#define RT5616_DAC_L2_SEL_SFT 14
+#define RT5616_DAC_L2_SEL_IF2 (0x0 << 14)
+#define RT5616_DAC_L2_SEL_IF3 (0x1 << 14)
+#define RT5616_DAC_L2_SEL_TXDC (0x2 << 14)
+#define RT5616_DAC_L2_SEL_BASS (0x3 << 14)
+#define RT5616_DAC_R2_SEL_MASK (0x3 << 12)
+#define RT5616_DAC_R2_SEL_SFT 12
+#define RT5616_DAC_R2_SEL_IF2 (0x0 << 12)
+#define RT5616_DAC_R2_SEL_IF3 (0x1 << 12)
+#define RT5616_DAC_R2_SEL_TXDC (0x2 << 12)
+#define RT5616_IF2_ADC_L_SEL_MASK (0x1 << 11)
+#define RT5616_IF2_ADC_L_SEL_SFT 11
+#define RT5616_IF2_ADC_L_SEL_TXDP (0x0 << 11)
+#define RT5616_IF2_ADC_L_SEL_PASS (0x1 << 11)
+#define RT5616_IF2_ADC_R_SEL_MASK (0x1 << 10)
+#define RT5616_IF2_ADC_R_SEL_SFT 10
+#define RT5616_IF2_ADC_R_SEL_TXDP (0x0 << 10)
+#define RT5616_IF2_ADC_R_SEL_PASS (0x1 << 10)
+#define RT5616_RXDC_SEL_MASK (0x3 << 8)
+#define RT5616_RXDC_SEL_SFT 8
+#define RT5616_RXDC_SEL_NOR (0x0 << 8)
+#define RT5616_RXDC_SEL_L2R (0x1 << 8)
+#define RT5616_RXDC_SEL_R2L (0x2 << 8)
+#define RT5616_RXDC_SEL_SWAP (0x3 << 8)
+#define RT5616_RXDP_SEL_MASK (0x3 << 6)
+#define RT5616_RXDP_SEL_SFT 6
+#define RT5616_RXDP_SEL_NOR (0x0 << 6)
+#define RT5616_RXDP_SEL_L2R (0x1 << 6)
+#define RT5616_RXDP_SEL_R2L (0x2 << 6)
+#define RT5616_RXDP_SEL_SWAP (0x3 << 6)
+#define RT5616_TXDC_SEL_MASK (0x3 << 4)
+#define RT5616_TXDC_SEL_SFT 4
+#define RT5616_TXDC_SEL_NOR (0x0 << 4)
+#define RT5616_TXDC_SEL_L2R (0x1 << 4)
+#define RT5616_TXDC_SEL_R2L (0x2 << 4)
+#define RT5616_TXDC_SEL_SWAP (0x3 << 4)
+#define RT5616_TXDP_SEL_MASK (0x3 << 2)
+#define RT5616_TXDP_SEL_SFT 2
+#define RT5616_TXDP_SEL_NOR (0x0 << 2)
+#define RT5616_TXDP_SEL_L2R (0x1 << 2)
+#define RT5616_TXDP_SEL_R2L (0x2 << 2)
+#define RT5616_TRXDP_SEL_SWAP (0x3 << 2)
+
+/* REC Left Mixer Control 1 (0x3b) */
+#define RT5616_G_LN_L2_RM_L_MASK (0x7 << 13)
+#define RT5616_G_IN_L2_RM_L_SFT 13
+#define RT5616_G_LN_L1_RM_L_MASK (0x7 << 10)
+#define RT5616_G_IN_L1_RM_L_SFT 10
+#define RT5616_G_BST3_RM_L_MASK (0x7 << 4)
+#define RT5616_G_BST3_RM_L_SFT 4
+#define RT5616_G_BST2_RM_L_MASK (0x7 << 1)
+#define RT5616_G_BST2_RM_L_SFT 1
+
+/* REC Left Mixer Control 2 (0x3c) */
+#define RT5616_G_BST1_RM_L_MASK (0x7 << 13)
+#define RT5616_G_BST1_RM_L_SFT 13
+#define RT5616_G_OM_L_RM_L_MASK (0x7 << 10)
+#define RT5616_G_OM_L_RM_L_SFT 10
+#define RT5616_M_IN2_L_RM_L (0x1 << 6)
+#define RT5616_M_IN2_L_RM_L_SFT 6
+#define RT5616_M_IN1_L_RM_L (0x1 << 5)
+#define RT5616_M_IN1_L_RM_L_SFT 5
+#define RT5616_M_BST3_RM_L (0x1 << 3)
+#define RT5616_M_BST3_RM_L_SFT 3
+#define RT5616_M_BST2_RM_L (0x1 << 2)
+#define RT5616_M_BST2_RM_L_SFT 2
+#define RT5616_M_BST1_RM_L (0x1 << 1)
+#define RT5616_M_BST1_RM_L_SFT 1
+#define RT5616_M_OM_L_RM_L (0x1)
+#define RT5616_M_OM_L_RM_L_SFT 0
+
+/* REC Right Mixer Control 1 (0x3d) */
+#define RT5616_G_IN2_R_RM_R_MASK (0x7 << 13)
+#define RT5616_G_IN2_R_RM_R_SFT 13
+#define RT5616_G_IN1_R_RM_R_MASK (0x7 << 10)
+#define RT5616_G_IN1_R_RM_R_SFT 10
+#define RT5616_G_BST3_RM_R_MASK (0x7 << 4)
+#define RT5616_G_BST3_RM_R_SFT 4
+#define RT5616_G_BST2_RM_R_MASK (0x7 << 1)
+#define RT5616_G_BST2_RM_R_SFT 1
+
+/* REC Right Mixer Control 2 (0x3e) */
+#define RT5616_G_BST1_RM_R_MASK (0x7 << 13)
+#define RT5616_G_BST1_RM_R_SFT 13
+#define RT5616_G_OM_R_RM_R_MASK (0x7 << 10)
+#define RT5616_G_OM_R_RM_R_SFT 10
+#define RT5616_M_IN2_R_RM_R (0x1 << 6)
+#define RT5616_M_IN2_R_RM_R_SFT 6
+#define RT5616_M_IN1_R_RM_R (0x1 << 5)
+#define RT5616_M_IN1_R_RM_R_SFT 5
+#define RT5616_M_BST3_RM_R (0x1 << 3)
+#define RT5616_M_BST3_RM_R_SFT 3
+#define RT5616_M_BST2_RM_R (0x1 << 2)
+#define RT5616_M_BST2_RM_R_SFT 2
+#define RT5616_M_BST1_RM_R (0x1 << 1)
+#define RT5616_M_BST1_RM_R_SFT 1
+#define RT5616_M_OM_R_RM_R (0x1)
+#define RT5616_M_OM_R_RM_R_SFT 0
+
+/* HPMIX Control (0x45) */
+#define RT5616_M_DAC1_HM (0x1 << 14)
+#define RT5616_M_DAC1_HM_SFT 14
+#define RT5616_M_HPVOL_HM (0x1 << 13)
+#define RT5616_M_HPVOL_HM_SFT 13
+#define RT5616_G_HPOMIX_MASK (0x1 << 12)
+#define RT5616_G_HPOMIX_SFT 12
+
+/* SPK Left Mixer Control (0x46) */
+#define RT5616_G_RM_L_SM_L_MASK (0x3 << 14)
+#define RT5616_G_RM_L_SM_L_SFT 14
+#define RT5616_G_IN_L_SM_L_MASK (0x3 << 12)
+#define RT5616_G_IN_L_SM_L_SFT 12
+#define RT5616_G_DAC_L1_SM_L_MASK (0x3 << 10)
+#define RT5616_G_DAC_L1_SM_L_SFT 10
+#define RT5616_G_DAC_L2_SM_L_MASK (0x3 << 8)
+#define RT5616_G_DAC_L2_SM_L_SFT 8
+#define RT5616_G_OM_L_SM_L_MASK (0x3 << 6)
+#define RT5616_G_OM_L_SM_L_SFT 6
+#define RT5616_M_RM_L_SM_L (0x1 << 5)
+#define RT5616_M_RM_L_SM_L_SFT 5
+#define RT5616_M_IN_L_SM_L (0x1 << 4)
+#define RT5616_M_IN_L_SM_L_SFT 4
+#define RT5616_M_DAC_L1_SM_L (0x1 << 3)
+#define RT5616_M_DAC_L1_SM_L_SFT 3
+#define RT5616_M_DAC_L2_SM_L (0x1 << 2)
+#define RT5616_M_DAC_L2_SM_L_SFT 2
+#define RT5616_M_OM_L_SM_L (0x1 << 1)
+#define RT5616_M_OM_L_SM_L_SFT 1
+
+/* SPK Right Mixer Control (0x47) */
+#define RT5616_G_RM_R_SM_R_MASK (0x3 << 14)
+#define RT5616_G_RM_R_SM_R_SFT 14
+#define RT5616_G_IN_R_SM_R_MASK (0x3 << 12)
+#define RT5616_G_IN_R_SM_R_SFT 12
+#define RT5616_G_DAC_R1_SM_R_MASK (0x3 << 10)
+#define RT5616_G_DAC_R1_SM_R_SFT 10
+#define RT5616_G_DAC_R2_SM_R_MASK (0x3 << 8)
+#define RT5616_G_DAC_R2_SM_R_SFT 8
+#define RT5616_G_OM_R_SM_R_MASK (0x3 << 6)
+#define RT5616_G_OM_R_SM_R_SFT 6
+#define RT5616_M_RM_R_SM_R (0x1 << 5)
+#define RT5616_M_RM_R_SM_R_SFT 5
+#define RT5616_M_IN_R_SM_R (0x1 << 4)
+#define RT5616_M_IN_R_SM_R_SFT 4
+#define RT5616_M_DAC_R1_SM_R (0x1 << 3)
+#define RT5616_M_DAC_R1_SM_R_SFT 3
+#define RT5616_M_DAC_R2_SM_R (0x1 << 2)
+#define RT5616_M_DAC_R2_SM_R_SFT 2
+#define RT5616_M_OM_R_SM_R (0x1 << 1)
+#define RT5616_M_OM_R_SM_R_SFT 1
+
+/* SPOLMIX Control (0x48) */
+#define RT5616_M_DAC_R1_SPM_L (0x1 << 15)
+#define RT5616_M_DAC_R1_SPM_L_SFT 15
+#define RT5616_M_DAC_L1_SPM_L (0x1 << 14)
+#define RT5616_M_DAC_L1_SPM_L_SFT 14
+#define RT5616_M_SV_R_SPM_L (0x1 << 13)
+#define RT5616_M_SV_R_SPM_L_SFT 13
+#define RT5616_M_SV_L_SPM_L (0x1 << 12)
+#define RT5616_M_SV_L_SPM_L_SFT 12
+#define RT5616_M_BST1_SPM_L (0x1 << 11)
+#define RT5616_M_BST1_SPM_L_SFT 11
+
+/* SPORMIX Control (0x49) */
+#define RT5616_M_DAC_R1_SPM_R (0x1 << 13)
+#define RT5616_M_DAC_R1_SPM_R_SFT 13
+#define RT5616_M_SV_R_SPM_R (0x1 << 12)
+#define RT5616_M_SV_R_SPM_R_SFT 12
+#define RT5616_M_BST1_SPM_R (0x1 << 11)
+#define RT5616_M_BST1_SPM_R_SFT 11
+
+/* SPOLMIX / SPORMIX Ratio Control (0x4a) */
+#define RT5616_SPO_CLSD_RATIO_MASK (0x7)
+#define RT5616_SPO_CLSD_RATIO_SFT 0
+
+/* Mono Output Mixer Control (0x4c) */
+#define RT5616_M_DAC_R2_MM (0x1 << 15)
+#define RT5616_M_DAC_R2_MM_SFT 15
+#define RT5616_M_DAC_L2_MM (0x1 << 14)
+#define RT5616_M_DAC_L2_MM_SFT 14
+#define RT5616_M_OV_R_MM (0x1 << 13)
+#define RT5616_M_OV_R_MM_SFT 13
+#define RT5616_M_OV_L_MM (0x1 << 12)
+#define RT5616_M_OV_L_MM_SFT 12
+#define RT5616_M_BST1_MM (0x1 << 11)
+#define RT5616_M_BST1_MM_SFT 11
+#define RT5616_G_MONOMIX_MASK (0x1 << 10)
+#define RT5616_G_MONOMIX_SFT 10
+
+/* Output Left Mixer Control 1 (0x4d) */
+#define RT5616_G_BST2_OM_L_MASK (0x7 << 10)
+#define RT5616_G_BST2_OM_L_SFT 10
+#define RT5616_G_BST1_OM_L_MASK (0x7 << 7)
+#define RT5616_G_BST1_OM_L_SFT 7
+#define RT5616_G_IN1_L_OM_L_MASK (0x7 << 4)
+#define RT5616_G_IN1_L_OM_L_SFT 4
+#define RT5616_G_RM_L_OM_L_MASK (0x7 << 1)
+#define RT5616_G_RM_L_OM_L_SFT 1
+
+/* Output Left Mixer Control 2 (0x4e) */
+#define RT5616_G_DAC_L1_OM_L_MASK (0x7 << 7)
+#define RT5616_G_DAC_L1_OM_L_SFT 7
+#define RT5616_G_IN2_L_OM_L_MASK (0x7 << 4)
+#define RT5616_G_IN2_L_OM_L_SFT 4
+
+/* Output Left Mixer Control 3 (0x4f) */
+#define RT5616_M_IN2_L_OM_L (0x1 << 9)
+#define RT5616_M_IN2_L_OM_L_SFT 9
+#define RT5616_M_BST2_OM_L (0x1 << 6)
+#define RT5616_M_BST2_OM_L_SFT 6
+#define RT5616_M_BST1_OM_L (0x1 << 5)
+#define RT5616_M_BST1_OM_L_SFT 5
+#define RT5616_M_IN1_L_OM_L (0x1 << 4)
+#define RT5616_M_IN1_L_OM_L_SFT 4
+#define RT5616_M_RM_L_OM_L (0x1 << 3)
+#define RT5616_M_RM_L_OM_L_SFT 3
+#define RT5616_M_DAC_L1_OM_L (0x1)
+#define RT5616_M_DAC_L1_OM_L_SFT 0
+
+/* Output Right Mixer Control 1 (0x50) */
+#define RT5616_G_BST2_OM_R_MASK (0x7 << 10)
+#define RT5616_G_BST2_OM_R_SFT 10
+#define RT5616_G_BST1_OM_R_MASK (0x7 << 7)
+#define RT5616_G_BST1_OM_R_SFT 7
+#define RT5616_G_IN1_R_OM_R_MASK (0x7 << 4)
+#define RT5616_G_IN1_R_OM_R_SFT 4
+#define RT5616_G_RM_R_OM_R_MASK (0x7 << 1)
+#define RT5616_G_RM_R_OM_R_SFT 1
+
+/* Output Right Mixer Control 2 (0x51) */
+#define RT5616_G_DAC_R1_OM_R_MASK (0x7 << 7)
+#define RT5616_G_DAC_R1_OM_R_SFT 7
+#define RT5616_G_IN2_R_OM_R_MASK (0x7 << 4)
+#define RT5616_G_IN2_R_OM_R_SFT 4
+
+/* Output Right Mixer Control 3 (0x52) */
+#define RT5616_M_IN2_R_OM_R (0x1 << 9)
+#define RT5616_M_IN2_R_OM_R_SFT 9
+#define RT5616_M_BST2_OM_R (0x1 << 6)
+#define RT5616_M_BST2_OM_R_SFT 6
+#define RT5616_M_BST1_OM_R (0x1 << 5)
+#define RT5616_M_BST1_OM_R_SFT 5
+#define RT5616_M_IN1_R_OM_R (0x1 << 4)
+#define RT5616_M_IN1_R_OM_R_SFT 4
+#define RT5616_M_RM_R_OM_R (0x1 << 3)
+#define RT5616_M_RM_R_OM_R_SFT 3
+#define RT5616_M_DAC_R1_OM_R (0x1)
+#define RT5616_M_DAC_R1_OM_R_SFT 0
+
+/* LOUT Mixer Control (0x53) */
+#define RT5616_M_DAC_L1_LM (0x1 << 15)
+#define RT5616_M_DAC_L1_LM_SFT 15
+#define RT5616_M_DAC_R1_LM (0x1 << 14)
+#define RT5616_M_DAC_R1_LM_SFT 14
+#define RT5616_M_OV_L_LM (0x1 << 13)
+#define RT5616_M_OV_L_LM_SFT 13
+#define RT5616_M_OV_R_LM (0x1 << 12)
+#define RT5616_M_OV_R_LM_SFT 12
+#define RT5616_G_LOUTMIX_MASK (0x1 << 11)
+#define RT5616_G_LOUTMIX_SFT 11
+
+/* Power Management for Digital 1 (0x61) */
+#define RT5616_PWR_I2S1 (0x1 << 15)
+#define RT5616_PWR_I2S1_BIT 15
+#define RT5616_PWR_I2S2 (0x1 << 14)
+#define RT5616_PWR_I2S2_BIT 14
+#define RT5616_PWR_DAC_L1 (0x1 << 12)
+#define RT5616_PWR_DAC_L1_BIT 12
+#define RT5616_PWR_DAC_R1 (0x1 << 11)
+#define RT5616_PWR_DAC_R1_BIT 11
+#define RT5616_PWR_ADC_L (0x1 << 2)
+#define RT5616_PWR_ADC_L_BIT 2
+#define RT5616_PWR_ADC_R (0x1 << 1)
+#define RT5616_PWR_ADC_R_BIT 1
+
+/* Power Management for Digital 2 (0x62) */
+#define RT5616_PWR_ADC_STO1_F (0x1 << 15)
+#define RT5616_PWR_ADC_STO1_F_BIT 15
+#define RT5616_PWR_DAC_STO1_F (0x1 << 11)
+#define RT5616_PWR_DAC_STO1_F_BIT 11
+
+/* Power Management for Analog 1 (0x63) */
+#define RT5616_PWR_VREF1 (0x1 << 15)
+#define RT5616_PWR_VREF1_BIT 15
+#define RT5616_PWR_FV1 (0x1 << 14)
+#define RT5616_PWR_FV1_BIT 14
+#define RT5616_PWR_MB (0x1 << 13)
+#define RT5616_PWR_MB_BIT 13
+#define RT5616_PWR_LM (0x1 << 12)
+#define RT5616_PWR_LM_BIT 12
+#define RT5616_PWR_BG (0x1 << 11)
+#define RT5616_PWR_BG_BIT 11
+#define RT5616_PWR_HP_L (0x1 << 7)
+#define RT5616_PWR_HP_L_BIT 7
+#define RT5616_PWR_HP_R (0x1 << 6)
+#define RT5616_PWR_HP_R_BIT 6
+#define RT5616_PWR_HA (0x1 << 5)
+#define RT5616_PWR_HA_BIT 5
+#define RT5616_PWR_VREF2 (0x1 << 4)
+#define RT5616_PWR_VREF2_BIT 4
+#define RT5616_PWR_FV2 (0x1 << 3)
+#define RT5616_PWR_FV2_BIT 3
+#define RT5616_PWR_LDO (0x1 << 2)
+#define RT5616_PWR_LDO_BIT 2
+#define RT5616_PWR_LDO_DVO_MASK (0x3)
+#define RT5616_PWR_LDO_DVO_1_0V 0
+#define RT5616_PWR_LDO_DVO_1_1V 1
+#define RT5616_PWR_LDO_DVO_1_2V 2
+#define RT5616_PWR_LDO_DVO_1_3V 3
+
+/* Power Management for Analog 2 (0x64) */
+#define RT5616_PWR_BST1 (0x1 << 15)
+#define RT5616_PWR_BST1_BIT 15
+#define RT5616_PWR_BST2 (0x1 << 14)
+#define RT5616_PWR_BST2_BIT 14
+#define RT5616_PWR_MB1 (0x1 << 11)
+#define RT5616_PWR_MB1_BIT 11
+#define RT5616_PWR_PLL (0x1 << 9)
+#define RT5616_PWR_PLL_BIT 9
+#define RT5616_PWR_BST1_OP2 (0x1 << 5)
+#define RT5616_PWR_BST1_OP2_BIT 5
+#define RT5616_PWR_BST2_OP2 (0x1 << 4)
+#define RT5616_PWR_BST2_OP2_BIT 4
+#define RT5616_PWR_BST3_OP2 (0x1 << 3)
+#define RT5616_PWR_BST3_OP2_BIT 3
+#define RT5616_PWR_JD_M (0x1 << 2)
+#define RT5616_PWM_JD_M_BIT 2
+#define RT5616_PWR_JD2 (0x1 << 1)
+#define RT5616_PWM_JD2_BIT 1
+#define RT5616_PWR_JD3 (0x1)
+#define RT5616_PWM_JD3_BIT 0
+
+/* Power Management for Mixer (0x65) */
+#define RT5616_PWR_OM_L (0x1 << 15)
+#define RT5616_PWR_OM_L_BIT 15
+#define RT5616_PWR_OM_R (0x1 << 14)
+#define RT5616_PWR_OM_R_BIT 14
+#define RT5616_PWR_RM_L (0x1 << 11)
+#define RT5616_PWR_RM_L_BIT 11
+#define RT5616_PWR_RM_R (0x1 << 10)
+#define RT5616_PWR_RM_R_BIT 10
+
+/* Power Management for Volume (0x66) */
+#define RT5616_PWR_OV_L (0x1 << 13)
+#define RT5616_PWR_OV_L_BIT 13
+#define RT5616_PWR_OV_R (0x1 << 12)
+#define RT5616_PWR_OV_R_BIT 12
+#define RT5616_PWR_HV_L (0x1 << 11)
+#define RT5616_PWR_HV_L_BIT 11
+#define RT5616_PWR_HV_R (0x1 << 10)
+#define RT5616_PWR_HV_R_BIT 10
+#define RT5616_PWR_IN1_L (0x1 << 9)
+#define RT5616_PWR_IN1_L_BIT 9
+#define RT5616_PWR_IN1_R (0x1 << 8)
+#define RT5616_PWR_IN1_R_BIT 8
+#define RT5616_PWR_IN2_L (0x1 << 7)
+#define RT5616_PWR_IN2_L_BIT 7
+#define RT5616_PWR_IN2_R (0x1 << 6)
+#define RT5616_PWR_IN2_R_BIT 6
+
+/* I2S1/2/3 Audio Serial Data Port Control (0x70 0x71) */
+#define RT5616_I2S_MS_MASK (0x1 << 15)
+#define RT5616_I2S_MS_SFT 15
+#define RT5616_I2S_MS_M (0x0 << 15)
+#define RT5616_I2S_MS_S (0x1 << 15)
+#define RT5616_I2S_O_CP_MASK (0x3 << 10)
+#define RT5616_I2S_O_CP_SFT 10
+#define RT5616_I2S_O_CP_OFF (0x0 << 10)
+#define RT5616_I2S_O_CP_U_LAW (0x1 << 10)
+#define RT5616_I2S_O_CP_A_LAW (0x2 << 10)
+#define RT5616_I2S_I_CP_MASK (0x3 << 8)
+#define RT5616_I2S_I_CP_SFT 8
+#define RT5616_I2S_I_CP_OFF (0x0 << 8)
+#define RT5616_I2S_I_CP_U_LAW (0x1 << 8)
+#define RT5616_I2S_I_CP_A_LAW (0x2 << 8)
+#define RT5616_I2S_BP_MASK (0x1 << 7)
+#define RT5616_I2S_BP_SFT 7
+#define RT5616_I2S_BP_NOR (0x0 << 7)
+#define RT5616_I2S_BP_INV (0x1 << 7)
+#define RT5616_I2S_DL_MASK (0x3 << 2)
+#define RT5616_I2S_DL_SFT 2
+#define RT5616_I2S_DL_16 (0x0 << 2)
+#define RT5616_I2S_DL_20 (0x1 << 2)
+#define RT5616_I2S_DL_24 (0x2 << 2)
+#define RT5616_I2S_DL_8 (0x3 << 2)
+#define RT5616_I2S_DF_MASK (0x3)
+#define RT5616_I2S_DF_SFT 0
+#define RT5616_I2S_DF_I2S (0x0)
+#define RT5616_I2S_DF_LEFT (0x1)
+#define RT5616_I2S_DF_PCM_A (0x2)
+#define RT5616_I2S_DF_PCM_B (0x3)
+
+/* ADC/DAC Clock Control 1 (0x73) */
+#define RT5616_I2S_PD1_MASK (0x7 << 12)
+#define RT5616_I2S_PD1_SFT 12
+#define RT5616_I2S_PD1_1 (0x0 << 12)
+#define RT5616_I2S_PD1_2 (0x1 << 12)
+#define RT5616_I2S_PD1_3 (0x2 << 12)
+#define RT5616_I2S_PD1_4 (0x3 << 12)
+#define RT5616_I2S_PD1_6 (0x4 << 12)
+#define RT5616_I2S_PD1_8 (0x5 << 12)
+#define RT5616_I2S_PD1_12 (0x6 << 12)
+#define RT5616_I2S_PD1_16 (0x7 << 12)
+#define RT5616_I2S_BCLK_MS2_MASK (0x1 << 11)
+#define RT5616_DAC_OSR_MASK (0x3 << 2)
+#define RT5616_DAC_OSR_SFT 2
+#define RT5616_DAC_OSR_128 (0x0 << 2)
+#define RT5616_DAC_OSR_64 (0x1 << 2)
+#define RT5616_DAC_OSR_32 (0x2 << 2)
+#define RT5616_DAC_OSR_128_3 (0x3 << 2)
+#define RT5616_ADC_OSR_MASK (0x3)
+#define RT5616_ADC_OSR_SFT 0
+#define RT5616_ADC_OSR_128 (0x0)
+#define RT5616_ADC_OSR_64 (0x1)
+#define RT5616_ADC_OSR_32 (0x2)
+#define RT5616_ADC_OSR_128_3 (0x3)
+
+/* ADC/DAC Clock Control 2 (0x74) */
+#define RT5616_DAHPF_EN (0x1 << 11)
+#define RT5616_DAHPF_EN_SFT 11
+#define RT5616_ADHPF_EN (0x1 << 10)
+#define RT5616_ADHPF_EN_SFT 10
+
+/* TDM Control 1 (0x77) */
+#define RT5616_TDM_INTEL_SEL_MASK (0x1 << 15)
+#define RT5616_TDM_INTEL_SEL_SFT 15
+#define RT5616_TDM_INTEL_SEL_64 (0x0 << 15)
+#define RT5616_TDM_INTEL_SEL_50 (0x1 << 15)
+#define RT5616_TDM_MODE_SEL_MASK (0x1 << 14)
+#define RT5616_TDM_MODE_SEL_SFT 14
+#define RT5616_TDM_MODE_SEL_NOR (0x0 << 14)
+#define RT5616_TDM_MODE_SEL_TDM (0x1 << 14)
+#define RT5616_TDM_CH_NUM_SEL_MASK (0x3 << 12)
+#define RT5616_TDM_CH_NUM_SEL_SFT 12
+#define RT5616_TDM_CH_NUM_SEL_2 (0x0 << 12)
+#define RT5616_TDM_CH_NUM_SEL_4 (0x1 << 12)
+#define RT5616_TDM_CH_NUM_SEL_6 (0x2 << 12)
+#define RT5616_TDM_CH_NUM_SEL_8 (0x3 << 12)
+#define RT5616_TDM_CH_LEN_SEL_MASK (0x3 << 10)
+#define RT5616_TDM_CH_LEN_SEL_SFT 10
+#define RT5616_TDM_CH_LEN_SEL_16 (0x0 << 10)
+#define RT5616_TDM_CH_LEN_SEL_20 (0x1 << 10)
+#define RT5616_TDM_CH_LEN_SEL_24 (0x2 << 10)
+#define RT5616_TDM_CH_LEN_SEL_32 (0x3 << 10)
+#define RT5616_TDM_ADC_SEL_MASK (0x1 << 9)
+#define RT5616_TDM_ADC_SEL_SFT 9
+#define RT5616_TDM_ADC_SEL_NOR (0x0 << 9)
+#define RT5616_TDM_ADC_SEL_SWAP (0x1 << 9)
+#define RT5616_TDM_ADC_START_SEL_MASK (0x1 << 8)
+#define RT5616_TDM_ADC_START_SEL_SFT 8
+#define RT5616_TDM_ADC_START_SEL_SL0 (0x0 << 8)
+#define RT5616_TDM_ADC_START_SEL_SL4 (0x1 << 8)
+#define RT5616_TDM_I2S_CH2_SEL_MASK (0x3 << 6)
+#define RT5616_TDM_I2S_CH2_SEL_SFT 6
+#define RT5616_TDM_I2S_CH2_SEL_LR (0x0 << 6)
+#define RT5616_TDM_I2S_CH2_SEL_RL (0x1 << 6)
+#define RT5616_TDM_I2S_CH2_SEL_LL (0x2 << 6)
+#define RT5616_TDM_I2S_CH2_SEL_RR (0x3 << 6)
+#define RT5616_TDM_I2S_CH4_SEL_MASK (0x3 << 4)
+#define RT5616_TDM_I2S_CH4_SEL_SFT 4
+#define RT5616_TDM_I2S_CH4_SEL_LR (0x0 << 4)
+#define RT5616_TDM_I2S_CH4_SEL_RL (0x1 << 4)
+#define RT5616_TDM_I2S_CH4_SEL_LL (0x2 << 4)
+#define RT5616_TDM_I2S_CH4_SEL_RR (0x3 << 4)
+#define RT5616_TDM_I2S_CH6_SEL_MASK (0x3 << 2)
+#define RT5616_TDM_I2S_CH6_SEL_SFT 2
+#define RT5616_TDM_I2S_CH6_SEL_LR (0x0 << 2)
+#define RT5616_TDM_I2S_CH6_SEL_RL (0x1 << 2)
+#define RT5616_TDM_I2S_CH6_SEL_LL (0x2 << 2)
+#define RT5616_TDM_I2S_CH6_SEL_RR (0x3 << 2)
+#define RT5616_TDM_I2S_CH8_SEL_MASK (0x3)
+#define RT5616_TDM_I2S_CH8_SEL_SFT 0
+#define RT5616_TDM_I2S_CH8_SEL_LR (0x0)
+#define RT5616_TDM_I2S_CH8_SEL_RL (0x1)
+#define RT5616_TDM_I2S_CH8_SEL_LL (0x2)
+#define RT5616_TDM_I2S_CH8_SEL_RR (0x3)
+
+/* TDM Control 2 (0x78) */
+#define RT5616_TDM_LRCK_POL_SEL_MASK (0x1 << 15)
+#define RT5616_TDM_LRCK_POL_SEL_SFT 15
+#define RT5616_TDM_LRCK_POL_SEL_NOR (0x0 << 15)
+#define RT5616_TDM_LRCK_POL_SEL_INV (0x1 << 15)
+#define RT5616_TDM_CH_VAL_SEL_MASK (0x1 << 14)
+#define RT5616_TDM_CH_VAL_SEL_SFT 14
+#define RT5616_TDM_CH_VAL_SEL_CH01 (0x0 << 14)
+#define RT5616_TDM_CH_VAL_SEL_CH0123 (0x1 << 14)
+#define RT5616_TDM_CH_VAL_EN (0x1 << 13)
+#define RT5616_TDM_CH_VAL_SFT 13
+#define RT5616_TDM_LPBK_EN (0x1 << 12)
+#define RT5616_TDM_LPBK_SFT 12
+#define RT5616_TDM_LRCK_PULSE_SEL_MASK (0x1 << 11)
+#define RT5616_TDM_LRCK_PULSE_SEL_SFT 11
+#define RT5616_TDM_LRCK_PULSE_SEL_BCLK (0x0 << 11)
+#define RT5616_TDM_LRCK_PULSE_SEL_CH (0x1 << 11)
+#define RT5616_TDM_END_EDGE_SEL_MASK (0x1 << 10)
+#define RT5616_TDM_END_EDGE_SEL_SFT 10
+#define RT5616_TDM_END_EDGE_SEL_POS (0x0 << 10)
+#define RT5616_TDM_END_EDGE_SEL_NEG (0x1 << 10)
+#define RT5616_TDM_END_EDGE_EN (0x1 << 9)
+#define RT5616_TDM_END_EDGE_EN_SFT 9
+#define RT5616_TDM_TRAN_EDGE_SEL_MASK (0x1 << 8)
+#define RT5616_TDM_TRAN_EDGE_SEL_SFT 8
+#define RT5616_TDM_TRAN_EDGE_SEL_POS (0x0 << 8)
+#define RT5616_TDM_TRAN_EDGE_SEL_NEG (0x1 << 8)
+#define RT5616_M_TDM2_L (0x1 << 7)
+#define RT5616_M_TDM2_L_SFT 7
+#define RT5616_M_TDM2_R (0x1 << 6)
+#define RT5616_M_TDM2_R_SFT 6
+#define RT5616_M_TDM4_L (0x1 << 5)
+#define RT5616_M_TDM4_L_SFT 5
+#define RT5616_M_TDM4_R (0x1 << 4)
+#define RT5616_M_TDM4_R_SFT 4
+
+/* Global Clock Control (0x80) */
+#define RT5616_SCLK_SRC_MASK (0x3 << 14)
+#define RT5616_SCLK_SRC_SFT 14
+#define RT5616_SCLK_SRC_MCLK (0x0 << 14)
+#define RT5616_SCLK_SRC_PLL1 (0x1 << 14)
+#define RT5616_PLL1_SRC_MASK (0x3 << 12)
+#define RT5616_PLL1_SRC_SFT 12
+#define RT5616_PLL1_SRC_MCLK (0x0 << 12)
+#define RT5616_PLL1_SRC_BCLK1 (0x1 << 12)
+#define RT5616_PLL1_SRC_BCLK2 (0x2 << 12)
+#define RT5616_PLL1_PD_MASK (0x1 << 3)
+#define RT5616_PLL1_PD_SFT 3
+#define RT5616_PLL1_PD_1 (0x0 << 3)
+#define RT5616_PLL1_PD_2 (0x1 << 3)
+
+#define RT5616_PLL_INP_MAX 40000000
+#define RT5616_PLL_INP_MIN 256000
+/* PLL M/N/K Code Control 1 (0x81) */
+#define RT5616_PLL_N_MAX 0x1ff
+#define RT5616_PLL_N_MASK (RT5616_PLL_N_MAX << 7)
+#define RT5616_PLL_N_SFT 7
+#define RT5616_PLL_K_MAX 0x1f
+#define RT5616_PLL_K_MASK (RT5616_PLL_K_MAX)
+#define RT5616_PLL_K_SFT 0
+
+/* PLL M/N/K Code Control 2 (0x82) */
+#define RT5616_PLL_M_MAX 0xf
+#define RT5616_PLL_M_MASK (RT5616_PLL_M_MAX << 12)
+#define RT5616_PLL_M_SFT 12
+#define RT5616_PLL_M_BP (0x1 << 11)
+#define RT5616_PLL_M_BP_SFT 11
+
+/* PLL tracking mode 1 (0x83) */
+#define RT5616_STO1_T_MASK (0x1 << 15)
+#define RT5616_STO1_T_SFT 15
+#define RT5616_STO1_T_SCLK (0x0 << 15)
+#define RT5616_STO1_T_LRCK1 (0x1 << 15)
+#define RT5616_STO2_T_MASK (0x1 << 12)
+#define RT5616_STO2_T_SFT 12
+#define RT5616_STO2_T_I2S2 (0x0 << 12)
+#define RT5616_STO2_T_LRCK2 (0x1 << 12)
+#define RT5616_ASRC2_REF_MASK (0x1 << 11)
+#define RT5616_ASRC2_REF_SFT 11
+#define RT5616_ASRC2_REF_LRCK2 (0x0 << 11)
+#define RT5616_ASRC2_REF_LRCK1 (0x1 << 11)
+#define RT5616_DMIC_1_M_MASK (0x1 << 9)
+#define RT5616_DMIC_1_M_SFT 9
+#define RT5616_DMIC_1_M_NOR (0x0 << 9)
+#define RT5616_DMIC_1_M_ASYN (0x1 << 9)
+
+/* PLL tracking mode 2 (0x84) */
+#define RT5616_STO1_ASRC_EN (0x1 << 15)
+#define RT5616_STO1_ASRC_EN_SFT 15
+#define RT5616_STO2_ASRC_EN (0x1 << 14)
+#define RT5616_STO2_ASRC_EN_SFT 14
+#define RT5616_STO1_DAC_M_MASK (0x1 << 13)
+#define RT5616_STO1_DAC_M_SFT 13
+#define RT5616_STO1_DAC_M_NOR (0x0 << 13)
+#define RT5616_STO1_DAC_M_ASRC (0x1 << 13)
+#define RT5616_STO2_DAC_M_MASK (0x1 << 12)
+#define RT5616_STO2_DAC_M_SFT 12
+#define RT5616_STO2_DAC_M_NOR (0x0 << 12)
+#define RT5616_STO2_DAC_M_ASRC (0x1 << 12)
+#define RT5616_ADC_M_MASK (0x1 << 11)
+#define RT5616_ADC_M_SFT 11
+#define RT5616_ADC_M_NOR (0x0 << 11)
+#define RT5616_ADC_M_ASRC (0x1 << 11)
+#define RT5616_I2S1_R_D_MASK (0x1 << 4)
+#define RT5616_I2S1_R_D_SFT 4
+#define RT5616_I2S1_R_D_DIS (0x0 << 4)
+#define RT5616_I2S1_R_D_EN (0x1 << 4)
+#define RT5616_I2S2_R_D_MASK (0x1 << 3)
+#define RT5616_I2S2_R_D_SFT 3
+#define RT5616_I2S2_R_D_DIS (0x0 << 3)
+#define RT5616_I2S2_R_D_EN (0x1 << 3)
+#define RT5616_PRE_SCLK_MASK (0x3)
+#define RT5616_PRE_SCLK_SFT 0
+#define RT5616_PRE_SCLK_512 (0x0)
+#define RT5616_PRE_SCLK_1024 (0x1)
+#define RT5616_PRE_SCLK_2048 (0x2)
+
+/* PLL tracking mode 3 (0x85) */
+#define RT5616_I2S1_RATE_MASK (0xf << 12)
+#define RT5616_I2S1_RATE_SFT 12
+#define RT5616_I2S2_RATE_MASK (0xf << 8)
+#define RT5616_I2S2_RATE_SFT 8
+#define RT5616_G_ASRC_LP_MASK (0x1 << 3)
+#define RT5616_G_ASRC_LP_SFT 3
+#define RT5616_ASRC_LP_F_M (0x1 << 2)
+#define RT5616_ASRC_LP_F_SFT 2
+#define RT5616_ASRC_LP_F_NOR (0x0 << 2)
+#define RT5616_ASRC_LP_F_SB (0x1 << 2)
+#define RT5616_FTK_PH_DET_MASK (0x3)
+#define RT5616_FTK_PH_DET_SFT 0
+#define RT5616_FTK_PH_DET_DIV1 (0x0)
+#define RT5616_FTK_PH_DET_DIV2 (0x1)
+#define RT5616_FTK_PH_DET_DIV4 (0x2)
+#define RT5616_FTK_PH_DET_DIV8 (0x3)
+
+/*PLL tracking mode 6 (0x89) */
+#define RT5616_I2S1_PD_MASK (0x7 << 12)
+#define RT5616_I2S1_PD_SFT 12
+#define RT5616_I2S2_PD_MASK (0x7 << 8)
+#define RT5616_I2S2_PD_SFT 8
+
+/*PLL tracking mode 7 (0x8a) */
+#define RT5616_FSI1_RATE_MASK (0xf << 12)
+#define RT5616_FSI1_RATE_SFT 12
+#define RT5616_FSI2_RATE_MASK (0xf << 8)
+#define RT5616_FSI2_RATE_SFT 8
+
+/* HPOUT Over Current Detection (0x8b) */
+#define RT5616_HP_OVCD_MASK (0x1 << 10)
+#define RT5616_HP_OVCD_SFT 10
+#define RT5616_HP_OVCD_DIS (0x0 << 10)
+#define RT5616_HP_OVCD_EN (0x1 << 10)
+#define RT5616_HP_OC_TH_MASK (0x3 << 8)
+#define RT5616_HP_OC_TH_SFT 8
+#define RT5616_HP_OC_TH_90 (0x0 << 8)
+#define RT5616_HP_OC_TH_105 (0x1 << 8)
+#define RT5616_HP_OC_TH_120 (0x2 << 8)
+#define RT5616_HP_OC_TH_135 (0x3 << 8)
+
+/* Depop Mode Control 1 (0x8e) */
+#define RT5616_SMT_TRIG_MASK (0x1 << 15)
+#define RT5616_SMT_TRIG_SFT 15
+#define RT5616_SMT_TRIG_DIS (0x0 << 15)
+#define RT5616_SMT_TRIG_EN (0x1 << 15)
+#define RT5616_HP_L_SMT_MASK (0x1 << 9)
+#define RT5616_HP_L_SMT_SFT 9
+#define RT5616_HP_L_SMT_DIS (0x0 << 9)
+#define RT5616_HP_L_SMT_EN (0x1 << 9)
+#define RT5616_HP_R_SMT_MASK (0x1 << 8)
+#define RT5616_HP_R_SMT_SFT 8
+#define RT5616_HP_R_SMT_DIS (0x0 << 8)
+#define RT5616_HP_R_SMT_EN (0x1 << 8)
+#define RT5616_HP_CD_PD_MASK (0x1 << 7)
+#define RT5616_HP_CD_PD_SFT 7
+#define RT5616_HP_CD_PD_DIS (0x0 << 7)
+#define RT5616_HP_CD_PD_EN (0x1 << 7)
+#define RT5616_RSTN_MASK (0x1 << 6)
+#define RT5616_RSTN_SFT 6
+#define RT5616_RSTN_DIS (0x0 << 6)
+#define RT5616_RSTN_EN (0x1 << 6)
+#define RT5616_RSTP_MASK (0x1 << 5)
+#define RT5616_RSTP_SFT 5
+#define RT5616_RSTP_DIS (0x0 << 5)
+#define RT5616_RSTP_EN (0x1 << 5)
+#define RT5616_HP_CO_MASK (0x1 << 4)
+#define RT5616_HP_CO_SFT 4
+#define RT5616_HP_CO_DIS (0x0 << 4)
+#define RT5616_HP_CO_EN (0x1 << 4)
+#define RT5616_HP_CP_MASK (0x1 << 3)
+#define RT5616_HP_CP_SFT 3
+#define RT5616_HP_CP_PD (0x0 << 3)
+#define RT5616_HP_CP_PU (0x1 << 3)
+#define RT5616_HP_SG_MASK (0x1 << 2)
+#define RT5616_HP_SG_SFT 2
+#define RT5616_HP_SG_DIS (0x0 << 2)
+#define RT5616_HP_SG_EN (0x1 << 2)
+#define RT5616_HP_DP_MASK (0x1 << 1)
+#define RT5616_HP_DP_SFT 1
+#define RT5616_HP_DP_PD (0x0 << 1)
+#define RT5616_HP_DP_PU (0x1 << 1)
+#define RT5616_HP_CB_MASK (0x1)
+#define RT5616_HP_CB_SFT 0
+#define RT5616_HP_CB_PD (0x0)
+#define RT5616_HP_CB_PU (0x1)
+
+/* Depop Mode Control 2 (0x8f) */
+#define RT5616_DEPOP_MASK (0x1 << 13)
+#define RT5616_DEPOP_SFT 13
+#define RT5616_DEPOP_AUTO (0x0 << 13)
+#define RT5616_DEPOP_MAN (0x1 << 13)
+#define RT5616_RAMP_MASK (0x1 << 12)
+#define RT5616_RAMP_SFT 12
+#define RT5616_RAMP_DIS (0x0 << 12)
+#define RT5616_RAMP_EN (0x1 << 12)
+#define RT5616_BPS_MASK (0x1 << 11)
+#define RT5616_BPS_SFT 11
+#define RT5616_BPS_DIS (0x0 << 11)
+#define RT5616_BPS_EN (0x1 << 11)
+#define RT5616_FAST_UPDN_MASK (0x1 << 10)
+#define RT5616_FAST_UPDN_SFT 10
+#define RT5616_FAST_UPDN_DIS (0x0 << 10)
+#define RT5616_FAST_UPDN_EN (0x1 << 10)
+#define RT5616_MRES_MASK (0x3 << 8)
+#define RT5616_MRES_SFT 8
+#define RT5616_MRES_15MO (0x0 << 8)
+#define RT5616_MRES_25MO (0x1 << 8)
+#define RT5616_MRES_35MO (0x2 << 8)
+#define RT5616_MRES_45MO (0x3 << 8)
+#define RT5616_VLO_MASK (0x1 << 7)
+#define RT5616_VLO_SFT 7
+#define RT5616_VLO_3V (0x0 << 7)
+#define RT5616_VLO_32V (0x1 << 7)
+#define RT5616_DIG_DP_MASK (0x1 << 6)
+#define RT5616_DIG_DP_SFT 6
+#define RT5616_DIG_DP_DIS (0x0 << 6)
+#define RT5616_DIG_DP_EN (0x1 << 6)
+#define RT5616_DP_TH_MASK (0x3 << 4)
+#define RT5616_DP_TH_SFT 4
+
+/* Depop Mode Control 3 (0x90) */
+#define RT5616_CP_SYS_MASK (0x7 << 12)
+#define RT5616_CP_SYS_SFT 12
+#define RT5616_CP_FQ1_MASK (0x7 << 8)
+#define RT5616_CP_FQ1_SFT 8
+#define RT5616_CP_FQ2_MASK (0x7 << 4)
+#define RT5616_CP_FQ2_SFT 4
+#define RT5616_CP_FQ3_MASK (0x7)
+#define RT5616_CP_FQ3_SFT 0
+#define RT5616_CP_FQ_1_5_KHZ 0
+#define RT5616_CP_FQ_3_KHZ 1
+#define RT5616_CP_FQ_6_KHZ 2
+#define RT5616_CP_FQ_12_KHZ 3
+#define RT5616_CP_FQ_24_KHZ 4
+#define RT5616_CP_FQ_48_KHZ 5
+#define RT5616_CP_FQ_96_KHZ 6
+#define RT5616_CP_FQ_192_KHZ 7
+
+/* HPOUT charge pump (0x91) */
+#define RT5616_OSW_L_MASK (0x1 << 11)
+#define RT5616_OSW_L_SFT 11
+#define RT5616_OSW_L_DIS (0x0 << 11)
+#define RT5616_OSW_L_EN (0x1 << 11)
+#define RT5616_OSW_R_MASK (0x1 << 10)
+#define RT5616_OSW_R_SFT 10
+#define RT5616_OSW_R_DIS (0x0 << 10)
+#define RT5616_OSW_R_EN (0x1 << 10)
+#define RT5616_PM_HP_MASK (0x3 << 8)
+#define RT5616_PM_HP_SFT 8
+#define RT5616_PM_HP_LV (0x0 << 8)
+#define RT5616_PM_HP_MV (0x1 << 8)
+#define RT5616_PM_HP_HV (0x2 << 8)
+#define RT5616_IB_HP_MASK (0x3 << 6)
+#define RT5616_IB_HP_SFT 6
+#define RT5616_IB_HP_125IL (0x0 << 6)
+#define RT5616_IB_HP_25IL (0x1 << 6)
+#define RT5616_IB_HP_5IL (0x2 << 6)
+#define RT5616_IB_HP_1IL (0x3 << 6)
+
+/* Micbias Control (0x93) */
+#define RT5616_MIC1_BS_MASK (0x1 << 15)
+#define RT5616_MIC1_BS_SFT 15
+#define RT5616_MIC1_BS_9AV (0x0 << 15)
+#define RT5616_MIC1_BS_75AV (0x1 << 15)
+#define RT5616_MIC1_CLK_MASK (0x1 << 13)
+#define RT5616_MIC1_CLK_SFT 13
+#define RT5616_MIC1_CLK_DIS (0x0 << 13)
+#define RT5616_MIC1_CLK_EN (0x1 << 13)
+#define RT5616_MIC1_OVCD_MASK (0x1 << 11)
+#define RT5616_MIC1_OVCD_SFT 11
+#define RT5616_MIC1_OVCD_DIS (0x0 << 11)
+#define RT5616_MIC1_OVCD_EN (0x1 << 11)
+#define RT5616_MIC1_OVTH_MASK (0x3 << 9)
+#define RT5616_MIC1_OVTH_SFT 9
+#define RT5616_MIC1_OVTH_600UA (0x0 << 9)
+#define RT5616_MIC1_OVTH_1500UA (0x1 << 9)
+#define RT5616_MIC1_OVTH_2000UA (0x2 << 9)
+#define RT5616_PWR_MB_MASK (0x1 << 5)
+#define RT5616_PWR_MB_SFT 5
+#define RT5616_PWR_MB_PD (0x0 << 5)
+#define RT5616_PWR_MB_PU (0x1 << 5)
+#define RT5616_PWR_CLK12M_MASK (0x1 << 4)
+#define RT5616_PWR_CLK12M_SFT 4
+#define RT5616_PWR_CLK12M_PD (0x0 << 4)
+#define RT5616_PWR_CLK12M_PU (0x1 << 4)
+
+/* Analog JD Control 1 (0x94) */
+#define RT5616_JD2_CMP_MASK (0x7 << 12)
+#define RT5616_JD2_CMP_SFT 12
+#define RT5616_JD_PU (0x1 << 11)
+#define RT5616_JD_PU_SFT 11
+#define RT5616_JD_PD (0x1 << 10)
+#define RT5616_JD_PD_SFT 10
+#define RT5616_JD_MODE_SEL_MASK (0x3 << 8)
+#define RT5616_JD_MODE_SEL_SFT 8
+#define RT5616_JD_MODE_SEL_M0 (0x0 << 8)
+#define RT5616_JD_MODE_SEL_M1 (0x1 << 8)
+#define RT5616_JD_MODE_SEL_M2 (0x2 << 8)
+#define RT5616_JD_M_CMP (0x7 << 4)
+#define RT5616_JD_M_CMP_SFT 4
+#define RT5616_JD_M_PU (0x1 << 3)
+#define RT5616_JD_M_PU_SFT 3
+#define RT5616_JD_M_PD (0x1 << 2)
+#define RT5616_JD_M_PD_SFT 2
+#define RT5616_JD_M_MODE_SEL_MASK (0x3)
+#define RT5616_JD_M_MODE_SEL_SFT 0
+#define RT5616_JD_M_MODE_SEL_M0 (0x0)
+#define RT5616_JD_M_MODE_SEL_M1 (0x1)
+#define RT5616_JD_M_MODE_SEL_M2 (0x2)
+
+/* Analog JD Control 2 (0x95) */
+#define RT5616_JD3_CMP_MASK (0x7 << 12)
+#define RT5616_JD3_CMP_SFT 12
+
+/* EQ Control 1 (0xb0) */
+#define RT5616_EQ_SRC_MASK (0x1 << 15)
+#define RT5616_EQ_SRC_SFT 15
+#define RT5616_EQ_SRC_DAC (0x0 << 15)
+#define RT5616_EQ_SRC_ADC (0x1 << 15)
+#define RT5616_EQ_UPD (0x1 << 14)
+#define RT5616_EQ_UPD_BIT 14
+#define RT5616_EQ_CD_MASK (0x1 << 13)
+#define RT5616_EQ_CD_SFT 13
+#define RT5616_EQ_CD_DIS (0x0 << 13)
+#define RT5616_EQ_CD_EN (0x1 << 13)
+#define RT5616_EQ_DITH_MASK (0x3 << 8)
+#define RT5616_EQ_DITH_SFT 8
+#define RT5616_EQ_DITH_NOR (0x0 << 8)
+#define RT5616_EQ_DITH_LSB (0x1 << 8)
+#define RT5616_EQ_DITH_LSB_1 (0x2 << 8)
+#define RT5616_EQ_DITH_LSB_2 (0x3 << 8)
+#define RT5616_EQ_CD_F (0x1 << 7)
+#define RT5616_EQ_CD_F_BIT 7
+#define RT5616_EQ_STA_HP2 (0x1 << 6)
+#define RT5616_EQ_STA_HP2_BIT 6
+#define RT5616_EQ_STA_HP1 (0x1 << 5)
+#define RT5616_EQ_STA_HP1_BIT 5
+#define RT5616_EQ_STA_BP4 (0x1 << 4)
+#define RT5616_EQ_STA_BP4_BIT 4
+#define RT5616_EQ_STA_BP3 (0x1 << 3)
+#define RT5616_EQ_STA_BP3_BIT 3
+#define RT5616_EQ_STA_BP2 (0x1 << 2)
+#define RT5616_EQ_STA_BP2_BIT 2
+#define RT5616_EQ_STA_BP1 (0x1 << 1)
+#define RT5616_EQ_STA_BP1_BIT 1
+#define RT5616_EQ_STA_LP (0x1)
+#define RT5616_EQ_STA_LP_BIT 0
+
+/* EQ Control 2 (0xb1) */
+#define RT5616_EQ_HPF1_M_MASK (0x1 << 8)
+#define RT5616_EQ_HPF1_M_SFT 8
+#define RT5616_EQ_HPF1_M_HI (0x0 << 8)
+#define RT5616_EQ_HPF1_M_1ST (0x1 << 8)
+#define RT5616_EQ_LPF1_M_MASK (0x1 << 7)
+#define RT5616_EQ_LPF1_M_SFT 7
+#define RT5616_EQ_LPF1_M_LO (0x0 << 7)
+#define RT5616_EQ_LPF1_M_1ST (0x1 << 7)
+#define RT5616_EQ_HPF2_MASK (0x1 << 6)
+#define RT5616_EQ_HPF2_SFT 6
+#define RT5616_EQ_HPF2_DIS (0x0 << 6)
+#define RT5616_EQ_HPF2_EN (0x1 << 6)
+#define RT5616_EQ_HPF1_MASK (0x1 << 5)
+#define RT5616_EQ_HPF1_SFT 5
+#define RT5616_EQ_HPF1_DIS (0x0 << 5)
+#define RT5616_EQ_HPF1_EN (0x1 << 5)
+#define RT5616_EQ_BPF4_MASK (0x1 << 4)
+#define RT5616_EQ_BPF4_SFT 4
+#define RT5616_EQ_BPF4_DIS (0x0 << 4)
+#define RT5616_EQ_BPF4_EN (0x1 << 4)
+#define RT5616_EQ_BPF3_MASK (0x1 << 3)
+#define RT5616_EQ_BPF3_SFT 3
+#define RT5616_EQ_BPF3_DIS (0x0 << 3)
+#define RT5616_EQ_BPF3_EN (0x1 << 3)
+#define RT5616_EQ_BPF2_MASK (0x1 << 2)
+#define RT5616_EQ_BPF2_SFT 2
+#define RT5616_EQ_BPF2_DIS (0x0 << 2)
+#define RT5616_EQ_BPF2_EN (0x1 << 2)
+#define RT5616_EQ_BPF1_MASK (0x1 << 1)
+#define RT5616_EQ_BPF1_SFT 1
+#define RT5616_EQ_BPF1_DIS (0x0 << 1)
+#define RT5616_EQ_BPF1_EN (0x1 << 1)
+#define RT5616_EQ_LPF_MASK (0x1)
+#define RT5616_EQ_LPF_SFT 0
+#define RT5616_EQ_LPF_DIS (0x0)
+#define RT5616_EQ_LPF_EN (0x1)
+#define RT5616_EQ_CTRL_MASK (0x7f)
+
+/* Memory Test (0xb2) */
+#define RT5616_MT_MASK (0x1 << 15)
+#define RT5616_MT_SFT 15
+#define RT5616_MT_DIS (0x0 << 15)
+#define RT5616_MT_EN (0x1 << 15)
+
+/* DRC/AGC Control 1 (0xb4) */
+#define RT5616_DRC_AGC_P_MASK (0x1 << 15)
+#define RT5616_DRC_AGC_P_SFT 15
+#define RT5616_DRC_AGC_P_DAC (0x0 << 15)
+#define RT5616_DRC_AGC_P_ADC (0x1 << 15)
+#define RT5616_DRC_AGC_MASK (0x1 << 14)
+#define RT5616_DRC_AGC_SFT 14
+#define RT5616_DRC_AGC_DIS (0x0 << 14)
+#define RT5616_DRC_AGC_EN (0x1 << 14)
+#define RT5616_DRC_AGC_UPD (0x1 << 13)
+#define RT5616_DRC_AGC_UPD_BIT 13
+#define RT5616_DRC_AGC_AR_MASK (0x1f << 8)
+#define RT5616_DRC_AGC_AR_SFT 8
+#define RT5616_DRC_AGC_R_MASK (0x7 << 5)
+#define RT5616_DRC_AGC_R_SFT 5
+#define RT5616_DRC_AGC_R_48K (0x1 << 5)
+#define RT5616_DRC_AGC_R_96K (0x2 << 5)
+#define RT5616_DRC_AGC_R_192K (0x3 << 5)
+#define RT5616_DRC_AGC_R_441K (0x5 << 5)
+#define RT5616_DRC_AGC_R_882K (0x6 << 5)
+#define RT5616_DRC_AGC_R_1764K (0x7 << 5)
+#define RT5616_DRC_AGC_RC_MASK (0x1f)
+#define RT5616_DRC_AGC_RC_SFT 0
+
+/* DRC/AGC Control 2 (0xb5) */
+#define RT5616_DRC_AGC_POB_MASK (0x3f << 8)
+#define RT5616_DRC_AGC_POB_SFT 8
+#define RT5616_DRC_AGC_CP_MASK (0x1 << 7)
+#define RT5616_DRC_AGC_CP_SFT 7
+#define RT5616_DRC_AGC_CP_DIS (0x0 << 7)
+#define RT5616_DRC_AGC_CP_EN (0x1 << 7)
+#define RT5616_DRC_AGC_CPR_MASK (0x3 << 5)
+#define RT5616_DRC_AGC_CPR_SFT 5
+#define RT5616_DRC_AGC_CPR_1_1 (0x0 << 5)
+#define RT5616_DRC_AGC_CPR_1_2 (0x1 << 5)
+#define RT5616_DRC_AGC_CPR_1_3 (0x2 << 5)
+#define RT5616_DRC_AGC_CPR_1_4 (0x3 << 5)
+#define RT5616_DRC_AGC_PRB_MASK (0x1f)
+#define RT5616_DRC_AGC_PRB_SFT 0
+
+/* DRC/AGC Control 3 (0xb6) */
+#define RT5616_DRC_AGC_NGB_MASK (0xf << 12)
+#define RT5616_DRC_AGC_NGB_SFT 12
+#define RT5616_DRC_AGC_TAR_MASK (0x1f << 7)
+#define RT5616_DRC_AGC_TAR_SFT 7
+#define RT5616_DRC_AGC_NG_MASK (0x1 << 6)
+#define RT5616_DRC_AGC_NG_SFT 6
+#define RT5616_DRC_AGC_NG_DIS (0x0 << 6)
+#define RT5616_DRC_AGC_NG_EN (0x1 << 6)
+#define RT5616_DRC_AGC_NGH_MASK (0x1 << 5)
+#define RT5616_DRC_AGC_NGH_SFT 5
+#define RT5616_DRC_AGC_NGH_DIS (0x0 << 5)
+#define RT5616_DRC_AGC_NGH_EN (0x1 << 5)
+#define RT5616_DRC_AGC_NGT_MASK (0x1f)
+#define RT5616_DRC_AGC_NGT_SFT 0
+
+/* Jack Detect Control 1 (0xbb) */
+#define RT5616_JD_MASK (0x7 << 13)
+#define RT5616_JD_SFT 13
+#define RT5616_JD_DIS (0x0 << 13)
+#define RT5616_JD_GPIO1 (0x1 << 13)
+#define RT5616_JD_GPIO2 (0x2 << 13)
+#define RT5616_JD_GPIO3 (0x3 << 13)
+#define RT5616_JD_GPIO4 (0x4 << 13)
+#define RT5616_JD_GPIO5 (0x5 << 13)
+#define RT5616_JD_GPIO6 (0x6 << 13)
+#define RT5616_JD_HP_MASK (0x1 << 11)
+#define RT5616_JD_HP_SFT 11
+#define RT5616_JD_HP_DIS (0x0 << 11)
+#define RT5616_JD_HP_EN (0x1 << 11)
+#define RT5616_JD_HP_TRG_MASK (0x1 << 10)
+#define RT5616_JD_HP_TRG_SFT 10
+#define RT5616_JD_HP_TRG_LO (0x0 << 10)
+#define RT5616_JD_HP_TRG_HI (0x1 << 10)
+#define RT5616_JD_SPL_MASK (0x1 << 9)
+#define RT5616_JD_SPL_SFT 9
+#define RT5616_JD_SPL_DIS (0x0 << 9)
+#define RT5616_JD_SPL_EN (0x1 << 9)
+#define RT5616_JD_SPL_TRG_MASK (0x1 << 8)
+#define RT5616_JD_SPL_TRG_SFT 8
+#define RT5616_JD_SPL_TRG_LO (0x0 << 8)
+#define RT5616_JD_SPL_TRG_HI (0x1 << 8)
+#define RT5616_JD_SPR_MASK (0x1 << 7)
+#define RT5616_JD_SPR_SFT 7
+#define RT5616_JD_SPR_DIS (0x0 << 7)
+#define RT5616_JD_SPR_EN (0x1 << 7)
+#define RT5616_JD_SPR_TRG_MASK (0x1 << 6)
+#define RT5616_JD_SPR_TRG_SFT 6
+#define RT5616_JD_SPR_TRG_LO (0x0 << 6)
+#define RT5616_JD_SPR_TRG_HI (0x1 << 6)
+#define RT5616_JD_LO_MASK (0x1 << 3)
+#define RT5616_JD_LO_SFT 3
+#define RT5616_JD_LO_DIS (0x0 << 3)
+#define RT5616_JD_LO_EN (0x1 << 3)
+#define RT5616_JD_LO_TRG_MASK (0x1 << 2)
+#define RT5616_JD_LO_TRG_SFT 2
+#define RT5616_JD_LO_TRG_LO (0x0 << 2)
+#define RT5616_JD_LO_TRG_HI (0x1 << 2)
+
+/* Jack Detect Control 2 (0xbc) */
+#define RT5616_JD_TRG_SEL_MASK (0x7 << 9)
+#define RT5616_JD_TRG_SEL_SFT 9
+#define RT5616_JD_TRG_SEL_GPIO (0x0 << 9)
+#define RT5616_JD_TRG_SEL_JD1_1 (0x1 << 9)
+#define RT5616_JD_TRG_SEL_JD1_2 (0x2 << 9)
+#define RT5616_JD_TRG_SEL_JD2 (0x3 << 9)
+#define RT5616_JD_TRG_SEL_JD3 (0x4 << 9)
+#define RT5616_JD3_IRQ_EN (0x1 << 8)
+#define RT5616_JD3_IRQ_EN_SFT 8
+#define RT5616_JD3_EN_STKY (0x1 << 7)
+#define RT5616_JD3_EN_STKY_SFT 7
+#define RT5616_JD3_INV (0x1 << 6)
+#define RT5616_JD3_INV_SFT 6
+
+/* IRQ Control 1 (0xbd) */
+#define RT5616_IRQ_JD_MASK (0x1 << 15)
+#define RT5616_IRQ_JD_SFT 15
+#define RT5616_IRQ_JD_BP (0x0 << 15)
+#define RT5616_IRQ_JD_NOR (0x1 << 15)
+#define RT5616_JD_STKY_MASK (0x1 << 13)
+#define RT5616_JD_STKY_SFT 13
+#define RT5616_JD_STKY_DIS (0x0 << 13)
+#define RT5616_JD_STKY_EN (0x1 << 13)
+#define RT5616_JD_P_MASK (0x1 << 11)
+#define RT5616_JD_P_SFT 11
+#define RT5616_JD_P_NOR (0x0 << 11)
+#define RT5616_JD_P_INV (0x1 << 11)
+#define RT5616_JD1_1_IRQ_EN (0x1 << 9)
+#define RT5616_JD1_1_IRQ_EN_SFT 9
+#define RT5616_JD1_1_EN_STKY (0x1 << 8)
+#define RT5616_JD1_1_EN_STKY_SFT 8
+#define RT5616_JD1_1_INV (0x1 << 7)
+#define RT5616_JD1_1_INV_SFT 7
+#define RT5616_JD1_2_IRQ_EN (0x1 << 6)
+#define RT5616_JD1_2_IRQ_EN_SFT 6
+#define RT5616_JD1_2_EN_STKY (0x1 << 5)
+#define RT5616_JD1_2_EN_STKY_SFT 5
+#define RT5616_JD1_2_INV (0x1 << 4)
+#define RT5616_JD1_2_INV_SFT 4
+#define RT5616_JD2_IRQ_EN (0x1 << 3)
+#define RT5616_JD2_IRQ_EN_SFT 3
+#define RT5616_JD2_EN_STKY (0x1 << 2)
+#define RT5616_JD2_EN_STKY_SFT 2
+#define RT5616_JD2_INV (0x1 << 1)
+#define RT5616_JD2_INV_SFT 1
+
+/* IRQ Control 2 (0xbe) */
+#define RT5616_IRQ_MB1_OC_MASK (0x1 << 15)
+#define RT5616_IRQ_MB1_OC_SFT 15
+#define RT5616_IRQ_MB1_OC_BP (0x0 << 15)
+#define RT5616_IRQ_MB1_OC_NOR (0x1 << 15)
+#define RT5616_MB1_OC_STKY_MASK (0x1 << 11)
+#define RT5616_MB1_OC_STKY_SFT 11
+#define RT5616_MB1_OC_STKY_DIS (0x0 << 11)
+#define RT5616_MB1_OC_STKY_EN (0x1 << 11)
+#define RT5616_MB1_OC_P_MASK (0x1 << 7)
+#define RT5616_MB1_OC_P_SFT 7
+#define RT5616_MB1_OC_P_NOR (0x0 << 7)
+#define RT5616_MB1_OC_P_INV (0x1 << 7)
+#define RT5616_MB2_OC_P_MASK (0x1 << 6)
+#define RT5616_MB1_OC_CLR (0x1 << 3)
+#define RT5616_MB1_OC_CLR_SFT 3
+#define RT5616_STA_GPIO8 (0x1)
+#define RT5616_STA_GPIO8_BIT 0
+
+/* Internal Status and GPIO status (0xbf) */
+#define RT5616_STA_JD3 (0x1 << 15)
+#define RT5616_STA_JD3_BIT 15
+#define RT5616_STA_JD2 (0x1 << 14)
+#define RT5616_STA_JD2_BIT 14
+#define RT5616_STA_JD1_2 (0x1 << 13)
+#define RT5616_STA_JD1_2_BIT 13
+#define RT5616_STA_JD1_1 (0x1 << 12)
+#define RT5616_STA_JD1_1_BIT 12
+#define RT5616_STA_GP7 (0x1 << 11)
+#define RT5616_STA_GP7_BIT 11
+#define RT5616_STA_GP6 (0x1 << 10)
+#define RT5616_STA_GP6_BIT 10
+#define RT5616_STA_GP5 (0x1 << 9)
+#define RT5616_STA_GP5_BIT 9
+#define RT5616_STA_GP1 (0x1 << 8)
+#define RT5616_STA_GP1_BIT 8
+#define RT5616_STA_GP2 (0x1 << 7)
+#define RT5616_STA_GP2_BIT 7
+#define RT5616_STA_GP3 (0x1 << 6)
+#define RT5616_STA_GP3_BIT 6
+#define RT5616_STA_GP4 (0x1 << 5)
+#define RT5616_STA_GP4_BIT 5
+#define RT5616_STA_GP_JD (0x1 << 4)
+#define RT5616_STA_GP_JD_BIT 4
+
+/* GPIO Control 1 (0xc0) */
+#define RT5616_GP1_PIN_MASK (0x1 << 15)
+#define RT5616_GP1_PIN_SFT 15
+#define RT5616_GP1_PIN_GPIO1 (0x0 << 15)
+#define RT5616_GP1_PIN_IRQ (0x1 << 15)
+#define RT5616_GP2_PIN_MASK (0x1 << 14)
+#define RT5616_GP2_PIN_SFT 14
+#define RT5616_GP2_PIN_GPIO2 (0x0 << 14)
+#define RT5616_GP2_PIN_DMIC1_SCL (0x1 << 14)
+#define RT5616_GPIO_M_MASK (0x1 << 9)
+#define RT5616_GPIO_M_SFT 9
+#define RT5616_GPIO_M_FLT (0x0 << 9)
+#define RT5616_GPIO_M_PH (0x1 << 9)
+#define RT5616_I2S2_SEL_MASK (0x1 << 8)
+#define RT5616_I2S2_SEL_SFT 8
+#define RT5616_I2S2_SEL_I2S (0x0 << 8)
+#define RT5616_I2S2_SEL_GPIO (0x1 << 8)
+#define RT5616_GP5_PIN_MASK (0x1 << 7)
+#define RT5616_GP5_PIN_SFT 7
+#define RT5616_GP5_PIN_GPIO5 (0x0 << 7)
+#define RT5616_GP5_PIN_IRQ (0x1 << 7)
+#define RT5616_GP6_PIN_MASK (0x1 << 6)
+#define RT5616_GP6_PIN_SFT 6
+#define RT5616_GP6_PIN_GPIO6 (0x0 << 6)
+#define RT5616_GP6_PIN_DMIC_SDA (0x1 << 6)
+#define RT5616_GP7_PIN_MASK (0x1 << 5)
+#define RT5616_GP7_PIN_SFT 5
+#define RT5616_GP7_PIN_GPIO7 (0x0 << 5)
+#define RT5616_GP7_PIN_IRQ (0x1 << 5)
+#define RT5616_GP8_PIN_MASK (0x1 << 4)
+#define RT5616_GP8_PIN_SFT 4
+#define RT5616_GP8_PIN_GPIO8 (0x0 << 4)
+#define RT5616_GP8_PIN_DMIC_SDA (0x1 << 4)
+#define RT5616_GPIO_PDM_SEL_MASK (0x1 << 3)
+#define RT5616_GPIO_PDM_SEL_SFT 3
+#define RT5616_GPIO_PDM_SEL_GPIO (0x0 << 3)
+#define RT5616_GPIO_PDM_SEL_PDM (0x1 << 3)
+
+/* GPIO Control 2 (0xc1) */
+#define RT5616_GP5_DR_MASK (0x1 << 14)
+#define RT5616_GP5_DR_SFT 14
+#define RT5616_GP5_DR_IN (0x0 << 14)
+#define RT5616_GP5_DR_OUT (0x1 << 14)
+#define RT5616_GP5_OUT_MASK (0x1 << 13)
+#define RT5616_GP5_OUT_SFT 13
+#define RT5616_GP5_OUT_LO (0x0 << 13)
+#define RT5616_GP5_OUT_HI (0x1 << 13)
+#define RT5616_GP5_P_MASK (0x1 << 12)
+#define RT5616_GP5_P_SFT 12
+#define RT5616_GP5_P_NOR (0x0 << 12)
+#define RT5616_GP5_P_INV (0x1 << 12)
+#define RT5616_GP4_DR_MASK (0x1 << 11)
+#define RT5616_GP4_DR_SFT 11
+#define RT5616_GP4_DR_IN (0x0 << 11)
+#define RT5616_GP4_DR_OUT (0x1 << 11)
+#define RT5616_GP4_OUT_MASK (0x1 << 10)
+#define RT5616_GP4_OUT_SFT 10
+#define RT5616_GP4_OUT_LO (0x0 << 10)
+#define RT5616_GP4_OUT_HI (0x1 << 10)
+#define RT5616_GP4_P_MASK (0x1 << 9)
+#define RT5616_GP4_P_SFT 9
+#define RT5616_GP4_P_NOR (0x0 << 9)
+#define RT5616_GP4_P_INV (0x1 << 9)
+#define RT5616_GP3_DR_MASK (0x1 << 8)
+#define RT5616_GP3_DR_SFT 8
+#define RT5616_GP3_DR_IN (0x0 << 8)
+#define RT5616_GP3_DR_OUT (0x1 << 8)
+#define RT5616_GP3_OUT_MASK (0x1 << 7)
+#define RT5616_GP3_OUT_SFT 7
+#define RT5616_GP3_OUT_LO (0x0 << 7)
+#define RT5616_GP3_OUT_HI (0x1 << 7)
+#define RT5616_GP3_P_MASK (0x1 << 6)
+#define RT5616_GP3_P_SFT 6
+#define RT5616_GP3_P_NOR (0x0 << 6)
+#define RT5616_GP3_P_INV (0x1 << 6)
+#define RT5616_GP2_DR_MASK (0x1 << 5)
+#define RT5616_GP2_DR_SFT 5
+#define RT5616_GP2_DR_IN (0x0 << 5)
+#define RT5616_GP2_DR_OUT (0x1 << 5)
+#define RT5616_GP2_OUT_MASK (0x1 << 4)
+#define RT5616_GP2_OUT_SFT 4
+#define RT5616_GP2_OUT_LO (0x0 << 4)
+#define RT5616_GP2_OUT_HI (0x1 << 4)
+#define RT5616_GP2_P_MASK (0x1 << 3)
+#define RT5616_GP2_P_SFT 3
+#define RT5616_GP2_P_NOR (0x0 << 3)
+#define RT5616_GP2_P_INV (0x1 << 3)
+#define RT5616_GP1_DR_MASK (0x1 << 2)
+#define RT5616_GP1_DR_SFT 2
+#define RT5616_GP1_DR_IN (0x0 << 2)
+#define RT5616_GP1_DR_OUT (0x1 << 2)
+#define RT5616_GP1_OUT_MASK (0x1 << 1)
+#define RT5616_GP1_OUT_SFT 1
+#define RT5616_GP1_OUT_LO (0x0 << 1)
+#define RT5616_GP1_OUT_HI (0x1 << 1)
+#define RT5616_GP1_P_MASK (0x1)
+#define RT5616_GP1_P_SFT 0
+#define RT5616_GP1_P_NOR (0x0)
+#define RT5616_GP1_P_INV (0x1)
+
+/* GPIO Control 3 (0xc2) */
+#define RT5616_GP8_DR_MASK (0x1 << 8)
+#define RT5616_GP8_DR_SFT 8
+#define RT5616_GP8_DR_IN (0x0 << 8)
+#define RT5616_GP8_DR_OUT (0x1 << 8)
+#define RT5616_GP8_OUT_MASK (0x1 << 7)
+#define RT5616_GP8_OUT_SFT 7
+#define RT5616_GP8_OUT_LO (0x0 << 7)
+#define RT5616_GP8_OUT_HI (0x1 << 7)
+#define RT5616_GP8_P_MASK (0x1 << 6)
+#define RT5616_GP8_P_SFT 6
+#define RT5616_GP8_P_NOR (0x0 << 6)
+#define RT5616_GP8_P_INV (0x1 << 6)
+#define RT5616_GP7_DR_MASK (0x1 << 5)
+#define RT5616_GP7_DR_SFT 5
+#define RT5616_GP7_DR_IN (0x0 << 5)
+#define RT5616_GP7_DR_OUT (0x1 << 5)
+#define RT5616_GP7_OUT_MASK (0x1 << 4)
+#define RT5616_GP7_OUT_SFT 4
+#define RT5616_GP7_OUT_LO (0x0 << 4)
+#define RT5616_GP7_OUT_HI (0x1 << 4)
+#define RT5616_GP7_P_MASK (0x1 << 3)
+#define RT5616_GP7_P_SFT 3
+#define RT5616_GP7_P_NOR (0x0 << 3)
+#define RT5616_GP7_P_INV (0x1 << 3)
+#define RT5616_GP6_DR_MASK (0x1 << 2)
+#define RT5616_GP6_DR_SFT 2
+#define RT5616_GP6_DR_IN (0x0 << 2)
+#define RT5616_GP6_DR_OUT (0x1 << 2)
+#define RT5616_GP6_OUT_MASK (0x1 << 1)
+#define RT5616_GP6_OUT_SFT 1
+#define RT5616_GP6_OUT_LO (0x0 << 1)
+#define RT5616_GP6_OUT_HI (0x1 << 1)
+#define RT5616_GP6_P_MASK (0x1)
+#define RT5616_GP6_P_SFT 0
+#define RT5616_GP6_P_NOR (0x0)
+#define RT5616_GP6_P_INV (0x1)
+
+/* Scramble Control (0xce) */
+#define RT5616_SCB_SWAP_MASK (0x1 << 15)
+#define RT5616_SCB_SWAP_SFT 15
+#define RT5616_SCB_SWAP_DIS (0x0 << 15)
+#define RT5616_SCB_SWAP_EN (0x1 << 15)
+#define RT5616_SCB_MASK (0x1 << 14)
+#define RT5616_SCB_SFT 14
+#define RT5616_SCB_DIS (0x0 << 14)
+#define RT5616_SCB_EN (0x1 << 14)
+
+/* Baseback Control (0xcf) */
+#define RT5616_BB_MASK (0x1 << 15)
+#define RT5616_BB_SFT 15
+#define RT5616_BB_DIS (0x0 << 15)
+#define RT5616_BB_EN (0x1 << 15)
+#define RT5616_BB_CT_MASK (0x7 << 12)
+#define RT5616_BB_CT_SFT 12
+#define RT5616_BB_CT_A (0x0 << 12)
+#define RT5616_BB_CT_B (0x1 << 12)
+#define RT5616_BB_CT_C (0x2 << 12)
+#define RT5616_BB_CT_D (0x3 << 12)
+#define RT5616_M_BB_L_MASK (0x1 << 9)
+#define RT5616_M_BB_L_SFT 9
+#define RT5616_M_BB_R_MASK (0x1 << 8)
+#define RT5616_M_BB_R_SFT 8
+#define RT5616_M_BB_HPF_L_MASK (0x1 << 7)
+#define RT5616_M_BB_HPF_L_SFT 7
+#define RT5616_M_BB_HPF_R_MASK (0x1 << 6)
+#define RT5616_M_BB_HPF_R_SFT 6
+#define RT5616_G_BB_BST_MASK (0x3f)
+#define RT5616_G_BB_BST_SFT 0
+
+/* MP3 Plus Control 1 (0xd0) */
+#define RT5616_M_MP3_L_MASK (0x1 << 15)
+#define RT5616_M_MP3_L_SFT 15
+#define RT5616_M_MP3_R_MASK (0x1 << 14)
+#define RT5616_M_MP3_R_SFT 14
+#define RT5616_M_MP3_MASK (0x1 << 13)
+#define RT5616_M_MP3_SFT 13
+#define RT5616_M_MP3_DIS (0x0 << 13)
+#define RT5616_M_MP3_EN (0x1 << 13)
+#define RT5616_EG_MP3_MASK (0x1f << 8)
+#define RT5616_EG_MP3_SFT 8
+#define RT5616_MP3_HLP_MASK (0x1 << 7)
+#define RT5616_MP3_HLP_SFT 7
+#define RT5616_MP3_HLP_DIS (0x0 << 7)
+#define RT5616_MP3_HLP_EN (0x1 << 7)
+#define RT5616_M_MP3_ORG_L_MASK (0x1 << 6)
+#define RT5616_M_MP3_ORG_L_SFT 6
+#define RT5616_M_MP3_ORG_R_MASK (0x1 << 5)
+#define RT5616_M_MP3_ORG_R_SFT 5
+
+/* MP3 Plus Control 2 (0xd1) */
+#define RT5616_MP3_WT_MASK (0x1 << 13)
+#define RT5616_MP3_WT_SFT 13
+#define RT5616_MP3_WT_1_4 (0x0 << 13)
+#define RT5616_MP3_WT_1_2 (0x1 << 13)
+#define RT5616_OG_MP3_MASK (0x1f << 8)
+#define RT5616_OG_MP3_SFT 8
+#define RT5616_HG_MP3_MASK (0x3f)
+#define RT5616_HG_MP3_SFT 0
+
+/* 3D HP Control 1 (0xd2) */
+#define RT5616_3D_CF_MASK (0x1 << 15)
+#define RT5616_3D_CF_SFT 15
+#define RT5616_3D_CF_DIS (0x0 << 15)
+#define RT5616_3D_CF_EN (0x1 << 15)
+#define RT5616_3D_HP_MASK (0x1 << 14)
+#define RT5616_3D_HP_SFT 14
+#define RT5616_3D_HP_DIS (0x0 << 14)
+#define RT5616_3D_HP_EN (0x1 << 14)
+#define RT5616_3D_BT_MASK (0x1 << 13)
+#define RT5616_3D_BT_SFT 13
+#define RT5616_3D_BT_DIS (0x0 << 13)
+#define RT5616_3D_BT_EN (0x1 << 13)
+#define RT5616_3D_1F_MIX_MASK (0x3 << 11)
+#define RT5616_3D_1F_MIX_SFT 11
+#define RT5616_3D_HP_M_MASK (0x1 << 10)
+#define RT5616_3D_HP_M_SFT 10
+#define RT5616_3D_HP_M_SUR (0x0 << 10)
+#define RT5616_3D_HP_M_FRO (0x1 << 10)
+#define RT5616_M_3D_HRTF_MASK (0x1 << 9)
+#define RT5616_M_3D_HRTF_SFT 9
+#define RT5616_M_3D_D2H_MASK (0x1 << 8)
+#define RT5616_M_3D_D2H_SFT 8
+#define RT5616_M_3D_D2R_MASK (0x1 << 7)
+#define RT5616_M_3D_D2R_SFT 7
+#define RT5616_M_3D_REVB_MASK (0x1 << 6)
+#define RT5616_M_3D_REVB_SFT 6
+
+/* Adjustable high pass filter control 1 (0xd3) */
+#define RT5616_2ND_HPF_MASK (0x1 << 15)
+#define RT5616_2ND_HPF_SFT 15
+#define RT5616_2ND_HPF_DIS (0x0 << 15)
+#define RT5616_2ND_HPF_EN (0x1 << 15)
+#define RT5616_HPF_CF_L_MASK (0x7 << 12)
+#define RT5616_HPF_CF_L_SFT 12
+#define RT5616_HPF_CF_R_MASK (0x7 << 8)
+#define RT5616_HPF_CF_R_SFT 8
+#define RT5616_ZD_T_MASK (0x3 << 6)
+#define RT5616_ZD_T_SFT 6
+#define RT5616_ZD_F_MASK (0x3 << 4)
+#define RT5616_ZD_F_SFT 4
+#define RT5616_ZD_F_IM (0x0 << 4)
+#define RT5616_ZD_F_ZC_IM (0x1 << 4)
+#define RT5616_ZD_F_ZC_IOD (0x2 << 4)
+#define RT5616_ZD_F_UN (0x3 << 4)
+
+/* Adjustable high pass filter control 2 (0xd4) */
+#define RT5616_HPF_CF_L_NUM_MASK (0x3f << 8)
+#define RT5616_HPF_CF_L_NUM_SFT 8
+#define RT5616_HPF_CF_R_NUM_MASK (0x3f)
+#define RT5616_HPF_CF_R_NUM_SFT 0
+
+/* HP calibration control and Amp detection (0xd6) */
+#define RT5616_SI_DAC_MASK (0x1 << 11)
+#define RT5616_SI_DAC_SFT 11
+#define RT5616_SI_DAC_AUTO (0x0 << 11)
+#define RT5616_SI_DAC_TEST (0x1 << 11)
+#define RT5616_DC_CAL_M_MASK (0x1 << 10)
+#define RT5616_DC_CAL_M_SFT 10
+#define RT5616_DC_CAL_M_NOR (0x0 << 10)
+#define RT5616_DC_CAL_M_CAL (0x1 << 10)
+#define RT5616_DC_CAL_MASK (0x1 << 9)
+#define RT5616_DC_CAL_SFT 9
+#define RT5616_DC_CAL_DIS (0x0 << 9)
+#define RT5616_DC_CAL_EN (0x1 << 9)
+#define RT5616_HPD_RCV_MASK (0x7 << 6)
+#define RT5616_HPD_RCV_SFT 6
+#define RT5616_HPD_PS_MASK (0x1 << 5)
+#define RT5616_HPD_PS_SFT 5
+#define RT5616_HPD_PS_DIS (0x0 << 5)
+#define RT5616_HPD_PS_EN (0x1 << 5)
+#define RT5616_CAL_M_MASK (0x1 << 4)
+#define RT5616_CAL_M_SFT 4
+#define RT5616_CAL_M_DEP (0x0 << 4)
+#define RT5616_CAL_M_CAL (0x1 << 4)
+#define RT5616_CAL_MASK (0x1 << 3)
+#define RT5616_CAL_SFT 3
+#define RT5616_CAL_DIS (0x0 << 3)
+#define RT5616_CAL_EN (0x1 << 3)
+#define RT5616_CAL_TEST_MASK (0x1 << 2)
+#define RT5616_CAL_TEST_SFT 2
+#define RT5616_CAL_TEST_DIS (0x0 << 2)
+#define RT5616_CAL_TEST_EN (0x1 << 2)
+#define RT5616_CAL_P_MASK (0x3)
+#define RT5616_CAL_P_SFT 0
+#define RT5616_CAL_P_NONE (0x0)
+#define RT5616_CAL_P_CAL (0x1)
+#define RT5616_CAL_P_DAC_CAL (0x2)
+
+/* Soft volume and zero cross control 1 (0xd9) */
+#define RT5616_SV_MASK (0x1 << 15)
+#define RT5616_SV_SFT 15
+#define RT5616_SV_DIS (0x0 << 15)
+#define RT5616_SV_EN (0x1 << 15)
+#define RT5616_OUT_SV_MASK (0x1 << 13)
+#define RT5616_OUT_SV_SFT 13
+#define RT5616_OUT_SV_DIS (0x0 << 13)
+#define RT5616_OUT_SV_EN (0x1 << 13)
+#define RT5616_HP_SV_MASK (0x1 << 12)
+#define RT5616_HP_SV_SFT 12
+#define RT5616_HP_SV_DIS (0x0 << 12)
+#define RT5616_HP_SV_EN (0x1 << 12)
+#define RT5616_ZCD_DIG_MASK (0x1 << 11)
+#define RT5616_ZCD_DIG_SFT 11
+#define RT5616_ZCD_DIG_DIS (0x0 << 11)
+#define RT5616_ZCD_DIG_EN (0x1 << 11)
+#define RT5616_ZCD_MASK (0x1 << 10)
+#define RT5616_ZCD_SFT 10
+#define RT5616_ZCD_PD (0x0 << 10)
+#define RT5616_ZCD_PU (0x1 << 10)
+#define RT5616_M_ZCD_MASK (0x3f << 4)
+#define RT5616_M_ZCD_SFT 4
+#define RT5616_M_ZCD_OM_L (0x1 << 7)
+#define RT5616_M_ZCD_OM_R (0x1 << 6)
+#define RT5616_M_ZCD_RM_L (0x1 << 5)
+#define RT5616_M_ZCD_RM_R (0x1 << 4)
+#define RT5616_SV_DLY_MASK (0xf)
+#define RT5616_SV_DLY_SFT 0
+
+/* Soft volume and zero cross control 2 (0xda) */
+#define RT5616_ZCD_HP_MASK (0x1 << 15)
+#define RT5616_ZCD_HP_SFT 15
+#define RT5616_ZCD_HP_DIS (0x0 << 15)
+#define RT5616_ZCD_HP_EN (0x1 << 15)
+
+/* Digital Misc Control (0xfa) */
+#define RT5616_I2S2_MS_SP_MASK (0x1 << 8)
+#define RT5616_I2S2_MS_SP_SEL 8
+#define RT5616_I2S2_MS_SP_64 (0x0 << 8)
+#define RT5616_I2S2_MS_SP_50 (0x1 << 8)
+#define RT5616_CLK_DET_EN (0x1 << 3)
+#define RT5616_CLK_DET_EN_SFT 3
+#define RT5616_AMP_DET_EN (0x1 << 1)
+#define RT5616_AMP_DET_EN_SFT 1
+#define RT5616_D_GATE_EN (0x1)
+#define RT5616_D_GATE_EN_SFT 0
+
+/* Codec Private Register definition */
+/* 3D Speaker Control (0x63) */
+#define RT5616_3D_SPK_MASK (0x1 << 15)
+#define RT5616_3D_SPK_SFT 15
+#define RT5616_3D_SPK_DIS (0x0 << 15)
+#define RT5616_3D_SPK_EN (0x1 << 15)
+#define RT5616_3D_SPK_M_MASK (0x3 << 13)
+#define RT5616_3D_SPK_M_SFT 13
+#define RT5616_3D_SPK_CG_MASK (0x1f << 8)
+#define RT5616_3D_SPK_CG_SFT 8
+#define RT5616_3D_SPK_SG_MASK (0x1f)
+#define RT5616_3D_SPK_SG_SFT 0
+
+/* Wind Noise Detection Control 1 (0x6c) */
+#define RT5616_WND_MASK (0x1 << 15)
+#define RT5616_WND_SFT 15
+#define RT5616_WND_DIS (0x0 << 15)
+#define RT5616_WND_EN (0x1 << 15)
+
+/* Wind Noise Detection Control 2 (0x6d) */
+#define RT5616_WND_FC_NW_MASK (0x3f << 10)
+#define RT5616_WND_FC_NW_SFT 10
+#define RT5616_WND_FC_WK_MASK (0x3f << 4)
+#define RT5616_WND_FC_WK_SFT 4
+
+/* Wind Noise Detection Control 3 (0x6e) */
+#define RT5616_HPF_FC_MASK (0x3f << 6)
+#define RT5616_HPF_FC_SFT 6
+#define RT5616_WND_FC_ST_MASK (0x3f)
+#define RT5616_WND_FC_ST_SFT 0
+
+/* Wind Noise Detection Control 4 (0x6f) */
+#define RT5616_WND_TH_LO_MASK (0x3ff)
+#define RT5616_WND_TH_LO_SFT 0
+
+/* Wind Noise Detection Control 5 (0x70) */
+#define RT5616_WND_TH_HI_MASK (0x3ff)
+#define RT5616_WND_TH_HI_SFT 0
+
+/* Wind Noise Detection Control 8 (0x73) */
+#define RT5616_WND_WIND_MASK (0x1 << 13) /* Read-Only */
+#define RT5616_WND_WIND_SFT 13
+#define RT5616_WND_STRONG_MASK (0x1 << 12) /* Read-Only */
+#define RT5616_WND_STRONG_SFT 12
+enum {
+ RT5616_NO_WIND,
+ RT5616_BREEZE,
+ RT5616_STORM,
+};
+
+/* Dipole Speaker Interface (0x75) */
+#define RT5616_DP_ATT_MASK (0x3 << 14)
+#define RT5616_DP_ATT_SFT 14
+#define RT5616_DP_SPK_MASK (0x1 << 10)
+#define RT5616_DP_SPK_SFT 10
+#define RT5616_DP_SPK_DIS (0x0 << 10)
+#define RT5616_DP_SPK_EN (0x1 << 10)
+
+/* EQ Pre Volume Control (0xb3) */
+#define RT5616_EQ_PRE_VOL_MASK (0xffff)
+#define RT5616_EQ_PRE_VOL_SFT 0
+
+/* EQ Post Volume Control (0xb4) */
+#define RT5616_EQ_PST_VOL_MASK (0xffff)
+#define RT5616_EQ_PST_VOL_SFT 0
+
+/* System Clock Source */
+enum {
+ RT5616_SCLK_S_MCLK,
+ RT5616_SCLK_S_PLL1,
+};
+
+/* PLL1 Source */
+enum {
+ RT5616_PLL1_S_MCLK,
+ RT5616_PLL1_S_BCLK1,
+ RT5616_PLL1_S_BCLK2,
+};
+
+enum {
+ RT5616_AIF1,
+ RT5616_AIFS,
+};
+
+#endif /* __RT5616_H__ */
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index f2beb1aa5763..11d032cdc658 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -488,6 +488,18 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
return 0;
}
+static int is_using_asrc(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
+ struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+ if (!rt5640->asrc_en)
+ return 0;
+
+ return 1;
+}
+
/* Digital Mixer */
static const struct snd_kcontrol_new rt5640_sto_adc_l_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5640_STO_ADC_MIXER,
@@ -1059,6 +1071,20 @@ static int rt5640_hp_post_event(struct snd_soc_dapm_widget *w,
static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2,
RT5640_PWR_PLL_BIT, 0, NULL, 0),
+
+ /* ASRC */
+ SND_SOC_DAPM_SUPPLY_S("Stereo Filter ASRC", 1, RT5640_ASRC_1,
+ 15, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2S2 Filter ASRC", 1, RT5640_ASRC_1,
+ 12, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5640_ASRC_1,
+ 11, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DMIC1 ASRC", 1, RT5640_ASRC_1,
+ 9, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DMIC2 ASRC", 1, RT5640_ASRC_1,
+ 8, 0, NULL, 0),
+
+
/* Input Side */
/* micbias */
SND_SOC_DAPM_SUPPLY("LDO2", RT5640_PWR_ANLG1,
@@ -1319,6 +1345,12 @@ static const struct snd_soc_dapm_widget rt5639_specific_dapm_widgets[] = {
};
static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
+ { "I2S1", NULL, "Stereo Filter ASRC", is_using_asrc },
+ { "I2S2", NULL, "I2S2 ASRC", is_using_asrc },
+ { "I2S2", NULL, "I2S2 Filter ASRC", is_using_asrc },
+ { "DMIC1", NULL, "DMIC1 ASRC", is_using_asrc },
+ { "DMIC2", NULL, "DMIC2 ASRC", is_using_asrc },
+
{"IN1P", NULL, "LDO2"},
{"IN2P", NULL, "LDO2"},
{"IN3P", NULL, "LDO2"},
@@ -1981,6 +2013,76 @@ int rt5640_dmic_enable(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(rt5640_dmic_enable);
+int rt5640_sel_asrc_clk_src(struct snd_soc_codec *codec,
+ unsigned int filter_mask, unsigned int clk_src)
+{
+ struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+ unsigned int asrc2_mask = 0;
+ unsigned int asrc2_value = 0;
+
+ switch (clk_src) {
+ case RT5640_CLK_SEL_SYS:
+ case RT5640_CLK_SEL_ASRC:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (!filter_mask)
+ return -EINVAL;
+
+ if (filter_mask & RT5640_DA_STEREO_FILTER) {
+ asrc2_mask |= RT5640_STO_DAC_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_STO_DAC_M_MASK)
+ | (clk_src << RT5640_STO_DAC_M_SFT);
+ }
+
+ if (filter_mask & RT5640_DA_MONO_L_FILTER) {
+ asrc2_mask |= RT5640_MDA_L_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_MDA_L_M_MASK)
+ | (clk_src << RT5640_MDA_L_M_SFT);
+ }
+
+ if (filter_mask & RT5640_DA_MONO_R_FILTER) {
+ asrc2_mask |= RT5640_MDA_R_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_MDA_R_M_MASK)
+ | (clk_src << RT5640_MDA_R_M_SFT);
+ }
+
+ if (filter_mask & RT5640_AD_STEREO_FILTER) {
+ asrc2_mask |= RT5640_ADC_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_ADC_M_MASK)
+ | (clk_src << RT5640_ADC_M_SFT);
+ }
+
+ if (filter_mask & RT5640_AD_MONO_L_FILTER) {
+ asrc2_mask |= RT5640_MAD_L_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_MAD_L_M_MASK)
+ | (clk_src << RT5640_MAD_L_M_SFT);
+ }
+
+ if (filter_mask & RT5640_AD_MONO_R_FILTER) {
+ asrc2_mask |= RT5640_MAD_R_M_MASK;
+ asrc2_value = (asrc2_value & ~RT5640_MAD_R_M_MASK)
+ | (clk_src << RT5640_MAD_R_M_SFT);
+ }
+
+ snd_soc_update_bits(codec, RT5640_ASRC_2,
+ asrc2_mask, asrc2_value);
+
+ if (snd_soc_read(codec, RT5640_ASRC_2)) {
+ rt5640->asrc_en = true;
+ snd_soc_update_bits(codec, RT5640_JD_CTRL, 0x3, 0x3);
+ } else {
+ rt5640->asrc_en = false;
+ snd_soc_update_bits(codec, RT5640_JD_CTRL, 0x3, 0x0);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt5640_sel_asrc_clk_src);
+
static int rt5640_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
@@ -2175,6 +2277,7 @@ static const struct acpi_device_id rt5640_acpi_match[] = {
{ "INT33CA", 0 },
{ "10EC5640", 0 },
{ "10EC5642", 0 },
+ { "INTCCFFD", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 3deb8babeabb..83a7150ddc24 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -1033,6 +1033,10 @@
#define RT5640_DMIC_2_M_NOR (0x0 << 8)
#define RT5640_DMIC_2_M_ASYN (0x1 << 8)
+/* ASRC clock source selection (0x84) */
+#define RT5640_CLK_SEL_SYS (0x0)
+#define RT5640_CLK_SEL_ASRC (0x1)
+
/* ASRC Control 2 (0x84) */
#define RT5640_MDA_L_M_MASK (0x1 << 15)
#define RT5640_MDA_L_M_SFT 15
@@ -2079,6 +2083,16 @@ enum {
RT5640_DMIC2,
};
+/* filter mask */
+enum {
+ RT5640_DA_STEREO_FILTER = 0x1,
+ RT5640_DA_MONO_L_FILTER = (0x1 << 1),
+ RT5640_DA_MONO_R_FILTER = (0x1 << 2),
+ RT5640_AD_STEREO_FILTER = (0x1 << 3),
+ RT5640_AD_MONO_L_FILTER = (0x1 << 4),
+ RT5640_AD_MONO_R_FILTER = (0x1 << 5),
+};
+
struct rt5640_priv {
struct snd_soc_codec *codec;
struct rt5640_platform_data pdata;
@@ -2095,9 +2109,12 @@ struct rt5640_priv {
int pll_out;
bool hp_mute;
+ bool asrc_en;
};
int rt5640_dmic_enable(struct snd_soc_codec *codec,
bool dmic1_data_pin, bool dmic2_data_pin);
+int rt5640_sel_asrc_clk_src(struct snd_soc_codec *codec,
+ unsigned int filter_mask, unsigned int clk_src);
#endif
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 3e3c7f6be29d..c61d38b585fb 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -64,7 +64,6 @@ static const struct reg_sequence init_list[] = {
{RT5645_PR_BASE + 0x21, 0x4040},
{RT5645_PR_BASE + 0x23, 0x0004},
};
-#define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
static const struct reg_sequence rt5650_init_list[] = {
{0xf6, 0x0100},
@@ -226,6 +225,163 @@ static const struct reg_default rt5645_reg[] = {
{ 0xff, 0x6308 },
};
+static const struct reg_default rt5650_reg[] = {
+ { 0x00, 0x0000 },
+ { 0x01, 0xc8c8 },
+ { 0x02, 0xc8c8 },
+ { 0x03, 0xc8c8 },
+ { 0x0a, 0x0002 },
+ { 0x0b, 0x2827 },
+ { 0x0c, 0xe000 },
+ { 0x0d, 0x0000 },
+ { 0x0e, 0x0000 },
+ { 0x0f, 0x0808 },
+ { 0x14, 0x3333 },
+ { 0x16, 0x4b00 },
+ { 0x18, 0x018b },
+ { 0x19, 0xafaf },
+ { 0x1a, 0xafaf },
+ { 0x1b, 0x0001 },
+ { 0x1c, 0x2f2f },
+ { 0x1d, 0x2f2f },
+ { 0x1e, 0x0000 },
+ { 0x20, 0x0000 },
+ { 0x27, 0x7060 },
+ { 0x28, 0x7070 },
+ { 0x29, 0x8080 },
+ { 0x2a, 0x5656 },
+ { 0x2b, 0x5454 },
+ { 0x2c, 0xaaa0 },
+ { 0x2d, 0x0000 },
+ { 0x2f, 0x1002 },
+ { 0x31, 0x5000 },
+ { 0x32, 0x0000 },
+ { 0x33, 0x0000 },
+ { 0x34, 0x0000 },
+ { 0x35, 0x0000 },
+ { 0x3b, 0x0000 },
+ { 0x3c, 0x007f },
+ { 0x3d, 0x0000 },
+ { 0x3e, 0x007f },
+ { 0x3f, 0x0000 },
+ { 0x40, 0x001f },
+ { 0x41, 0x0000 },
+ { 0x42, 0x001f },
+ { 0x45, 0x6000 },
+ { 0x46, 0x003e },
+ { 0x47, 0x003e },
+ { 0x48, 0xf807 },
+ { 0x4a, 0x0004 },
+ { 0x4d, 0x0000 },
+ { 0x4e, 0x0000 },
+ { 0x4f, 0x01ff },
+ { 0x50, 0x0000 },
+ { 0x51, 0x0000 },
+ { 0x52, 0x01ff },
+ { 0x53, 0xf000 },
+ { 0x56, 0x0111 },
+ { 0x57, 0x0064 },
+ { 0x58, 0xef0e },
+ { 0x59, 0xf0f0 },
+ { 0x5a, 0xef0e },
+ { 0x5b, 0xf0f0 },
+ { 0x5c, 0xef0e },
+ { 0x5d, 0xf0f0 },
+ { 0x5e, 0xf000 },
+ { 0x5f, 0x0000 },
+ { 0x61, 0x0300 },
+ { 0x62, 0x0000 },
+ { 0x63, 0x00c2 },
+ { 0x64, 0x0000 },
+ { 0x65, 0x0000 },
+ { 0x66, 0x0000 },
+ { 0x6a, 0x0000 },
+ { 0x6c, 0x0aaa },
+ { 0x70, 0x8000 },
+ { 0x71, 0x8000 },
+ { 0x72, 0x8000 },
+ { 0x73, 0x7770 },
+ { 0x74, 0x3e00 },
+ { 0x75, 0x2409 },
+ { 0x76, 0x000a },
+ { 0x77, 0x0c00 },
+ { 0x78, 0x0000 },
+ { 0x79, 0x0123 },
+ { 0x7a, 0x0123 },
+ { 0x80, 0x0000 },
+ { 0x81, 0x0000 },
+ { 0x82, 0x0000 },
+ { 0x83, 0x0000 },
+ { 0x84, 0x0000 },
+ { 0x85, 0x0000 },
+ { 0x8a, 0x0000 },
+ { 0x8e, 0x0004 },
+ { 0x8f, 0x1100 },
+ { 0x90, 0x0646 },
+ { 0x91, 0x0c06 },
+ { 0x93, 0x0000 },
+ { 0x94, 0x0200 },
+ { 0x95, 0x0000 },
+ { 0x9a, 0x2184 },
+ { 0x9b, 0x010a },
+ { 0x9c, 0x0aea },
+ { 0x9d, 0x000c },
+ { 0x9e, 0x0400 },
+ { 0xa0, 0xa0a8 },
+ { 0xa1, 0x0059 },
+ { 0xa2, 0x0001 },
+ { 0xae, 0x6000 },
+ { 0xaf, 0x0000 },
+ { 0xb0, 0x6000 },
+ { 0xb1, 0x0000 },
+ { 0xb2, 0x0000 },
+ { 0xb3, 0x001f },
+ { 0xb4, 0x020c },
+ { 0xb5, 0x1f00 },
+ { 0xb6, 0x0000 },
+ { 0xbb, 0x0000 },
+ { 0xbc, 0x0000 },
+ { 0xbd, 0x0000 },
+ { 0xbe, 0x0000 },
+ { 0xbf, 0x3100 },
+ { 0xc0, 0x0000 },
+ { 0xc1, 0x0000 },
+ { 0xc2, 0x0000 },
+ { 0xc3, 0x2000 },
+ { 0xcd, 0x0000 },
+ { 0xce, 0x0000 },
+ { 0xcf, 0x1813 },
+ { 0xd0, 0x0690 },
+ { 0xd1, 0x1c17 },
+ { 0xd3, 0xb320 },
+ { 0xd4, 0x0000 },
+ { 0xd6, 0x0400 },
+ { 0xd9, 0x0809 },
+ { 0xda, 0x0000 },
+ { 0xdb, 0x0003 },
+ { 0xdc, 0x0049 },
+ { 0xdd, 0x001b },
+ { 0xdf, 0x0008 },
+ { 0xe0, 0x4000 },
+ { 0xe6, 0x8000 },
+ { 0xe7, 0x0200 },
+ { 0xec, 0xb300 },
+ { 0xed, 0x0000 },
+ { 0xf0, 0x001f },
+ { 0xf1, 0x020c },
+ { 0xf2, 0x1f00 },
+ { 0xf3, 0x0000 },
+ { 0xf4, 0x4000 },
+ { 0xf8, 0x0000 },
+ { 0xf9, 0x0000 },
+ { 0xfa, 0x2060 },
+ { 0xfb, 0x4040 },
+ { 0xfc, 0x0000 },
+ { 0xfd, 0x0002 },
+ { 0xfe, 0x10ec },
+ { 0xff, 0x6308 },
+};
+
struct rt5645_eq_param_s {
unsigned short reg;
unsigned short val;
@@ -248,6 +404,7 @@ struct rt5645_priv {
struct delayed_work jack_detect_work, rcclock_work;
struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)];
struct rt5645_eq_param_s *eq_param;
+ struct timer_list btn_check_timer;
int codec_type;
int sysclk;
@@ -572,14 +729,12 @@ static int rt5645_spk_put_volsw(struct snd_kcontrol *kcontrol,
struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
int ret;
- cancel_delayed_work_sync(&rt5645->rcclock_work);
-
regmap_update_bits(rt5645->regmap, RT5645_MICBIAS,
RT5645_PWR_CLK25M_MASK, RT5645_PWR_CLK25M_PU);
ret = snd_soc_put_volsw(kcontrol, ucontrol);
- queue_delayed_work(system_power_efficient_wq, &rt5645->rcclock_work,
+ mod_delayed_work(system_power_efficient_wq, &rt5645->rcclock_work,
msecs_to_jiffies(200));
return ret;
@@ -2911,6 +3066,7 @@ static void rt5645_enable_push_button_irq(struct snd_soc_codec *codec,
snd_soc_dapm_force_enable_pin(dapm, "ADC R power");
snd_soc_dapm_sync(dapm);
+ snd_soc_update_bits(codec, RT5650_4BTN_IL_CMD1, 0x3, 0x3);
snd_soc_update_bits(codec,
RT5645_INT_IRQ_ST, 0x8, 0x8);
snd_soc_update_bits(codec,
@@ -2979,7 +3135,7 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
}
if (rt5645->pdata.jd_invert)
regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
- RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
+ RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR);
} else { /* jack out */
rt5645->jack_type = 0;
@@ -3000,7 +3156,7 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
snd_soc_dapm_sync(dapm);
if (rt5645->pdata.jd_invert)
regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
- RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR);
+ RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
}
return rt5645->jack_type;
@@ -3124,6 +3280,12 @@ static void rt5645_jack_detect_work(struct work_struct *work)
}
if (btn_type == 0)/* button release */
report = rt5645->jack_type;
+ else {
+ if (rt5645->pdata.jd_invert) {
+ mod_timer(&rt5645->btn_check_timer,
+ msecs_to_jiffies(100));
+ }
+ }
break;
/* jack out */
@@ -3166,6 +3328,14 @@ static irqreturn_t rt5645_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static void rt5645_btn_check_callback(unsigned long data)
+{
+ struct rt5645_priv *rt5645 = (struct rt5645_priv *)data;
+
+ queue_delayed_work(system_power_efficient_wq,
+ &rt5645->jack_detect_work, msecs_to_jiffies(5));
+}
+
static int rt5645_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
@@ -3322,6 +3492,31 @@ static const struct regmap_config rt5645_regmap = {
.num_ranges = ARRAY_SIZE(rt5645_ranges),
};
+static const struct regmap_config rt5650_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .use_single_rw = true,
+ .max_register = RT5645_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5645_ranges) *
+ RT5645_PR_SPACING),
+ .volatile_reg = rt5645_volatile_register,
+ .readable_reg = rt5645_readable_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5650_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt5650_reg),
+ .ranges = rt5645_ranges,
+ .num_ranges = ARRAY_SIZE(rt5645_ranges),
+};
+
+static const struct regmap_config temp_regmap = {
+ .name="nocache",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .use_single_rw = true,
+ .max_register = RT5645_VENDOR_ID2 + 1,
+ .cache_type = REGCACHE_NONE,
+};
+
static const struct i2c_device_id rt5645_i2c_id[] = {
{ "rt5645", 0 },
{ "rt5650", 0 },
@@ -3330,7 +3525,7 @@ static const struct i2c_device_id rt5645_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id);
#ifdef CONFIG_ACPI
-static struct acpi_device_id rt5645_acpi_match[] = {
+static const struct acpi_device_id rt5645_acpi_match[] = {
{ "10EC5645", 0 },
{ "10EC5650", 0 },
{},
@@ -3338,69 +3533,23 @@ static struct acpi_device_id rt5645_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match);
#endif
-static struct rt5645_platform_data *rt5645_pdata;
-
-static struct rt5645_platform_data strago_platform_data = {
+static struct rt5645_platform_data general_platform_data = {
.dmic1_data_pin = RT5645_DMIC1_DISABLE,
.dmic2_data_pin = RT5645_DMIC_DATA_IN2P,
.jd_mode = 3,
};
-static int strago_quirk_cb(const struct dmi_system_id *id)
-{
- rt5645_pdata = &strago_platform_data;
-
- return 1;
-}
-
static const struct dmi_system_id dmi_platform_intel_braswell[] = {
{
.ident = "Intel Strago",
- .callback = strago_quirk_cb,
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Strago"),
},
},
{
- .ident = "Google Celes",
- .callback = strago_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
- },
- },
- {
- .ident = "Google Ultima",
- .callback = strago_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "Ultima"),
- },
- },
- {
- .ident = "Google Reks",
- .callback = strago_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "Reks"),
- },
- },
- {
- .ident = "Google Edgar",
- .callback = strago_quirk_cb,
+ .ident = "Google Chrome",
.matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "Edgar"),
- },
- },
- {
- .ident = "Google Wizpig",
- .callback = strago_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "Wizpig"),
- },
- },
- {
- .ident = "Google Terra",
- .callback = strago_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "Terra"),
+ DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
},
},
{ }
@@ -3413,17 +3562,9 @@ static struct rt5645_platform_data buddy_platform_data = {
.jd_invert = true,
};
-static int buddy_quirk_cb(const struct dmi_system_id *id)
-{
- rt5645_pdata = &buddy_platform_data;
-
- return 1;
-}
-
static struct dmi_system_id dmi_platform_intel_broadwell[] = {
{
.ident = "Chrome Buddy",
- .callback = buddy_quirk_cb,
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Buddy"),
},
@@ -3431,6 +3572,16 @@ static struct dmi_system_id dmi_platform_intel_broadwell[] = {
{ }
};
+static bool rt5645_check_dp(struct device *dev)
+{
+ if (device_property_present(dev, "realtek,in2-differential") ||
+ device_property_present(dev, "realtek,dmic1-data-pin") ||
+ device_property_present(dev, "realtek,dmic2-data-pin") ||
+ device_property_present(dev, "realtek,jd-mode"))
+ return true;
+
+ return false;
+}
static int rt5645_parse_dt(struct rt5645_priv *rt5645, struct device *dev)
{
@@ -3453,6 +3604,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
struct rt5645_priv *rt5645;
int ret, i;
unsigned int val;
+ struct regmap *regmap;
rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv),
GFP_KERNEL);
@@ -3464,11 +3616,12 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt5645->pdata = *pdata;
- else if (dmi_check_system(dmi_platform_intel_braswell) ||
- dmi_check_system(dmi_platform_intel_broadwell))
- rt5645->pdata = *rt5645_pdata;
- else
+ else if (dmi_check_system(dmi_platform_intel_broadwell))
+ rt5645->pdata = buddy_platform_data;
+ else if (rt5645_check_dp(&i2c->dev))
rt5645_parse_dt(rt5645, &i2c->dev);
+ else if (dmi_check_system(dmi_platform_intel_braswell))
+ rt5645->pdata = general_platform_data;
rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect",
GPIOD_IN);
@@ -3478,14 +3631,6 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
return PTR_ERR(rt5645->gpiod_hp_det);
}
- rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap);
- if (IS_ERR(rt5645->regmap)) {
- ret = PTR_ERR(rt5645->regmap);
- dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
-
for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++)
rt5645->supplies[i].supply = rt5645_supply_names[i];
@@ -3504,13 +3649,22 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
return ret;
}
- regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val);
+ regmap = devm_regmap_init_i2c(i2c, &temp_regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&i2c->dev, "Failed to allocate temp register map: %d\n",
+ ret);
+ return ret;
+ }
+ regmap_read(regmap, RT5645_VENDOR_ID2, &val);
switch (val) {
case RT5645_DEVICE_ID:
+ rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap);
rt5645->codec_type = CODEC_TYPE_RT5645;
break;
case RT5650_DEVICE_ID:
+ rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5650_regmap);
rt5645->codec_type = CODEC_TYPE_RT5650;
break;
default:
@@ -3521,6 +3675,13 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
goto err_enable;
}
+ if (IS_ERR(rt5645->regmap)) {
+ ret = PTR_ERR(rt5645->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
regmap_write(rt5645->regmap, RT5645_RESET, 0);
ret = regmap_register_patch(rt5645->regmap, init_list,
@@ -3641,6 +3802,13 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
}
}
+ if (rt5645->pdata.jd_invert) {
+ regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
+ RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
+ setup_timer(&rt5645->btn_check_timer,
+ rt5645_btn_check_callback, (unsigned long)rt5645);
+ }
+
INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work);
INIT_DELAYED_WORK(&rt5645->rcclock_work, rt5645_rcclock_work);
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 1d4031818966..7a6197042423 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -18,6 +18,7 @@
#include <linux/regmap.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
+#include <linux/acpi.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -1735,12 +1736,38 @@ static const struct regmap_config rt5651_regmap = {
.num_ranges = ARRAY_SIZE(rt5651_ranges),
};
+#if defined(CONFIG_OF)
+static const struct of_device_id rt5651_of_match[] = {
+ { .compatible = "realtek,rt5651", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rt5651_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id rt5651_acpi_match[] = {
+ { "10EC5651", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, rt5651_acpi_match);
+#endif
+
static const struct i2c_device_id rt5651_i2c_id[] = {
{ "rt5651", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
+static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
+{
+ rt5651->pdata.in2_diff = of_property_read_bool(np,
+ "realtek,in2-differential");
+ rt5651->pdata.dmic_en = of_property_read_bool(np,
+ "realtek,dmic-en");
+
+ return 0;
+}
+
static int rt5651_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -1757,6 +1784,8 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt5651->pdata = *pdata;
+ else if (i2c->dev.of_node)
+ rt5651_parse_dt(rt5651, i2c->dev.of_node);
rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap);
if (IS_ERR(rt5651->regmap)) {
@@ -1806,6 +1835,8 @@ static int rt5651_i2c_remove(struct i2c_client *i2c)
static struct i2c_driver rt5651_i2c_driver = {
.driver = {
.name = "rt5651",
+ .acpi_match_table = ACPI_PTR(rt5651_acpi_match),
+ .of_match_table = of_match_ptr(rt5651_of_match),
},
.probe = rt5651_i2c_probe,
.remove = rt5651_i2c_remove,
diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c
new file mode 100644
index 000000000000..820d8fa62b5e
--- /dev/null
+++ b/sound/soc/codecs/rt5659.c
@@ -0,0 +1,4223 @@
+/*
+ * rt5659.c -- RT5659/RT5658 ALSA SoC audio codec driver
+ *
+ * Copyright 2015 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/acpi.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/rt5659.h>
+
+#include "rl6231.h"
+#include "rt5659.h"
+
+static const struct reg_default rt5659_reg[] = {
+ { 0x0000, 0x0000 },
+ { 0x0001, 0x4848 },
+ { 0x0002, 0x8080 },
+ { 0x0003, 0xc8c8 },
+ { 0x0004, 0xc80a },
+ { 0x0005, 0x0000 },
+ { 0x0006, 0x0000 },
+ { 0x0007, 0x0103 },
+ { 0x0008, 0x0080 },
+ { 0x0009, 0x0000 },
+ { 0x000a, 0x0000 },
+ { 0x000c, 0x0000 },
+ { 0x000d, 0x0000 },
+ { 0x000f, 0x0808 },
+ { 0x0010, 0x3080 },
+ { 0x0011, 0x4a00 },
+ { 0x0012, 0x4e00 },
+ { 0x0015, 0x42c1 },
+ { 0x0016, 0x0000 },
+ { 0x0018, 0x000b },
+ { 0x0019, 0xafaf },
+ { 0x001a, 0xafaf },
+ { 0x001b, 0x0011 },
+ { 0x001c, 0x2f2f },
+ { 0x001d, 0x2f2f },
+ { 0x001e, 0x2f2f },
+ { 0x001f, 0x0000 },
+ { 0x0020, 0x0000 },
+ { 0x0021, 0x0000 },
+ { 0x0022, 0x5757 },
+ { 0x0023, 0x0039 },
+ { 0x0026, 0xc060 },
+ { 0x0027, 0xd8d8 },
+ { 0x0029, 0x8080 },
+ { 0x002a, 0xaaaa },
+ { 0x002b, 0xaaaa },
+ { 0x002c, 0x00af },
+ { 0x002d, 0x0000 },
+ { 0x002f, 0x1002 },
+ { 0x0031, 0x5000 },
+ { 0x0032, 0x0000 },
+ { 0x0033, 0x0000 },
+ { 0x0034, 0x0000 },
+ { 0x0035, 0x0000 },
+ { 0x0036, 0x0000 },
+ { 0x003a, 0x0000 },
+ { 0x003b, 0x0000 },
+ { 0x003c, 0x007f },
+ { 0x003d, 0x0000 },
+ { 0x003e, 0x007f },
+ { 0x0040, 0x0808 },
+ { 0x0046, 0x001f },
+ { 0x0047, 0x001f },
+ { 0x0048, 0x0003 },
+ { 0x0049, 0xe061 },
+ { 0x004a, 0x0000 },
+ { 0x004b, 0x031f },
+ { 0x004d, 0x0000 },
+ { 0x004e, 0x001f },
+ { 0x004f, 0x0000 },
+ { 0x0050, 0x001f },
+ { 0x0052, 0xf000 },
+ { 0x0053, 0x0111 },
+ { 0x0054, 0x0064 },
+ { 0x0055, 0x0080 },
+ { 0x0056, 0xef0e },
+ { 0x0057, 0xf0f0 },
+ { 0x0058, 0xef0e },
+ { 0x0059, 0xf0f0 },
+ { 0x005a, 0xef0e },
+ { 0x005b, 0xf0f0 },
+ { 0x005c, 0xf000 },
+ { 0x005d, 0x0000 },
+ { 0x005e, 0x1f2c },
+ { 0x005f, 0x1f2c },
+ { 0x0060, 0x2717 },
+ { 0x0061, 0x0000 },
+ { 0x0062, 0x0000 },
+ { 0x0063, 0x003e },
+ { 0x0064, 0x0000 },
+ { 0x0065, 0x0000 },
+ { 0x0066, 0x0000 },
+ { 0x0067, 0x0000 },
+ { 0x006a, 0x0000 },
+ { 0x006b, 0x0000 },
+ { 0x006c, 0x0000 },
+ { 0x006e, 0x0000 },
+ { 0x006f, 0x0000 },
+ { 0x0070, 0x8000 },
+ { 0x0071, 0x8000 },
+ { 0x0072, 0x8000 },
+ { 0x0073, 0x1110 },
+ { 0x0074, 0xfe00 },
+ { 0x0075, 0x2409 },
+ { 0x0076, 0x000a },
+ { 0x0077, 0x00f0 },
+ { 0x0078, 0x0000 },
+ { 0x0079, 0x0000 },
+ { 0x007a, 0x0123 },
+ { 0x007b, 0x8003 },
+ { 0x0080, 0x0000 },
+ { 0x0081, 0x0000 },
+ { 0x0082, 0x0000 },
+ { 0x0083, 0x0000 },
+ { 0x0084, 0x0000 },
+ { 0x0085, 0x0000 },
+ { 0x0086, 0x0008 },
+ { 0x0087, 0x0000 },
+ { 0x0088, 0x0000 },
+ { 0x0089, 0x0000 },
+ { 0x008a, 0x0000 },
+ { 0x008b, 0x0000 },
+ { 0x008c, 0x0003 },
+ { 0x008e, 0x0000 },
+ { 0x008f, 0x1000 },
+ { 0x0090, 0x0646 },
+ { 0x0091, 0x0c16 },
+ { 0x0092, 0x0073 },
+ { 0x0093, 0x0000 },
+ { 0x0094, 0x0080 },
+ { 0x0097, 0x0000 },
+ { 0x0098, 0x0000 },
+ { 0x0099, 0x0000 },
+ { 0x009a, 0x0000 },
+ { 0x009b, 0x0000 },
+ { 0x009c, 0x007f },
+ { 0x009d, 0x0000 },
+ { 0x009e, 0x007f },
+ { 0x009f, 0x0000 },
+ { 0x00a0, 0x0060 },
+ { 0x00a1, 0x90a1 },
+ { 0x00ae, 0x2000 },
+ { 0x00af, 0x0000 },
+ { 0x00b0, 0x2000 },
+ { 0x00b1, 0x0000 },
+ { 0x00b2, 0x0000 },
+ { 0x00b6, 0x0000 },
+ { 0x00b7, 0x0000 },
+ { 0x00b8, 0x0000 },
+ { 0x00b9, 0x0000 },
+ { 0x00ba, 0x0000 },
+ { 0x00bb, 0x0000 },
+ { 0x00be, 0x0000 },
+ { 0x00bf, 0x0000 },
+ { 0x00c0, 0x0000 },
+ { 0x00c1, 0x0000 },
+ { 0x00c2, 0x0000 },
+ { 0x00c3, 0x0000 },
+ { 0x00c4, 0x0003 },
+ { 0x00c5, 0x0000 },
+ { 0x00cb, 0xa02f },
+ { 0x00cc, 0x0000 },
+ { 0x00cd, 0x0e02 },
+ { 0x00d6, 0x0000 },
+ { 0x00d7, 0x2244 },
+ { 0x00d9, 0x0809 },
+ { 0x00da, 0x0000 },
+ { 0x00db, 0x0008 },
+ { 0x00dc, 0x00c0 },
+ { 0x00dd, 0x6724 },
+ { 0x00de, 0x3131 },
+ { 0x00df, 0x0008 },
+ { 0x00e0, 0x4000 },
+ { 0x00e1, 0x3131 },
+ { 0x00e4, 0x400c },
+ { 0x00e5, 0x8031 },
+ { 0x00ea, 0xb320 },
+ { 0x00eb, 0x0000 },
+ { 0x00ec, 0xb300 },
+ { 0x00ed, 0x0000 },
+ { 0x00f0, 0x0000 },
+ { 0x00f1, 0x0202 },
+ { 0x00f2, 0x0ddd },
+ { 0x00f3, 0x0ddd },
+ { 0x00f4, 0x0ddd },
+ { 0x00f6, 0x0000 },
+ { 0x00f7, 0x0000 },
+ { 0x00f8, 0x0000 },
+ { 0x00f9, 0x0000 },
+ { 0x00fa, 0x8000 },
+ { 0x00fb, 0x0000 },
+ { 0x00fc, 0x0000 },
+ { 0x00fd, 0x0001 },
+ { 0x00fe, 0x10ec },
+ { 0x00ff, 0x6311 },
+ { 0x0100, 0xaaaa },
+ { 0x010a, 0xaaaa },
+ { 0x010b, 0x00a0 },
+ { 0x010c, 0xaeae },
+ { 0x010d, 0xaaaa },
+ { 0x010e, 0xaaa8 },
+ { 0x010f, 0xa0aa },
+ { 0x0110, 0xe02a },
+ { 0x0111, 0xa702 },
+ { 0x0112, 0xaaaa },
+ { 0x0113, 0x2800 },
+ { 0x0116, 0x0000 },
+ { 0x0117, 0x0f00 },
+ { 0x011a, 0x0020 },
+ { 0x011b, 0x0011 },
+ { 0x011c, 0x0150 },
+ { 0x011d, 0x0000 },
+ { 0x011e, 0x0000 },
+ { 0x011f, 0x0000 },
+ { 0x0120, 0x0000 },
+ { 0x0121, 0x009b },
+ { 0x0122, 0x5014 },
+ { 0x0123, 0x0421 },
+ { 0x0124, 0x7cea },
+ { 0x0125, 0x0420 },
+ { 0x0126, 0x5550 },
+ { 0x0132, 0x0000 },
+ { 0x0133, 0x0000 },
+ { 0x0137, 0x5055 },
+ { 0x0138, 0x3700 },
+ { 0x0139, 0x79a1 },
+ { 0x013a, 0x2020 },
+ { 0x013b, 0x2020 },
+ { 0x013c, 0x2005 },
+ { 0x013e, 0x1f00 },
+ { 0x013f, 0x0000 },
+ { 0x0145, 0x0002 },
+ { 0x0146, 0x0000 },
+ { 0x0147, 0x0000 },
+ { 0x0148, 0x0000 },
+ { 0x0150, 0x1813 },
+ { 0x0151, 0x0690 },
+ { 0x0152, 0x1c17 },
+ { 0x0153, 0x6883 },
+ { 0x0154, 0xd3ce },
+ { 0x0155, 0x352d },
+ { 0x0156, 0x00eb },
+ { 0x0157, 0x3717 },
+ { 0x0158, 0x4c6a },
+ { 0x0159, 0xe41b },
+ { 0x015a, 0x2a13 },
+ { 0x015b, 0xb600 },
+ { 0x015c, 0xc730 },
+ { 0x015d, 0x35d4 },
+ { 0x015e, 0x00bf },
+ { 0x0160, 0x0ec0 },
+ { 0x0161, 0x0020 },
+ { 0x0162, 0x0080 },
+ { 0x0163, 0x0800 },
+ { 0x0164, 0x0000 },
+ { 0x0165, 0x0000 },
+ { 0x0166, 0x0000 },
+ { 0x0167, 0x001f },
+ { 0x0170, 0x4e80 },
+ { 0x0171, 0x0020 },
+ { 0x0172, 0x0080 },
+ { 0x0173, 0x0800 },
+ { 0x0174, 0x000c },
+ { 0x0175, 0x0000 },
+ { 0x0190, 0x3300 },
+ { 0x0191, 0x2200 },
+ { 0x0192, 0x0000 },
+ { 0x01b0, 0x4b38 },
+ { 0x01b1, 0x0000 },
+ { 0x01b2, 0x0000 },
+ { 0x01b3, 0x0000 },
+ { 0x01c0, 0x0045 },
+ { 0x01c1, 0x0540 },
+ { 0x01c2, 0x0000 },
+ { 0x01c3, 0x0030 },
+ { 0x01c7, 0x0000 },
+ { 0x01c8, 0x5757 },
+ { 0x01c9, 0x5757 },
+ { 0x01ca, 0x5757 },
+ { 0x01cb, 0x5757 },
+ { 0x01cc, 0x5757 },
+ { 0x01cd, 0x5757 },
+ { 0x01ce, 0x006f },
+ { 0x01da, 0x0000 },
+ { 0x01db, 0x0000 },
+ { 0x01de, 0x7d00 },
+ { 0x01df, 0x10c0 },
+ { 0x01e0, 0x06a1 },
+ { 0x01e1, 0x0000 },
+ { 0x01e2, 0x0000 },
+ { 0x01e3, 0x0000 },
+ { 0x01e4, 0x0001 },
+ { 0x01e6, 0x0000 },
+ { 0x01e7, 0x0000 },
+ { 0x01e8, 0x0000 },
+ { 0x01ea, 0x0000 },
+ { 0x01eb, 0x0000 },
+ { 0x01ec, 0x0000 },
+ { 0x01ed, 0x0000 },
+ { 0x01ee, 0x0000 },
+ { 0x01ef, 0x0000 },
+ { 0x01f0, 0x0000 },
+ { 0x01f1, 0x0000 },
+ { 0x01f2, 0x0000 },
+ { 0x01f6, 0x1e04 },
+ { 0x01f7, 0x01a1 },
+ { 0x01f8, 0x0000 },
+ { 0x01f9, 0x0000 },
+ { 0x01fa, 0x0002 },
+ { 0x01fb, 0x0000 },
+ { 0x01fc, 0x0000 },
+ { 0x01fd, 0x0000 },
+ { 0x01fe, 0x0000 },
+ { 0x0200, 0x066c },
+ { 0x0201, 0x7fff },
+ { 0x0202, 0x7fff },
+ { 0x0203, 0x0000 },
+ { 0x0204, 0x0000 },
+ { 0x0205, 0x0000 },
+ { 0x0206, 0x0000 },
+ { 0x0207, 0x0000 },
+ { 0x0208, 0x0000 },
+ { 0x0256, 0x0000 },
+ { 0x0257, 0x0000 },
+ { 0x0258, 0x0000 },
+ { 0x0259, 0x0000 },
+ { 0x025a, 0x0000 },
+ { 0x025b, 0x3333 },
+ { 0x025c, 0x3333 },
+ { 0x025d, 0x3333 },
+ { 0x025e, 0x0000 },
+ { 0x025f, 0x0000 },
+ { 0x0260, 0x0000 },
+ { 0x0261, 0x0022 },
+ { 0x0262, 0x0300 },
+ { 0x0265, 0x1e80 },
+ { 0x0266, 0x0131 },
+ { 0x0267, 0x0003 },
+ { 0x0268, 0x0000 },
+ { 0x0269, 0x0000 },
+ { 0x026a, 0x0000 },
+ { 0x026b, 0x0000 },
+ { 0x026c, 0x0000 },
+ { 0x026d, 0x0000 },
+ { 0x026e, 0x0000 },
+ { 0x026f, 0x0000 },
+ { 0x0270, 0x0000 },
+ { 0x0271, 0x0000 },
+ { 0x0272, 0x0000 },
+ { 0x0273, 0x0000 },
+ { 0x0280, 0x0000 },
+ { 0x0281, 0x0000 },
+ { 0x0282, 0x0418 },
+ { 0x0283, 0x7fff },
+ { 0x0284, 0x7000 },
+ { 0x0290, 0x01d0 },
+ { 0x0291, 0x0100 },
+ { 0x02fa, 0x0000 },
+ { 0x02fb, 0x0000 },
+ { 0x02fc, 0x0000 },
+ { 0x0300, 0x001f },
+ { 0x0301, 0x032c },
+ { 0x0302, 0x5f21 },
+ { 0x0303, 0x4000 },
+ { 0x0304, 0x4000 },
+ { 0x0305, 0x0600 },
+ { 0x0306, 0x8000 },
+ { 0x0307, 0x0700 },
+ { 0x0308, 0x001f },
+ { 0x0309, 0x032c },
+ { 0x030a, 0x5f21 },
+ { 0x030b, 0x4000 },
+ { 0x030c, 0x4000 },
+ { 0x030d, 0x0600 },
+ { 0x030e, 0x8000 },
+ { 0x030f, 0x0700 },
+ { 0x0310, 0x4560 },
+ { 0x0311, 0xa4a8 },
+ { 0x0312, 0x7418 },
+ { 0x0313, 0x0000 },
+ { 0x0314, 0x0006 },
+ { 0x0315, 0x00ff },
+ { 0x0316, 0xc400 },
+ { 0x0317, 0x4560 },
+ { 0x0318, 0xa4a8 },
+ { 0x0319, 0x7418 },
+ { 0x031a, 0x0000 },
+ { 0x031b, 0x0006 },
+ { 0x031c, 0x00ff },
+ { 0x031d, 0xc400 },
+ { 0x0320, 0x0f20 },
+ { 0x0321, 0x8700 },
+ { 0x0322, 0x7dc2 },
+ { 0x0323, 0xa178 },
+ { 0x0324, 0x5383 },
+ { 0x0325, 0x7dc2 },
+ { 0x0326, 0xa178 },
+ { 0x0327, 0x5383 },
+ { 0x0328, 0x003e },
+ { 0x0329, 0x02c1 },
+ { 0x032a, 0xd37d },
+ { 0x0330, 0x00a6 },
+ { 0x0331, 0x04c3 },
+ { 0x0332, 0x27c8 },
+ { 0x0333, 0xbf50 },
+ { 0x0334, 0x0045 },
+ { 0x0335, 0x2007 },
+ { 0x0336, 0x7418 },
+ { 0x0337, 0x0501 },
+ { 0x0338, 0x0000 },
+ { 0x0339, 0x0010 },
+ { 0x033a, 0x1010 },
+ { 0x0340, 0x0800 },
+ { 0x0341, 0x0800 },
+ { 0x0342, 0x0800 },
+ { 0x0343, 0x0800 },
+ { 0x0344, 0x0000 },
+ { 0x0345, 0x0000 },
+ { 0x0346, 0x0000 },
+ { 0x0347, 0x0000 },
+ { 0x0348, 0x0000 },
+ { 0x0349, 0x0000 },
+ { 0x034a, 0x0000 },
+ { 0x034b, 0x0000 },
+ { 0x034c, 0x0000 },
+ { 0x034d, 0x0000 },
+ { 0x034e, 0x0000 },
+ { 0x034f, 0x0000 },
+ { 0x0350, 0x0000 },
+ { 0x0351, 0x0000 },
+ { 0x0352, 0x0000 },
+ { 0x0353, 0x0000 },
+ { 0x0354, 0x0000 },
+ { 0x0355, 0x0000 },
+ { 0x0356, 0x0000 },
+ { 0x0357, 0x0000 },
+ { 0x0358, 0x0000 },
+ { 0x0359, 0x0000 },
+ { 0x035a, 0x0000 },
+ { 0x035b, 0x0000 },
+ { 0x035c, 0x0000 },
+ { 0x035d, 0x0000 },
+ { 0x035e, 0x2000 },
+ { 0x035f, 0x0000 },
+ { 0x0360, 0x2000 },
+ { 0x0361, 0x2000 },
+ { 0x0362, 0x0000 },
+ { 0x0363, 0x2000 },
+ { 0x0364, 0x0200 },
+ { 0x0365, 0x0000 },
+ { 0x0366, 0x0000 },
+ { 0x0367, 0x0000 },
+ { 0x0368, 0x0000 },
+ { 0x0369, 0x0000 },
+ { 0x036a, 0x0000 },
+ { 0x036b, 0x0000 },
+ { 0x036c, 0x0000 },
+ { 0x036d, 0x0000 },
+ { 0x036e, 0x0200 },
+ { 0x036f, 0x0000 },
+ { 0x0370, 0x0000 },
+ { 0x0371, 0x0000 },
+ { 0x0372, 0x0000 },
+ { 0x0373, 0x0000 },
+ { 0x0374, 0x0000 },
+ { 0x0375, 0x0000 },
+ { 0x0376, 0x0000 },
+ { 0x0377, 0x0000 },
+ { 0x03d0, 0x0000 },
+ { 0x03d1, 0x0000 },
+ { 0x03d2, 0x0000 },
+ { 0x03d3, 0x0000 },
+ { 0x03d4, 0x2000 },
+ { 0x03d5, 0x2000 },
+ { 0x03d6, 0x0000 },
+ { 0x03d7, 0x0000 },
+ { 0x03d8, 0x2000 },
+ { 0x03d9, 0x2000 },
+ { 0x03da, 0x2000 },
+ { 0x03db, 0x2000 },
+ { 0x03dc, 0x0000 },
+ { 0x03dd, 0x0000 },
+ { 0x03de, 0x0000 },
+ { 0x03df, 0x2000 },
+ { 0x03e0, 0x0000 },
+ { 0x03e1, 0x0000 },
+ { 0x03e2, 0x0000 },
+ { 0x03e3, 0x0000 },
+ { 0x03e4, 0x0000 },
+ { 0x03e5, 0x0000 },
+ { 0x03e6, 0x0000 },
+ { 0x03e7, 0x0000 },
+ { 0x03e8, 0x0000 },
+ { 0x03e9, 0x0000 },
+ { 0x03ea, 0x0000 },
+ { 0x03eb, 0x0000 },
+ { 0x03ec, 0x0000 },
+ { 0x03ed, 0x0000 },
+ { 0x03ee, 0x0000 },
+ { 0x03ef, 0x0000 },
+ { 0x03f0, 0x0800 },
+ { 0x03f1, 0x0800 },
+ { 0x03f2, 0x0800 },
+ { 0x03f3, 0x0800 },
+};
+
+static bool rt5659_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case RT5659_RESET:
+ case RT5659_EJD_CTRL_2:
+ case RT5659_SILENCE_CTRL:
+ case RT5659_DAC2_DIG_VOL:
+ case RT5659_HP_IMP_GAIN_2:
+ case RT5659_PDM_OUT_CTRL:
+ case RT5659_PDM_DATA_CTRL_1:
+ case RT5659_PDM_DATA_CTRL_4:
+ case RT5659_HAPTIC_GEN_CTRL_1:
+ case RT5659_HAPTIC_GEN_CTRL_3:
+ case RT5659_HAPTIC_LPF_CTRL_3:
+ case RT5659_CLK_DET:
+ case RT5659_MICBIAS_1:
+ case RT5659_ASRC_11:
+ case RT5659_ADC_EQ_CTRL_1:
+ case RT5659_DAC_EQ_CTRL_1:
+ case RT5659_INT_ST_1:
+ case RT5659_INT_ST_2:
+ case RT5659_GPIO_STA:
+ case RT5659_SINE_GEN_CTRL_1:
+ case RT5659_IL_CMD_1:
+ case RT5659_4BTN_IL_CMD_1:
+ case RT5659_PSV_IL_CMD_1:
+ case RT5659_AJD1_CTRL:
+ case RT5659_AJD2_AJD3_CTRL:
+ case RT5659_JD_CTRL_3:
+ case RT5659_VENDOR_ID:
+ case RT5659_VENDOR_ID_1:
+ case RT5659_DEVICE_ID:
+ case RT5659_MEMORY_TEST:
+ case RT5659_SOFT_RAMP_DEPOP_DAC_CLK_CTRL:
+ case RT5659_VOL_TEST:
+ case RT5659_STO_NG2_CTRL_1:
+ case RT5659_STO_NG2_CTRL_5:
+ case RT5659_STO_NG2_CTRL_6:
+ case RT5659_STO_NG2_CTRL_7:
+ case RT5659_MONO_NG2_CTRL_1:
+ case RT5659_MONO_NG2_CTRL_5:
+ case RT5659_MONO_NG2_CTRL_6:
+ case RT5659_HP_IMP_SENS_CTRL_1:
+ case RT5659_HP_IMP_SENS_CTRL_3:
+ case RT5659_HP_IMP_SENS_CTRL_4:
+ case RT5659_HP_CALIB_CTRL_1:
+ case RT5659_HP_CALIB_CTRL_9:
+ case RT5659_HP_CALIB_STA_1:
+ case RT5659_HP_CALIB_STA_2:
+ case RT5659_HP_CALIB_STA_3:
+ case RT5659_HP_CALIB_STA_4:
+ case RT5659_HP_CALIB_STA_5:
+ case RT5659_HP_CALIB_STA_6:
+ case RT5659_HP_CALIB_STA_7:
+ case RT5659_HP_CALIB_STA_8:
+ case RT5659_HP_CALIB_STA_9:
+ case RT5659_MONO_AMP_CALIB_CTRL_1:
+ case RT5659_MONO_AMP_CALIB_CTRL_3:
+ case RT5659_MONO_AMP_CALIB_STA_1:
+ case RT5659_MONO_AMP_CALIB_STA_2:
+ case RT5659_MONO_AMP_CALIB_STA_3:
+ case RT5659_MONO_AMP_CALIB_STA_4:
+ case RT5659_SPK_PWR_LMT_STA_1:
+ case RT5659_SPK_PWR_LMT_STA_2:
+ case RT5659_SPK_PWR_LMT_STA_3:
+ case RT5659_SPK_PWR_LMT_STA_4:
+ case RT5659_SPK_PWR_LMT_STA_5:
+ case RT5659_SPK_PWR_LMT_STA_6:
+ case RT5659_SPK_DC_CAILB_CTRL_1:
+ case RT5659_SPK_DC_CAILB_STA_1:
+ case RT5659_SPK_DC_CAILB_STA_2:
+ case RT5659_SPK_DC_CAILB_STA_3:
+ case RT5659_SPK_DC_CAILB_STA_4:
+ case RT5659_SPK_DC_CAILB_STA_5:
+ case RT5659_SPK_DC_CAILB_STA_6:
+ case RT5659_SPK_DC_CAILB_STA_7:
+ case RT5659_SPK_DC_CAILB_STA_8:
+ case RT5659_SPK_DC_CAILB_STA_9:
+ case RT5659_SPK_DC_CAILB_STA_10:
+ case RT5659_SPK_VDD_STA_1:
+ case RT5659_SPK_VDD_STA_2:
+ case RT5659_SPK_DC_DET_CTRL_1:
+ case RT5659_PURE_DC_DET_CTRL_1:
+ case RT5659_PURE_DC_DET_CTRL_2:
+ case RT5659_DRC1_PRIV_1:
+ case RT5659_DRC1_PRIV_4:
+ case RT5659_DRC1_PRIV_5:
+ case RT5659_DRC1_PRIV_6:
+ case RT5659_DRC1_PRIV_7:
+ case RT5659_DRC2_PRIV_1:
+ case RT5659_DRC2_PRIV_4:
+ case RT5659_DRC2_PRIV_5:
+ case RT5659_DRC2_PRIV_6:
+ case RT5659_DRC2_PRIV_7:
+ case RT5659_ALC_PGA_STA_1:
+ case RT5659_ALC_PGA_STA_2:
+ case RT5659_ALC_PGA_STA_3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rt5659_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case RT5659_RESET:
+ case RT5659_SPO_VOL:
+ case RT5659_HP_VOL:
+ case RT5659_LOUT:
+ case RT5659_MONO_OUT:
+ case RT5659_HPL_GAIN:
+ case RT5659_HPR_GAIN:
+ case RT5659_MONO_GAIN:
+ case RT5659_SPDIF_CTRL_1:
+ case RT5659_SPDIF_CTRL_2:
+ case RT5659_CAL_BST_CTRL:
+ case RT5659_IN1_IN2:
+ case RT5659_IN3_IN4:
+ case RT5659_INL1_INR1_VOL:
+ case RT5659_EJD_CTRL_1:
+ case RT5659_EJD_CTRL_2:
+ case RT5659_EJD_CTRL_3:
+ case RT5659_SILENCE_CTRL:
+ case RT5659_PSV_CTRL:
+ case RT5659_SIDETONE_CTRL:
+ case RT5659_DAC1_DIG_VOL:
+ case RT5659_DAC2_DIG_VOL:
+ case RT5659_DAC_CTRL:
+ case RT5659_STO1_ADC_DIG_VOL:
+ case RT5659_MONO_ADC_DIG_VOL:
+ case RT5659_STO2_ADC_DIG_VOL:
+ case RT5659_STO1_BOOST:
+ case RT5659_MONO_BOOST:
+ case RT5659_STO2_BOOST:
+ case RT5659_HP_IMP_GAIN_1:
+ case RT5659_HP_IMP_GAIN_2:
+ case RT5659_STO1_ADC_MIXER:
+ case RT5659_MONO_ADC_MIXER:
+ case RT5659_AD_DA_MIXER:
+ case RT5659_STO_DAC_MIXER:
+ case RT5659_MONO_DAC_MIXER:
+ case RT5659_DIG_MIXER:
+ case RT5659_A_DAC_MUX:
+ case RT5659_DIG_INF23_DATA:
+ case RT5659_PDM_OUT_CTRL:
+ case RT5659_PDM_DATA_CTRL_1:
+ case RT5659_PDM_DATA_CTRL_2:
+ case RT5659_PDM_DATA_CTRL_3:
+ case RT5659_PDM_DATA_CTRL_4:
+ case RT5659_SPDIF_CTRL:
+ case RT5659_REC1_GAIN:
+ case RT5659_REC1_L1_MIXER:
+ case RT5659_REC1_L2_MIXER:
+ case RT5659_REC1_R1_MIXER:
+ case RT5659_REC1_R2_MIXER:
+ case RT5659_CAL_REC:
+ case RT5659_REC2_L1_MIXER:
+ case RT5659_REC2_L2_MIXER:
+ case RT5659_REC2_R1_MIXER:
+ case RT5659_REC2_R2_MIXER:
+ case RT5659_SPK_L_MIXER:
+ case RT5659_SPK_R_MIXER:
+ case RT5659_SPO_AMP_GAIN:
+ case RT5659_ALC_BACK_GAIN:
+ case RT5659_MONOMIX_GAIN:
+ case RT5659_MONOMIX_IN_GAIN:
+ case RT5659_OUT_L_GAIN:
+ case RT5659_OUT_L_MIXER:
+ case RT5659_OUT_R_GAIN:
+ case RT5659_OUT_R_MIXER:
+ case RT5659_LOUT_MIXER:
+ case RT5659_HAPTIC_GEN_CTRL_1:
+ case RT5659_HAPTIC_GEN_CTRL_2:
+ case RT5659_HAPTIC_GEN_CTRL_3:
+ case RT5659_HAPTIC_GEN_CTRL_4:
+ case RT5659_HAPTIC_GEN_CTRL_5:
+ case RT5659_HAPTIC_GEN_CTRL_6:
+ case RT5659_HAPTIC_GEN_CTRL_7:
+ case RT5659_HAPTIC_GEN_CTRL_8:
+ case RT5659_HAPTIC_GEN_CTRL_9:
+ case RT5659_HAPTIC_GEN_CTRL_10:
+ case RT5659_HAPTIC_GEN_CTRL_11:
+ case RT5659_HAPTIC_LPF_CTRL_1:
+ case RT5659_HAPTIC_LPF_CTRL_2:
+ case RT5659_HAPTIC_LPF_CTRL_3:
+ case RT5659_PWR_DIG_1:
+ case RT5659_PWR_DIG_2:
+ case RT5659_PWR_ANLG_1:
+ case RT5659_PWR_ANLG_2:
+ case RT5659_PWR_ANLG_3:
+ case RT5659_PWR_MIXER:
+ case RT5659_PWR_VOL:
+ case RT5659_PRIV_INDEX:
+ case RT5659_CLK_DET:
+ case RT5659_PRIV_DATA:
+ case RT5659_PRE_DIV_1:
+ case RT5659_PRE_DIV_2:
+ case RT5659_I2S1_SDP:
+ case RT5659_I2S2_SDP:
+ case RT5659_I2S3_SDP:
+ case RT5659_ADDA_CLK_1:
+ case RT5659_ADDA_CLK_2:
+ case RT5659_DMIC_CTRL_1:
+ case RT5659_DMIC_CTRL_2:
+ case RT5659_TDM_CTRL_1:
+ case RT5659_TDM_CTRL_2:
+ case RT5659_TDM_CTRL_3:
+ case RT5659_TDM_CTRL_4:
+ case RT5659_TDM_CTRL_5:
+ case RT5659_GLB_CLK:
+ case RT5659_PLL_CTRL_1:
+ case RT5659_PLL_CTRL_2:
+ case RT5659_ASRC_1:
+ case RT5659_ASRC_2:
+ case RT5659_ASRC_3:
+ case RT5659_ASRC_4:
+ case RT5659_ASRC_5:
+ case RT5659_ASRC_6:
+ case RT5659_ASRC_7:
+ case RT5659_ASRC_8:
+ case RT5659_ASRC_9:
+ case RT5659_ASRC_10:
+ case RT5659_DEPOP_1:
+ case RT5659_DEPOP_2:
+ case RT5659_DEPOP_3:
+ case RT5659_HP_CHARGE_PUMP_1:
+ case RT5659_HP_CHARGE_PUMP_2:
+ case RT5659_MICBIAS_1:
+ case RT5659_MICBIAS_2:
+ case RT5659_ASRC_11:
+ case RT5659_ASRC_12:
+ case RT5659_ASRC_13:
+ case RT5659_REC_M1_M2_GAIN_CTRL:
+ case RT5659_RC_CLK_CTRL:
+ case RT5659_CLASSD_CTRL_1:
+ case RT5659_CLASSD_CTRL_2:
+ case RT5659_ADC_EQ_CTRL_1:
+ case RT5659_ADC_EQ_CTRL_2:
+ case RT5659_DAC_EQ_CTRL_1:
+ case RT5659_DAC_EQ_CTRL_2:
+ case RT5659_DAC_EQ_CTRL_3:
+ case RT5659_IRQ_CTRL_1:
+ case RT5659_IRQ_CTRL_2:
+ case RT5659_IRQ_CTRL_3:
+ case RT5659_IRQ_CTRL_4:
+ case RT5659_IRQ_CTRL_5:
+ case RT5659_IRQ_CTRL_6:
+ case RT5659_INT_ST_1:
+ case RT5659_INT_ST_2:
+ case RT5659_GPIO_CTRL_1:
+ case RT5659_GPIO_CTRL_2:
+ case RT5659_GPIO_CTRL_3:
+ case RT5659_GPIO_CTRL_4:
+ case RT5659_GPIO_CTRL_5:
+ case RT5659_GPIO_STA:
+ case RT5659_SINE_GEN_CTRL_1:
+ case RT5659_SINE_GEN_CTRL_2:
+ case RT5659_SINE_GEN_CTRL_3:
+ case RT5659_HP_AMP_DET_CTRL_1:
+ case RT5659_HP_AMP_DET_CTRL_2:
+ case RT5659_SV_ZCD_1:
+ case RT5659_SV_ZCD_2:
+ case RT5659_IL_CMD_1:
+ case RT5659_IL_CMD_2:
+ case RT5659_IL_CMD_3:
+ case RT5659_IL_CMD_4:
+ case RT5659_4BTN_IL_CMD_1:
+ case RT5659_4BTN_IL_CMD_2:
+ case RT5659_4BTN_IL_CMD_3:
+ case RT5659_PSV_IL_CMD_1:
+ case RT5659_PSV_IL_CMD_2:
+ case RT5659_ADC_STO1_HP_CTRL_1:
+ case RT5659_ADC_STO1_HP_CTRL_2:
+ case RT5659_ADC_MONO_HP_CTRL_1:
+ case RT5659_ADC_MONO_HP_CTRL_2:
+ case RT5659_AJD1_CTRL:
+ case RT5659_AJD2_AJD3_CTRL:
+ case RT5659_JD1_THD:
+ case RT5659_JD2_THD:
+ case RT5659_JD3_THD:
+ case RT5659_JD_CTRL_1:
+ case RT5659_JD_CTRL_2:
+ case RT5659_JD_CTRL_3:
+ case RT5659_JD_CTRL_4:
+ case RT5659_DIG_MISC:
+ case RT5659_DUMMY_2:
+ case RT5659_DUMMY_3:
+ case RT5659_VENDOR_ID:
+ case RT5659_VENDOR_ID_1:
+ case RT5659_DEVICE_ID:
+ case RT5659_DAC_ADC_DIG_VOL:
+ case RT5659_BIAS_CUR_CTRL_1:
+ case RT5659_BIAS_CUR_CTRL_2:
+ case RT5659_BIAS_CUR_CTRL_3:
+ case RT5659_BIAS_CUR_CTRL_4:
+ case RT5659_BIAS_CUR_CTRL_5:
+ case RT5659_BIAS_CUR_CTRL_6:
+ case RT5659_BIAS_CUR_CTRL_7:
+ case RT5659_BIAS_CUR_CTRL_8:
+ case RT5659_BIAS_CUR_CTRL_9:
+ case RT5659_BIAS_CUR_CTRL_10:
+ case RT5659_MEMORY_TEST:
+ case RT5659_VREF_REC_OP_FB_CAP_CTRL:
+ case RT5659_CLASSD_0:
+ case RT5659_CLASSD_1:
+ case RT5659_CLASSD_2:
+ case RT5659_CLASSD_3:
+ case RT5659_CLASSD_4:
+ case RT5659_CLASSD_5:
+ case RT5659_CLASSD_6:
+ case RT5659_CLASSD_7:
+ case RT5659_CLASSD_8:
+ case RT5659_CLASSD_9:
+ case RT5659_CLASSD_10:
+ case RT5659_CHARGE_PUMP_1:
+ case RT5659_CHARGE_PUMP_2:
+ case RT5659_DIG_IN_CTRL_1:
+ case RT5659_DIG_IN_CTRL_2:
+ case RT5659_PAD_DRIVING_CTRL:
+ case RT5659_SOFT_RAMP_DEPOP:
+ case RT5659_PLL:
+ case RT5659_CHOP_DAC:
+ case RT5659_CHOP_ADC:
+ case RT5659_CALIB_ADC_CTRL:
+ case RT5659_SOFT_RAMP_DEPOP_DAC_CLK_CTRL:
+ case RT5659_VOL_TEST:
+ case RT5659_TEST_MODE_CTRL_1:
+ case RT5659_TEST_MODE_CTRL_2:
+ case RT5659_TEST_MODE_CTRL_3:
+ case RT5659_TEST_MODE_CTRL_4:
+ case RT5659_BASSBACK_CTRL:
+ case RT5659_MP3_PLUS_CTRL_1:
+ case RT5659_MP3_PLUS_CTRL_2:
+ case RT5659_MP3_HPF_A1:
+ case RT5659_MP3_HPF_A2:
+ case RT5659_MP3_HPF_H0:
+ case RT5659_MP3_LPF_H0:
+ case RT5659_3D_SPK_CTRL:
+ case RT5659_3D_SPK_COEF_1:
+ case RT5659_3D_SPK_COEF_2:
+ case RT5659_3D_SPK_COEF_3:
+ case RT5659_3D_SPK_COEF_4:
+ case RT5659_3D_SPK_COEF_5:
+ case RT5659_3D_SPK_COEF_6:
+ case RT5659_3D_SPK_COEF_7:
+ case RT5659_STO_NG2_CTRL_1:
+ case RT5659_STO_NG2_CTRL_2:
+ case RT5659_STO_NG2_CTRL_3:
+ case RT5659_STO_NG2_CTRL_4:
+ case RT5659_STO_NG2_CTRL_5:
+ case RT5659_STO_NG2_CTRL_6:
+ case RT5659_STO_NG2_CTRL_7:
+ case RT5659_STO_NG2_CTRL_8:
+ case RT5659_MONO_NG2_CTRL_1:
+ case RT5659_MONO_NG2_CTRL_2:
+ case RT5659_MONO_NG2_CTRL_3:
+ case RT5659_MONO_NG2_CTRL_4:
+ case RT5659_MONO_NG2_CTRL_5:
+ case RT5659_MONO_NG2_CTRL_6:
+ case RT5659_MID_HP_AMP_DET:
+ case RT5659_LOW_HP_AMP_DET:
+ case RT5659_LDO_CTRL:
+ case RT5659_HP_DECROSS_CTRL_1:
+ case RT5659_HP_DECROSS_CTRL_2:
+ case RT5659_HP_DECROSS_CTRL_3:
+ case RT5659_HP_DECROSS_CTRL_4:
+ case RT5659_HP_IMP_SENS_CTRL_1:
+ case RT5659_HP_IMP_SENS_CTRL_2:
+ case RT5659_HP_IMP_SENS_CTRL_3:
+ case RT5659_HP_IMP_SENS_CTRL_4:
+ case RT5659_HP_IMP_SENS_MAP_1:
+ case RT5659_HP_IMP_SENS_MAP_2:
+ case RT5659_HP_IMP_SENS_MAP_3:
+ case RT5659_HP_IMP_SENS_MAP_4:
+ case RT5659_HP_IMP_SENS_MAP_5:
+ case RT5659_HP_IMP_SENS_MAP_6:
+ case RT5659_HP_IMP_SENS_MAP_7:
+ case RT5659_HP_IMP_SENS_MAP_8:
+ case RT5659_HP_LOGIC_CTRL_1:
+ case RT5659_HP_LOGIC_CTRL_2:
+ case RT5659_HP_CALIB_CTRL_1:
+ case RT5659_HP_CALIB_CTRL_2:
+ case RT5659_HP_CALIB_CTRL_3:
+ case RT5659_HP_CALIB_CTRL_4:
+ case RT5659_HP_CALIB_CTRL_5:
+ case RT5659_HP_CALIB_CTRL_6:
+ case RT5659_HP_CALIB_CTRL_7:
+ case RT5659_HP_CALIB_CTRL_9:
+ case RT5659_HP_CALIB_CTRL_10:
+ case RT5659_HP_CALIB_CTRL_11:
+ case RT5659_HP_CALIB_STA_1:
+ case RT5659_HP_CALIB_STA_2:
+ case RT5659_HP_CALIB_STA_3:
+ case RT5659_HP_CALIB_STA_4:
+ case RT5659_HP_CALIB_STA_5:
+ case RT5659_HP_CALIB_STA_6:
+ case RT5659_HP_CALIB_STA_7:
+ case RT5659_HP_CALIB_STA_8:
+ case RT5659_HP_CALIB_STA_9:
+ case RT5659_MONO_AMP_CALIB_CTRL_1:
+ case RT5659_MONO_AMP_CALIB_CTRL_2:
+ case RT5659_MONO_AMP_CALIB_CTRL_3:
+ case RT5659_MONO_AMP_CALIB_CTRL_4:
+ case RT5659_MONO_AMP_CALIB_CTRL_5:
+ case RT5659_MONO_AMP_CALIB_STA_1:
+ case RT5659_MONO_AMP_CALIB_STA_2:
+ case RT5659_MONO_AMP_CALIB_STA_3:
+ case RT5659_MONO_AMP_CALIB_STA_4:
+ case RT5659_SPK_PWR_LMT_CTRL_1:
+ case RT5659_SPK_PWR_LMT_CTRL_2:
+ case RT5659_SPK_PWR_LMT_CTRL_3:
+ case RT5659_SPK_PWR_LMT_STA_1:
+ case RT5659_SPK_PWR_LMT_STA_2:
+ case RT5659_SPK_PWR_LMT_STA_3:
+ case RT5659_SPK_PWR_LMT_STA_4:
+ case RT5659_SPK_PWR_LMT_STA_5:
+ case RT5659_SPK_PWR_LMT_STA_6:
+ case RT5659_FLEX_SPK_BST_CTRL_1:
+ case RT5659_FLEX_SPK_BST_CTRL_2:
+ case RT5659_FLEX_SPK_BST_CTRL_3:
+ case RT5659_FLEX_SPK_BST_CTRL_4:
+ case RT5659_SPK_EX_LMT_CTRL_1:
+ case RT5659_SPK_EX_LMT_CTRL_2:
+ case RT5659_SPK_EX_LMT_CTRL_3:
+ case RT5659_SPK_EX_LMT_CTRL_4:
+ case RT5659_SPK_EX_LMT_CTRL_5:
+ case RT5659_SPK_EX_LMT_CTRL_6:
+ case RT5659_SPK_EX_LMT_CTRL_7:
+ case RT5659_ADJ_HPF_CTRL_1:
+ case RT5659_ADJ_HPF_CTRL_2:
+ case RT5659_SPK_DC_CAILB_CTRL_1:
+ case RT5659_SPK_DC_CAILB_CTRL_2:
+ case RT5659_SPK_DC_CAILB_CTRL_3:
+ case RT5659_SPK_DC_CAILB_CTRL_4:
+ case RT5659_SPK_DC_CAILB_CTRL_5:
+ case RT5659_SPK_DC_CAILB_STA_1:
+ case RT5659_SPK_DC_CAILB_STA_2:
+ case RT5659_SPK_DC_CAILB_STA_3:
+ case RT5659_SPK_DC_CAILB_STA_4:
+ case RT5659_SPK_DC_CAILB_STA_5:
+ case RT5659_SPK_DC_CAILB_STA_6:
+ case RT5659_SPK_DC_CAILB_STA_7:
+ case RT5659_SPK_DC_CAILB_STA_8:
+ case RT5659_SPK_DC_CAILB_STA_9:
+ case RT5659_SPK_DC_CAILB_STA_10:
+ case RT5659_SPK_VDD_STA_1:
+ case RT5659_SPK_VDD_STA_2:
+ case RT5659_SPK_DC_DET_CTRL_1:
+ case RT5659_SPK_DC_DET_CTRL_2:
+ case RT5659_SPK_DC_DET_CTRL_3:
+ case RT5659_PURE_DC_DET_CTRL_1:
+ case RT5659_PURE_DC_DET_CTRL_2:
+ case RT5659_DUMMY_4:
+ case RT5659_DUMMY_5:
+ case RT5659_DUMMY_6:
+ case RT5659_DRC1_CTRL_1:
+ case RT5659_DRC1_CTRL_2:
+ case RT5659_DRC1_CTRL_3:
+ case RT5659_DRC1_CTRL_4:
+ case RT5659_DRC1_CTRL_5:
+ case RT5659_DRC1_CTRL_6:
+ case RT5659_DRC1_HARD_LMT_CTRL_1:
+ case RT5659_DRC1_HARD_LMT_CTRL_2:
+ case RT5659_DRC2_CTRL_1:
+ case RT5659_DRC2_CTRL_2:
+ case RT5659_DRC2_CTRL_3:
+ case RT5659_DRC2_CTRL_4:
+ case RT5659_DRC2_CTRL_5:
+ case RT5659_DRC2_CTRL_6:
+ case RT5659_DRC2_HARD_LMT_CTRL_1:
+ case RT5659_DRC2_HARD_LMT_CTRL_2:
+ case RT5659_DRC1_PRIV_1:
+ case RT5659_DRC1_PRIV_2:
+ case RT5659_DRC1_PRIV_3:
+ case RT5659_DRC1_PRIV_4:
+ case RT5659_DRC1_PRIV_5:
+ case RT5659_DRC1_PRIV_6:
+ case RT5659_DRC1_PRIV_7:
+ case RT5659_DRC2_PRIV_1:
+ case RT5659_DRC2_PRIV_2:
+ case RT5659_DRC2_PRIV_3:
+ case RT5659_DRC2_PRIV_4:
+ case RT5659_DRC2_PRIV_5:
+ case RT5659_DRC2_PRIV_6:
+ case RT5659_DRC2_PRIV_7:
+ case RT5659_MULTI_DRC_CTRL:
+ case RT5659_CROSS_OVER_1:
+ case RT5659_CROSS_OVER_2:
+ case RT5659_CROSS_OVER_3:
+ case RT5659_CROSS_OVER_4:
+ case RT5659_CROSS_OVER_5:
+ case RT5659_CROSS_OVER_6:
+ case RT5659_CROSS_OVER_7:
+ case RT5659_CROSS_OVER_8:
+ case RT5659_CROSS_OVER_9:
+ case RT5659_CROSS_OVER_10:
+ case RT5659_ALC_PGA_CTRL_1:
+ case RT5659_ALC_PGA_CTRL_2:
+ case RT5659_ALC_PGA_CTRL_3:
+ case RT5659_ALC_PGA_CTRL_4:
+ case RT5659_ALC_PGA_CTRL_5:
+ case RT5659_ALC_PGA_CTRL_6:
+ case RT5659_ALC_PGA_CTRL_7:
+ case RT5659_ALC_PGA_CTRL_8:
+ case RT5659_ALC_PGA_STA_1:
+ case RT5659_ALC_PGA_STA_2:
+ case RT5659_ALC_PGA_STA_3:
+ case RT5659_DAC_L_EQ_PRE_VOL:
+ case RT5659_DAC_R_EQ_PRE_VOL:
+ case RT5659_DAC_L_EQ_POST_VOL:
+ case RT5659_DAC_R_EQ_POST_VOL:
+ case RT5659_DAC_L_EQ_LPF1_A1:
+ case RT5659_DAC_L_EQ_LPF1_H0:
+ case RT5659_DAC_R_EQ_LPF1_A1:
+ case RT5659_DAC_R_EQ_LPF1_H0:
+ case RT5659_DAC_L_EQ_BPF2_A1:
+ case RT5659_DAC_L_EQ_BPF2_A2:
+ case RT5659_DAC_L_EQ_BPF2_H0:
+ case RT5659_DAC_R_EQ_BPF2_A1:
+ case RT5659_DAC_R_EQ_BPF2_A2:
+ case RT5659_DAC_R_EQ_BPF2_H0:
+ case RT5659_DAC_L_EQ_BPF3_A1:
+ case RT5659_DAC_L_EQ_BPF3_A2:
+ case RT5659_DAC_L_EQ_BPF3_H0:
+ case RT5659_DAC_R_EQ_BPF3_A1:
+ case RT5659_DAC_R_EQ_BPF3_A2:
+ case RT5659_DAC_R_EQ_BPF3_H0:
+ case RT5659_DAC_L_EQ_BPF4_A1:
+ case RT5659_DAC_L_EQ_BPF4_A2:
+ case RT5659_DAC_L_EQ_BPF4_H0:
+ case RT5659_DAC_R_EQ_BPF4_A1:
+ case RT5659_DAC_R_EQ_BPF4_A2:
+ case RT5659_DAC_R_EQ_BPF4_H0:
+ case RT5659_DAC_L_EQ_HPF1_A1:
+ case RT5659_DAC_L_EQ_HPF1_H0:
+ case RT5659_DAC_R_EQ_HPF1_A1:
+ case RT5659_DAC_R_EQ_HPF1_H0:
+ case RT5659_DAC_L_EQ_HPF2_A1:
+ case RT5659_DAC_L_EQ_HPF2_A2:
+ case RT5659_DAC_L_EQ_HPF2_H0:
+ case RT5659_DAC_R_EQ_HPF2_A1:
+ case RT5659_DAC_R_EQ_HPF2_A2:
+ case RT5659_DAC_R_EQ_HPF2_H0:
+ case RT5659_DAC_L_BI_EQ_BPF1_H0_1:
+ case RT5659_DAC_L_BI_EQ_BPF1_H0_2:
+ case RT5659_DAC_L_BI_EQ_BPF1_B1_1:
+ case RT5659_DAC_L_BI_EQ_BPF1_B1_2:
+ case RT5659_DAC_L_BI_EQ_BPF1_B2_1:
+ case RT5659_DAC_L_BI_EQ_BPF1_B2_2:
+ case RT5659_DAC_L_BI_EQ_BPF1_A1_1:
+ case RT5659_DAC_L_BI_EQ_BPF1_A1_2:
+ case RT5659_DAC_L_BI_EQ_BPF1_A2_1:
+ case RT5659_DAC_L_BI_EQ_BPF1_A2_2:
+ case RT5659_DAC_R_BI_EQ_BPF1_H0_1:
+ case RT5659_DAC_R_BI_EQ_BPF1_H0_2:
+ case RT5659_DAC_R_BI_EQ_BPF1_B1_1:
+ case RT5659_DAC_R_BI_EQ_BPF1_B1_2:
+ case RT5659_DAC_R_BI_EQ_BPF1_B2_1:
+ case RT5659_DAC_R_BI_EQ_BPF1_B2_2:
+ case RT5659_DAC_R_BI_EQ_BPF1_A1_1:
+ case RT5659_DAC_R_BI_EQ_BPF1_A1_2:
+ case RT5659_DAC_R_BI_EQ_BPF1_A2_1:
+ case RT5659_DAC_R_BI_EQ_BPF1_A2_2:
+ case RT5659_ADC_L_EQ_LPF1_A1:
+ case RT5659_ADC_R_EQ_LPF1_A1:
+ case RT5659_ADC_L_EQ_LPF1_H0:
+ case RT5659_ADC_R_EQ_LPF1_H0:
+ case RT5659_ADC_L_EQ_BPF1_A1:
+ case RT5659_ADC_R_EQ_BPF1_A1:
+ case RT5659_ADC_L_EQ_BPF1_A2:
+ case RT5659_ADC_R_EQ_BPF1_A2:
+ case RT5659_ADC_L_EQ_BPF1_H0:
+ case RT5659_ADC_R_EQ_BPF1_H0:
+ case RT5659_ADC_L_EQ_BPF2_A1:
+ case RT5659_ADC_R_EQ_BPF2_A1:
+ case RT5659_ADC_L_EQ_BPF2_A2:
+ case RT5659_ADC_R_EQ_BPF2_A2:
+ case RT5659_ADC_L_EQ_BPF2_H0:
+ case RT5659_ADC_R_EQ_BPF2_H0:
+ case RT5659_ADC_L_EQ_BPF3_A1:
+ case RT5659_ADC_R_EQ_BPF3_A1:
+ case RT5659_ADC_L_EQ_BPF3_A2:
+ case RT5659_ADC_R_EQ_BPF3_A2:
+ case RT5659_ADC_L_EQ_BPF3_H0:
+ case RT5659_ADC_R_EQ_BPF3_H0:
+ case RT5659_ADC_L_EQ_BPF4_A1:
+ case RT5659_ADC_R_EQ_BPF4_A1:
+ case RT5659_ADC_L_EQ_BPF4_A2:
+ case RT5659_ADC_R_EQ_BPF4_A2:
+ case RT5659_ADC_L_EQ_BPF4_H0:
+ case RT5659_ADC_R_EQ_BPF4_H0:
+ case RT5659_ADC_L_EQ_HPF1_A1:
+ case RT5659_ADC_R_EQ_HPF1_A1:
+ case RT5659_ADC_L_EQ_HPF1_H0:
+ case RT5659_ADC_R_EQ_HPF1_H0:
+ case RT5659_ADC_L_EQ_PRE_VOL:
+ case RT5659_ADC_R_EQ_PRE_VOL:
+ case RT5659_ADC_L_EQ_POST_VOL:
+ case RT5659_ADC_R_EQ_POST_VOL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -2325, 75, 0);
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
+static const DECLARE_TLV_DB_SCALE(in_bst_tlv, -1200, 75, 0);
+
+/* Interface data select */
+static const char * const rt5659_data_select[] = {
+ "L/R", "R/L", "L/L", "R/R"
+};
+
+static const SOC_ENUM_SINGLE_DECL(rt5659_if1_01_adc_enum,
+ RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT01_SFT, rt5659_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5659_if1_23_adc_enum,
+ RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT23_SFT, rt5659_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5659_if1_45_adc_enum,
+ RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT45_SFT, rt5659_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5659_if1_67_adc_enum,
+ RT5659_TDM_CTRL_2, RT5659_DS_ADC_SLOT67_SFT, rt5659_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5659_if2_dac_enum,
+ RT5659_DIG_INF23_DATA, RT5659_IF2_DAC_SEL_SFT, rt5659_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5659_if2_adc_enum,
+ RT5659_DIG_INF23_DATA, RT5659_IF2_ADC_SEL_SFT, rt5659_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5659_if3_dac_enum,
+ RT5659_DIG_INF23_DATA, RT5659_IF3_DAC_SEL_SFT, rt5659_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5659_if3_adc_enum,
+ RT5659_DIG_INF23_DATA, RT5659_IF3_ADC_SEL_SFT, rt5659_data_select);
+
+static const struct snd_kcontrol_new rt5659_if1_01_adc_swap_mux =
+ SOC_DAPM_ENUM("IF1 01 ADC Swap Source", rt5659_if1_01_adc_enum);
+
+static const struct snd_kcontrol_new rt5659_if1_23_adc_swap_mux =
+ SOC_DAPM_ENUM("IF1 23 ADC1 Swap Source", rt5659_if1_23_adc_enum);
+
+static const struct snd_kcontrol_new rt5659_if1_45_adc_swap_mux =
+ SOC_DAPM_ENUM("IF1 45 ADC1 Swap Source", rt5659_if1_45_adc_enum);
+
+static const struct snd_kcontrol_new rt5659_if1_67_adc_swap_mux =
+ SOC_DAPM_ENUM("IF1 67 ADC1 Swap Source", rt5659_if1_67_adc_enum);
+
+static const struct snd_kcontrol_new rt5659_if2_dac_swap_mux =
+ SOC_DAPM_ENUM("IF2 DAC Swap Source", rt5659_if2_dac_enum);
+
+static const struct snd_kcontrol_new rt5659_if2_adc_swap_mux =
+ SOC_DAPM_ENUM("IF2 ADC Swap Source", rt5659_if2_adc_enum);
+
+static const struct snd_kcontrol_new rt5659_if3_dac_swap_mux =
+ SOC_DAPM_ENUM("IF3 DAC Swap Source", rt5659_if3_dac_enum);
+
+static const struct snd_kcontrol_new rt5659_if3_adc_swap_mux =
+ SOC_DAPM_ENUM("IF3 ADC Swap Source", rt5659_if3_adc_enum);
+
+static const char * const rt5659_asrc_clk_src[] = {
+ "clk_sysy_div_out", "clk_i2s1_track", "clk_i2s2_track",
+ "clk_i2s3_track", "clk_sys2", "clk_sys3"
+};
+
+static unsigned int rt5659_asrc_clk_map_values[] = {
+ 0, 1, 2, 3, 5, 6,
+};
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(
+ rt5659_da_sto_asrc_enum, RT5659_ASRC_2, RT5659_DA_STO_T_SFT, 0x7,
+ rt5659_asrc_clk_src, rt5659_asrc_clk_map_values);
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(
+ rt5659_da_monol_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_L_T_SFT, 0x7,
+ rt5659_asrc_clk_src, rt5659_asrc_clk_map_values);
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(
+ rt5659_da_monor_asrc_enum, RT5659_ASRC_2, RT5659_DA_MONO_R_T_SFT, 0x7,
+ rt5659_asrc_clk_src, rt5659_asrc_clk_map_values);
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(
+ rt5659_ad_sto1_asrc_enum, RT5659_ASRC_2, RT5659_AD_STO1_T_SFT, 0x7,
+ rt5659_asrc_clk_src, rt5659_asrc_clk_map_values);
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(
+ rt5659_ad_sto2_asrc_enum, RT5659_ASRC_3, RT5659_AD_STO2_T_SFT, 0x7,
+ rt5659_asrc_clk_src, rt5659_asrc_clk_map_values);
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(
+ rt5659_ad_monol_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_L_T_SFT, 0x7,
+ rt5659_asrc_clk_src, rt5659_asrc_clk_map_values);
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(
+ rt5659_ad_monor_asrc_enum, RT5659_ASRC_3, RT5659_AD_MONO_R_T_SFT, 0x7,
+ rt5659_asrc_clk_src, rt5659_asrc_clk_map_values);
+
+static int rt5659_hp_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ int ret = snd_soc_put_volsw(kcontrol, ucontrol);
+
+ if (snd_soc_read(codec, RT5659_STO_NG2_CTRL_1) & RT5659_NG2_EN) {
+ snd_soc_update_bits(codec, RT5659_STO_NG2_CTRL_1,
+ RT5659_NG2_EN_MASK, RT5659_NG2_DIS);
+ snd_soc_update_bits(codec, RT5659_STO_NG2_CTRL_1,
+ RT5659_NG2_EN_MASK, RT5659_NG2_EN);
+ }
+
+ return ret;
+}
+
+static void rt5659_enable_push_button_irq(struct snd_soc_codec *codec,
+ bool enable)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+
+ if (enable) {
+ snd_soc_write(codec, RT5659_4BTN_IL_CMD_1, 0x000b);
+
+ /* MICBIAS1 and Mic Det Power for button detect*/
+ snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
+ snd_soc_dapm_force_enable_pin(dapm,
+ "Mic Det Power");
+ snd_soc_dapm_sync(dapm);
+
+ snd_soc_update_bits(codec, RT5659_PWR_ANLG_2,
+ RT5659_PWR_MB1, RT5659_PWR_MB1);
+ snd_soc_update_bits(codec, RT5659_PWR_VOL,
+ RT5659_PWR_MIC_DET, RT5659_PWR_MIC_DET);
+
+ snd_soc_update_bits(codec, RT5659_IRQ_CTRL_2,
+ RT5659_IL_IRQ_MASK, RT5659_IL_IRQ_EN);
+ snd_soc_update_bits(codec, RT5659_4BTN_IL_CMD_2,
+ RT5659_4BTN_IL_MASK, RT5659_4BTN_IL_EN);
+ } else {
+ snd_soc_update_bits(codec, RT5659_4BTN_IL_CMD_2,
+ RT5659_4BTN_IL_MASK, RT5659_4BTN_IL_DIS);
+ snd_soc_update_bits(codec, RT5659_IRQ_CTRL_2,
+ RT5659_IL_IRQ_MASK, RT5659_IL_IRQ_DIS);
+ /* MICBIAS1 and Mic Det Power for button detect*/
+ snd_soc_dapm_disable_pin(dapm, "MICBIAS1");
+ snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
+ snd_soc_dapm_sync(dapm);
+ }
+}
+
+/**
+ * rt5659_headset_detect - Detect headset.
+ * @codec: SoC audio codec device.
+ * @jack_insert: Jack insert or not.
+ *
+ * Detect whether is headset or not when jack inserted.
+ *
+ * Returns detect status.
+ */
+
+static int rt5659_headset_detect(struct snd_soc_codec *codec, int jack_insert)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+ int val, i = 0, sleep_time[5] = {300, 150, 100, 50, 30};
+ int reg_63;
+
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+
+ if (jack_insert) {
+ snd_soc_dapm_force_enable_pin(dapm,
+ "Mic Det Power");
+ snd_soc_dapm_sync(dapm);
+ reg_63 = snd_soc_read(codec, RT5659_PWR_ANLG_1);
+
+ snd_soc_update_bits(codec, RT5659_PWR_ANLG_1,
+ RT5659_PWR_VREF2 | RT5659_PWR_MB,
+ RT5659_PWR_VREF2 | RT5659_PWR_MB);
+ msleep(20);
+ snd_soc_update_bits(codec, RT5659_PWR_ANLG_1,
+ RT5659_PWR_FV2, RT5659_PWR_FV2);
+
+ snd_soc_write(codec, RT5659_EJD_CTRL_2, 0x4160);
+ snd_soc_update_bits(codec, RT5659_EJD_CTRL_1,
+ 0x20, 0x0);
+ msleep(20);
+ snd_soc_update_bits(codec, RT5659_EJD_CTRL_1,
+ 0x20, 0x20);
+
+ while (i < 5) {
+ msleep(sleep_time[i]);
+ val = snd_soc_read(codec, RT5659_EJD_CTRL_2) & 0x0003;
+ i++;
+ if (val == 0x1 || val == 0x2 || val == 0x3)
+ break;
+ }
+
+ switch (val) {
+ case 1:
+ rt5659->jack_type = SND_JACK_HEADSET;
+ rt5659_enable_push_button_irq(codec, true);
+ break;
+ default:
+ snd_soc_write(codec, RT5659_PWR_ANLG_1, reg_63);
+ rt5659->jack_type = SND_JACK_HEADPHONE;
+ snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
+ snd_soc_dapm_sync(dapm);
+ break;
+ }
+ } else {
+ snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
+ snd_soc_dapm_sync(dapm);
+ if (rt5659->jack_type == SND_JACK_HEADSET)
+ rt5659_enable_push_button_irq(codec, false);
+ rt5659->jack_type = 0;
+ }
+
+ dev_dbg(codec->dev, "jack_type = %d\n", rt5659->jack_type);
+ return rt5659->jack_type;
+}
+
+static int rt5659_button_detect(struct snd_soc_codec *codec)
+{
+ int btn_type, val;
+
+ val = snd_soc_read(codec, RT5659_4BTN_IL_CMD_1);
+ btn_type = val & 0xfff0;
+ snd_soc_write(codec, RT5659_4BTN_IL_CMD_1, val);
+
+ return btn_type;
+}
+
+static irqreturn_t rt5659_irq(int irq, void *data)
+{
+ struct rt5659_priv *rt5659 = data;
+
+ queue_delayed_work(system_power_efficient_wq,
+ &rt5659->jack_detect_work, msecs_to_jiffies(250));
+
+ return IRQ_HANDLED;
+}
+
+int rt5659_set_jack_detect(struct snd_soc_codec *codec,
+ struct snd_soc_jack *hs_jack)
+{
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+
+ rt5659->hs_jack = hs_jack;
+
+ rt5659_irq(0, rt5659);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt5659_set_jack_detect);
+
+static void rt5659_jack_detect_work(struct work_struct *work)
+{
+ struct rt5659_priv *rt5659 =
+ container_of(work, struct rt5659_priv, jack_detect_work.work);
+ int val, btn_type, report = 0;
+
+ if (!rt5659->codec)
+ return;
+
+ val = snd_soc_read(rt5659->codec, RT5659_INT_ST_1) & 0x0080;
+ if (!val) {
+ /* jack in */
+ if (rt5659->jack_type == 0) {
+ /* jack was out, report jack type */
+ report = rt5659_headset_detect(rt5659->codec, 1);
+ } else {
+ /* jack is already in, report button event */
+ report = SND_JACK_HEADSET;
+ btn_type = rt5659_button_detect(rt5659->codec);
+ /**
+ * rt5659 can report three kinds of button behavior,
+ * one click, double click and hold. However,
+ * currently we will report button pressed/released
+ * event. So all the three button behaviors are
+ * treated as button pressed.
+ */
+ switch (btn_type) {
+ case 0x8000:
+ case 0x4000:
+ case 0x2000:
+ report |= SND_JACK_BTN_0;
+ break;
+ case 0x1000:
+ case 0x0800:
+ case 0x0400:
+ report |= SND_JACK_BTN_1;
+ break;
+ case 0x0200:
+ case 0x0100:
+ case 0x0080:
+ report |= SND_JACK_BTN_2;
+ break;
+ case 0x0040:
+ case 0x0020:
+ case 0x0010:
+ report |= SND_JACK_BTN_3;
+ break;
+ case 0x0000: /* unpressed */
+ break;
+ default:
+ btn_type = 0;
+ dev_err(rt5659->codec->dev,
+ "Unexpected button code 0x%04x\n",
+ btn_type);
+ break;
+ }
+
+ /* button release or spurious interrput*/
+ if (btn_type == 0)
+ report = rt5659->jack_type;
+ }
+ } else {
+ /* jack out */
+ report = rt5659_headset_detect(rt5659->codec, 0);
+ }
+
+ snd_soc_jack_report(rt5659->hs_jack, report, SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3);
+}
+
+static const struct snd_kcontrol_new rt5659_snd_controls[] = {
+ /* Speaker Output Volume */
+ SOC_DOUBLE_TLV("Speaker Playback Volume", RT5659_SPO_VOL,
+ RT5659_L_VOL_SFT, RT5659_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+ /* Headphone Output Volume */
+ SOC_DOUBLE_R_EXT_TLV("Headphone Playback Volume", RT5659_HPL_GAIN,
+ RT5659_HPR_GAIN, RT5659_G_HP_SFT, 31, 1, snd_soc_get_volsw,
+ rt5659_hp_vol_put, hp_vol_tlv),
+
+ /* Mono Output Volume */
+ SOC_SINGLE_TLV("Mono Playback Volume", RT5659_MONO_OUT,
+ RT5659_L_VOL_SFT, 39, 1, out_vol_tlv),
+
+ /* Output Volume */
+ SOC_DOUBLE_TLV("OUT Playback Volume", RT5659_LOUT,
+ RT5659_L_VOL_SFT, RT5659_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+ /* DAC Digital Volume */
+ SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5659_DAC1_DIG_VOL,
+ RT5659_L_VOL_SFT, RT5659_R_VOL_SFT, 175, 0, dac_vol_tlv),
+ SOC_DOUBLE("DAC1 Playback Switch", RT5659_AD_DA_MIXER,
+ RT5659_M_DAC1_L_SFT, RT5659_M_DAC1_R_SFT, 1, 1),
+
+ SOC_DOUBLE_TLV("DAC2 Playback Volume", RT5659_DAC2_DIG_VOL,
+ RT5659_L_VOL_SFT, RT5659_R_VOL_SFT, 175, 0, dac_vol_tlv),
+ SOC_DOUBLE("DAC2 Playback Switch", RT5659_DAC_CTRL,
+ RT5659_M_DAC2_L_VOL_SFT, RT5659_M_DAC2_R_VOL_SFT, 1, 1),
+
+ /* IN1/IN2/IN3/IN4 Volume */
+ SOC_SINGLE_TLV("IN1 Boost Volume", RT5659_IN1_IN2,
+ RT5659_BST1_SFT, 69, 0, in_bst_tlv),
+ SOC_SINGLE_TLV("IN2 Boost Volume", RT5659_IN1_IN2,
+ RT5659_BST2_SFT, 69, 0, in_bst_tlv),
+ SOC_SINGLE_TLV("IN3 Boost Volume", RT5659_IN3_IN4,
+ RT5659_BST3_SFT, 69, 0, in_bst_tlv),
+ SOC_SINGLE_TLV("IN4 Boost Volume", RT5659_IN3_IN4,
+ RT5659_BST4_SFT, 69, 0, in_bst_tlv),
+
+ /* INL/INR Volume Control */
+ SOC_DOUBLE_TLV("IN Capture Volume", RT5659_INL1_INR1_VOL,
+ RT5659_INL_VOL_SFT, RT5659_INR_VOL_SFT, 31, 1, in_vol_tlv),
+
+ /* ADC Digital Volume Control */
+ SOC_DOUBLE("STO1 ADC Capture Switch", RT5659_STO1_ADC_DIG_VOL,
+ RT5659_L_MUTE_SFT, RT5659_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE_TLV("STO1 ADC Capture Volume", RT5659_STO1_ADC_DIG_VOL,
+ RT5659_L_VOL_SFT, RT5659_R_VOL_SFT, 127, 0, adc_vol_tlv),
+ SOC_DOUBLE("Mono ADC Capture Switch", RT5659_MONO_ADC_DIG_VOL,
+ RT5659_L_MUTE_SFT, RT5659_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5659_MONO_ADC_DIG_VOL,
+ RT5659_L_VOL_SFT, RT5659_R_VOL_SFT, 127, 0, adc_vol_tlv),
+ SOC_DOUBLE("STO2 ADC Capture Switch", RT5659_STO2_ADC_DIG_VOL,
+ RT5659_L_MUTE_SFT, RT5659_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE_TLV("STO2 ADC Capture Volume", RT5659_STO2_ADC_DIG_VOL,
+ RT5659_L_VOL_SFT, RT5659_R_VOL_SFT, 127, 0, adc_vol_tlv),
+
+ /* ADC Boost Volume Control */
+ SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5659_STO1_BOOST,
+ RT5659_STO1_ADC_L_BST_SFT, RT5659_STO1_ADC_R_BST_SFT,
+ 3, 0, adc_bst_tlv),
+
+ SOC_DOUBLE_TLV("Mono ADC Boost Gain Volume", RT5659_MONO_BOOST,
+ RT5659_MONO_ADC_L_BST_SFT, RT5659_MONO_ADC_R_BST_SFT,
+ 3, 0, adc_bst_tlv),
+
+ SOC_DOUBLE_TLV("STO2 ADC Boost Gain Volume", RT5659_STO2_BOOST,
+ RT5659_STO2_ADC_L_BST_SFT, RT5659_STO2_ADC_R_BST_SFT,
+ 3, 0, adc_bst_tlv),
+
+ SOC_SINGLE("DAC IF1 DAC1 L Data Switch", RT5659_TDM_CTRL_4, 12, 7, 0),
+ SOC_SINGLE("DAC IF1 DAC1 R Data Switch", RT5659_TDM_CTRL_4, 8, 7, 0),
+ SOC_SINGLE("DAC IF1 DAC2 L Data Switch", RT5659_TDM_CTRL_4, 4, 7, 0),
+ SOC_SINGLE("DAC IF1 DAC2 R Data Switch", RT5659_TDM_CTRL_4, 0, 7, 0),
+};
+
+/**
+ * set_dmic_clk - Set parameter of dmic.
+ *
+ * @w: DAPM widget.
+ * @kcontrol: The kcontrol of this widget.
+ * @event: Event id.
+ *
+ * Choose dmic clock between 1MHz and 3MHz.
+ * It is better for clock to approximate 3MHz.
+ */
+static int set_dmic_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+ int pd, idx = -EINVAL;
+
+ pd = rl6231_get_pre_div(rt5659->regmap,
+ RT5659_ADDA_CLK_1, RT5659_I2S_PD1_SFT);
+ idx = rl6231_calc_dmic_clk(rt5659->sysclk / pd);
+
+ if (idx < 0)
+ dev_err(codec->dev, "Failed to set DMIC clock\n");
+ else {
+ snd_soc_update_bits(codec, RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_CLK_MASK, idx << RT5659_DMIC_CLK_SFT);
+ }
+ return idx;
+}
+
+static int set_adc_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, RT5659_CHOP_ADC,
+ RT5659_CKXEN_ADCC_MASK | RT5659_CKGEN_ADCC_MASK,
+ RT5659_CKXEN_ADCC_MASK | RT5659_CKGEN_ADCC_MASK);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, RT5659_CHOP_ADC,
+ RT5659_CKXEN_ADCC_MASK | RT5659_CKGEN_ADCC_MASK, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+
+}
+
+static int rt5659_charge_pump_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Depop */
+ snd_soc_write(codec, RT5659_DEPOP_1, 0x0009);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_write(codec, RT5659_HP_CHARGE_PUMP_1, 0x0c16);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *w,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int val;
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ val = snd_soc_read(codec, RT5659_GLB_CLK);
+ val &= RT5659_SCLK_SRC_MASK;
+ if (val == RT5659_SCLK_SRC_PLL1)
+ return 1;
+ else
+ return 0;
+}
+
+static int is_using_asrc(struct snd_soc_dapm_widget *w,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int reg, shift, val;
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (w->shift) {
+ case RT5659_ADC_MONO_R_ASRC_SFT:
+ reg = RT5659_ASRC_3;
+ shift = RT5659_AD_MONO_R_T_SFT;
+ break;
+ case RT5659_ADC_MONO_L_ASRC_SFT:
+ reg = RT5659_ASRC_3;
+ shift = RT5659_AD_MONO_L_T_SFT;
+ break;
+ case RT5659_ADC_STO1_ASRC_SFT:
+ reg = RT5659_ASRC_2;
+ shift = RT5659_AD_STO1_T_SFT;
+ break;
+ case RT5659_DAC_MONO_R_ASRC_SFT:
+ reg = RT5659_ASRC_2;
+ shift = RT5659_DA_MONO_R_T_SFT;
+ break;
+ case RT5659_DAC_MONO_L_ASRC_SFT:
+ reg = RT5659_ASRC_2;
+ shift = RT5659_DA_MONO_L_T_SFT;
+ break;
+ case RT5659_DAC_STO_ASRC_SFT:
+ reg = RT5659_ASRC_2;
+ shift = RT5659_DA_STO_T_SFT;
+ break;
+ default:
+ return 0;
+ }
+
+ val = (snd_soc_read(codec, reg) >> shift) & 0xf;
+ switch (val) {
+ case 1:
+ case 2:
+ case 3:
+ /* I2S_Pre_Div1 should be 1 in asrc mode */
+ snd_soc_update_bits(codec, RT5659_ADDA_CLK_1,
+ RT5659_I2S_PD1_MASK, RT5659_I2S_PD1_2);
+ return 1;
+ default:
+ return 0;
+ }
+
+}
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt5659_sto1_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5659_STO1_ADC_MIXER,
+ RT5659_M_STO1_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5659_STO1_ADC_MIXER,
+ RT5659_M_STO1_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_sto1_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5659_STO1_ADC_MIXER,
+ RT5659_M_STO1_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5659_STO1_ADC_MIXER,
+ RT5659_M_STO1_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_mono_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5659_MONO_ADC_MIXER,
+ RT5659_M_MONO_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5659_MONO_ADC_MIXER,
+ RT5659_M_MONO_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_mono_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5659_MONO_ADC_MIXER,
+ RT5659_M_MONO_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5659_MONO_ADC_MIXER,
+ RT5659_M_MONO_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5659_AD_DA_MIXER,
+ RT5659_M_ADCMIX_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5659_AD_DA_MIXER,
+ RT5659_M_DAC1_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5659_AD_DA_MIXER,
+ RT5659_M_ADCMIX_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC1 Switch", RT5659_AD_DA_MIXER,
+ RT5659_M_DAC1_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_sto_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5659_STO_DAC_MIXER,
+ RT5659_M_DAC_L1_STO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5659_STO_DAC_MIXER,
+ RT5659_M_DAC_R1_STO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_STO_DAC_MIXER,
+ RT5659_M_DAC_L2_STO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5659_STO_DAC_MIXER,
+ RT5659_M_DAC_R2_STO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_sto_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5659_STO_DAC_MIXER,
+ RT5659_M_DAC_L1_STO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5659_STO_DAC_MIXER,
+ RT5659_M_DAC_R1_STO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_STO_DAC_MIXER,
+ RT5659_M_DAC_L2_STO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5659_STO_DAC_MIXER,
+ RT5659_M_DAC_R2_STO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_mono_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5659_MONO_DAC_MIXER,
+ RT5659_M_DAC_L1_MONO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5659_MONO_DAC_MIXER,
+ RT5659_M_DAC_R1_MONO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_MONO_DAC_MIXER,
+ RT5659_M_DAC_L2_MONO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5659_MONO_DAC_MIXER,
+ RT5659_M_DAC_R2_MONO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_mono_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5659_MONO_DAC_MIXER,
+ RT5659_M_DAC_L1_MONO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5659_MONO_DAC_MIXER,
+ RT5659_M_DAC_R1_MONO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_MONO_DAC_MIXER,
+ RT5659_M_DAC_L2_MONO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5659_MONO_DAC_MIXER,
+ RT5659_M_DAC_R2_MONO_R_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt5659_rec1_l_mix[] = {
+ SOC_DAPM_SINGLE("SPKVOLL Switch", RT5659_REC1_L2_MIXER,
+ RT5659_M_SPKVOLL_RM1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5659_REC1_L2_MIXER,
+ RT5659_M_INL_RM1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST4 Switch", RT5659_REC1_L2_MIXER,
+ RT5659_M_BST4_RM1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5659_REC1_L2_MIXER,
+ RT5659_M_BST3_RM1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5659_REC1_L2_MIXER,
+ RT5659_M_BST2_RM1_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5659_REC1_L2_MIXER,
+ RT5659_M_BST1_RM1_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_rec1_r_mix[] = {
+ SOC_DAPM_SINGLE("HPOVOLR Switch", RT5659_REC1_L2_MIXER,
+ RT5659_M_HPOVOLR_RM1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5659_REC1_R2_MIXER,
+ RT5659_M_INR_RM1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST4 Switch", RT5659_REC1_R2_MIXER,
+ RT5659_M_BST4_RM1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5659_REC1_R2_MIXER,
+ RT5659_M_BST3_RM1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5659_REC1_R2_MIXER,
+ RT5659_M_BST2_RM1_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5659_REC1_R2_MIXER,
+ RT5659_M_BST1_RM1_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_rec2_l_mix[] = {
+ SOC_DAPM_SINGLE("SPKVOLL Switch", RT5659_REC2_L2_MIXER,
+ RT5659_M_SPKVOL_RM2_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOLL Switch", RT5659_REC2_L2_MIXER,
+ RT5659_M_OUTVOLL_RM2_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST4 Switch", RT5659_REC2_L2_MIXER,
+ RT5659_M_BST4_RM2_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5659_REC2_L2_MIXER,
+ RT5659_M_BST3_RM2_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5659_REC2_L2_MIXER,
+ RT5659_M_BST2_RM2_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5659_REC2_L2_MIXER,
+ RT5659_M_BST1_RM2_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_rec2_r_mix[] = {
+ SOC_DAPM_SINGLE("MONOVOL Switch", RT5659_REC2_R2_MIXER,
+ RT5659_M_MONOVOL_RM2_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOLR Switch", RT5659_REC2_R2_MIXER,
+ RT5659_M_OUTVOLR_RM2_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST4 Switch", RT5659_REC2_R2_MIXER,
+ RT5659_M_BST4_RM2_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5659_REC2_R2_MIXER,
+ RT5659_M_BST3_RM2_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5659_REC2_R2_MIXER,
+ RT5659_M_BST2_RM2_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5659_REC2_R2_MIXER,
+ RT5659_M_BST1_RM2_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_spk_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_SPK_L_MIXER,
+ RT5659_M_DAC_L2_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5659_SPK_L_MIXER,
+ RT5659_M_BST1_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5659_SPK_L_MIXER,
+ RT5659_M_IN_L_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5659_SPK_L_MIXER,
+ RT5659_M_IN_R_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5659_SPK_L_MIXER,
+ RT5659_M_BST3_SM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_spk_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5659_SPK_R_MIXER,
+ RT5659_M_DAC_R2_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST4 Switch", RT5659_SPK_R_MIXER,
+ RT5659_M_BST4_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5659_SPK_R_MIXER,
+ RT5659_M_IN_L_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5659_SPK_R_MIXER,
+ RT5659_M_IN_R_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5659_SPK_R_MIXER,
+ RT5659_M_BST3_SM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_monovol_mix[] = {
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_MONOMIX_IN_GAIN,
+ RT5659_M_DAC_L2_MM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5659_MONOMIX_IN_GAIN,
+ RT5659_M_DAC_R2_MM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5659_MONOMIX_IN_GAIN,
+ RT5659_M_BST1_MM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5659_MONOMIX_IN_GAIN,
+ RT5659_M_BST2_MM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5659_MONOMIX_IN_GAIN,
+ RT5659_M_BST3_MM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_out_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_OUT_L_MIXER,
+ RT5659_M_DAC_L2_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5659_OUT_L_MIXER,
+ RT5659_M_IN_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5659_OUT_L_MIXER,
+ RT5659_M_BST1_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5659_OUT_L_MIXER,
+ RT5659_M_BST2_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5659_OUT_L_MIXER,
+ RT5659_M_BST3_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_out_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5659_OUT_R_MIXER,
+ RT5659_M_DAC_R2_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5659_OUT_R_MIXER,
+ RT5659_M_IN_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5659_OUT_R_MIXER,
+ RT5659_M_BST2_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST3 Switch", RT5659_OUT_R_MIXER,
+ RT5659_M_BST3_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST4 Switch", RT5659_OUT_R_MIXER,
+ RT5659_M_BST4_OM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_spo_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_SPO_AMP_GAIN,
+ RT5659_M_DAC_L2_SPKOMIX_SFT, 1, 0),
+ SOC_DAPM_SINGLE("SPKVOL L Switch", RT5659_SPO_AMP_GAIN,
+ RT5659_M_SPKVOLL_SPKOMIX_SFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new rt5659_spo_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5659_SPO_AMP_GAIN,
+ RT5659_M_DAC_R2_SPKOMIX_SFT, 1, 0),
+ SOC_DAPM_SINGLE("SPKVOL R Switch", RT5659_SPO_AMP_GAIN,
+ RT5659_M_SPKVOLR_SPKOMIX_SFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new rt5659_mono_mix[] = {
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_MONOMIX_IN_GAIN,
+ RT5659_M_DAC_L2_MA_SFT, 1, 1),
+ SOC_DAPM_SINGLE("MONOVOL Switch", RT5659_MONOMIX_IN_GAIN,
+ RT5659_M_MONOVOL_MA_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_lout_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5659_LOUT_MIXER,
+ RT5659_M_DAC_L2_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL L Switch", RT5659_LOUT_MIXER,
+ RT5659_M_OV_L_LM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5659_lout_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5659_LOUT_MIXER,
+ RT5659_M_DAC_R2_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL R Switch", RT5659_LOUT_MIXER,
+ RT5659_M_OV_R_LM_SFT, 1, 1),
+};
+
+/*DAC L2, DAC R2*/
+/*MX-1B [6:4], MX-1B [2:0]*/
+static const char * const rt5659_dac2_src[] = {
+ "IF1 DAC2", "IF2 DAC", "IF3 DAC", "Mono ADC MIX"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_dac_l2_enum, RT5659_DAC_CTRL,
+ RT5659_DAC_L2_SEL_SFT, rt5659_dac2_src);
+
+static const struct snd_kcontrol_new rt5659_dac_l2_mux =
+ SOC_DAPM_ENUM("DAC L2 Source", rt5659_dac_l2_enum);
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_dac_r2_enum, RT5659_DAC_CTRL,
+ RT5659_DAC_R2_SEL_SFT, rt5659_dac2_src);
+
+static const struct snd_kcontrol_new rt5659_dac_r2_mux =
+ SOC_DAPM_ENUM("DAC R2 Source", rt5659_dac_r2_enum);
+
+
+/* STO1 ADC1 Source */
+/* MX-26 [13] */
+static const char * const rt5659_sto1_adc1_src[] = {
+ "DAC MIX", "ADC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_sto1_adc1_enum, RT5659_STO1_ADC_MIXER,
+ RT5659_STO1_ADC1_SRC_SFT, rt5659_sto1_adc1_src);
+
+static const struct snd_kcontrol_new rt5659_sto1_adc1_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC1 Source", rt5659_sto1_adc1_enum);
+
+/* STO1 ADC Source */
+/* MX-26 [12] */
+static const char * const rt5659_sto1_adc_src[] = {
+ "ADC1", "ADC2"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_sto1_adc_enum, RT5659_STO1_ADC_MIXER,
+ RT5659_STO1_ADC_SRC_SFT, rt5659_sto1_adc_src);
+
+static const struct snd_kcontrol_new rt5659_sto1_adc_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC Source", rt5659_sto1_adc_enum);
+
+/* STO1 ADC2 Source */
+/* MX-26 [11] */
+static const char * const rt5659_sto1_adc2_src[] = {
+ "DAC MIX", "DMIC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_sto1_adc2_enum, RT5659_STO1_ADC_MIXER,
+ RT5659_STO1_ADC2_SRC_SFT, rt5659_sto1_adc2_src);
+
+static const struct snd_kcontrol_new rt5659_sto1_adc2_mux =
+ SOC_DAPM_ENUM("Stereo1 ADC2 Source", rt5659_sto1_adc2_enum);
+
+/* STO1 DMIC Source */
+/* MX-26 [8] */
+static const char * const rt5659_sto1_dmic_src[] = {
+ "DMIC1", "DMIC2"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_sto1_dmic_enum, RT5659_STO1_ADC_MIXER,
+ RT5659_STO1_DMIC_SRC_SFT, rt5659_sto1_dmic_src);
+
+static const struct snd_kcontrol_new rt5659_sto1_dmic_mux =
+ SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5659_sto1_dmic_enum);
+
+
+/* MONO ADC L2 Source */
+/* MX-27 [12] */
+static const char * const rt5659_mono_adc_l2_src[] = {
+ "Mono DAC MIXL", "DMIC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_mono_adc_l2_enum, RT5659_MONO_ADC_MIXER,
+ RT5659_MONO_ADC_L2_SRC_SFT, rt5659_mono_adc_l2_src);
+
+static const struct snd_kcontrol_new rt5659_mono_adc_l2_mux =
+ SOC_DAPM_ENUM("Mono ADC L2 Source", rt5659_mono_adc_l2_enum);
+
+
+/* MONO ADC L1 Source */
+/* MX-27 [11] */
+static const char * const rt5659_mono_adc_l1_src[] = {
+ "Mono DAC MIXL", "ADC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_mono_adc_l1_enum, RT5659_MONO_ADC_MIXER,
+ RT5659_MONO_ADC_L1_SRC_SFT, rt5659_mono_adc_l1_src);
+
+static const struct snd_kcontrol_new rt5659_mono_adc_l1_mux =
+ SOC_DAPM_ENUM("Mono ADC L1 Source", rt5659_mono_adc_l1_enum);
+
+/* MONO ADC L Source, MONO ADC R Source*/
+/* MX-27 [10:9], MX-27 [2:1] */
+static const char * const rt5659_mono_adc_src[] = {
+ "ADC1 L", "ADC1 R", "ADC2 L", "ADC2 R"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_mono_adc_l_enum, RT5659_MONO_ADC_MIXER,
+ RT5659_MONO_ADC_L_SRC_SFT, rt5659_mono_adc_src);
+
+static const struct snd_kcontrol_new rt5659_mono_adc_l_mux =
+ SOC_DAPM_ENUM("Mono ADC L Source", rt5659_mono_adc_l_enum);
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_mono_adcr_enum, RT5659_MONO_ADC_MIXER,
+ RT5659_MONO_ADC_R_SRC_SFT, rt5659_mono_adc_src);
+
+static const struct snd_kcontrol_new rt5659_mono_adc_r_mux =
+ SOC_DAPM_ENUM("Mono ADC R Source", rt5659_mono_adcr_enum);
+
+/* MONO DMIC L Source */
+/* MX-27 [8] */
+static const char * const rt5659_mono_dmic_l_src[] = {
+ "DMIC1 L", "DMIC2 L"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_mono_dmic_l_enum, RT5659_MONO_ADC_MIXER,
+ RT5659_MONO_DMIC_L_SRC_SFT, rt5659_mono_dmic_l_src);
+
+static const struct snd_kcontrol_new rt5659_mono_dmic_l_mux =
+ SOC_DAPM_ENUM("Mono DMIC L Source", rt5659_mono_dmic_l_enum);
+
+/* MONO ADC R2 Source */
+/* MX-27 [4] */
+static const char * const rt5659_mono_adc_r2_src[] = {
+ "Mono DAC MIXR", "DMIC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_mono_adc_r2_enum, RT5659_MONO_ADC_MIXER,
+ RT5659_MONO_ADC_R2_SRC_SFT, rt5659_mono_adc_r2_src);
+
+static const struct snd_kcontrol_new rt5659_mono_adc_r2_mux =
+ SOC_DAPM_ENUM("Mono ADC R2 Source", rt5659_mono_adc_r2_enum);
+
+/* MONO ADC R1 Source */
+/* MX-27 [3] */
+static const char * const rt5659_mono_adc_r1_src[] = {
+ "Mono DAC MIXR", "ADC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_mono_adc_r1_enum, RT5659_MONO_ADC_MIXER,
+ RT5659_MONO_ADC_R1_SRC_SFT, rt5659_mono_adc_r1_src);
+
+static const struct snd_kcontrol_new rt5659_mono_adc_r1_mux =
+ SOC_DAPM_ENUM("Mono ADC R1 Source", rt5659_mono_adc_r1_enum);
+
+/* MONO DMIC R Source */
+/* MX-27 [0] */
+static const char * const rt5659_mono_dmic_r_src[] = {
+ "DMIC1 R", "DMIC2 R"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_mono_dmic_r_enum, RT5659_MONO_ADC_MIXER,
+ RT5659_MONO_DMIC_R_SRC_SFT, rt5659_mono_dmic_r_src);
+
+static const struct snd_kcontrol_new rt5659_mono_dmic_r_mux =
+ SOC_DAPM_ENUM("Mono DMIC R Source", rt5659_mono_dmic_r_enum);
+
+
+/* DAC R1 Source, DAC L1 Source*/
+/* MX-29 [11:10], MX-29 [9:8]*/
+static const char * const rt5659_dac1_src[] = {
+ "IF1 DAC1", "IF2 DAC", "IF3 DAC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_dac_r1_enum, RT5659_AD_DA_MIXER,
+ RT5659_DAC1_R_SEL_SFT, rt5659_dac1_src);
+
+static const struct snd_kcontrol_new rt5659_dac_r1_mux =
+ SOC_DAPM_ENUM("DAC R1 Source", rt5659_dac_r1_enum);
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_dac_l1_enum, RT5659_AD_DA_MIXER,
+ RT5659_DAC1_L_SEL_SFT, rt5659_dac1_src);
+
+static const struct snd_kcontrol_new rt5659_dac_l1_mux =
+ SOC_DAPM_ENUM("DAC L1 Source", rt5659_dac_l1_enum);
+
+/* DAC Digital Mixer L Source, DAC Digital Mixer R Source*/
+/* MX-2C [6], MX-2C [4]*/
+static const char * const rt5659_dig_dac_mix_src[] = {
+ "Stereo DAC Mixer", "Mono DAC Mixer"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_dig_dac_mixl_enum, RT5659_DIG_MIXER,
+ RT5659_DAC_MIX_L_SFT, rt5659_dig_dac_mix_src);
+
+static const struct snd_kcontrol_new rt5659_dig_dac_mixl_mux =
+ SOC_DAPM_ENUM("DAC Digital Mixer L Source", rt5659_dig_dac_mixl_enum);
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_dig_dac_mixr_enum, RT5659_DIG_MIXER,
+ RT5659_DAC_MIX_R_SFT, rt5659_dig_dac_mix_src);
+
+static const struct snd_kcontrol_new rt5659_dig_dac_mixr_mux =
+ SOC_DAPM_ENUM("DAC Digital Mixer R Source", rt5659_dig_dac_mixr_enum);
+
+/* Analog DAC L1 Source, Analog DAC R1 Source*/
+/* MX-2D [3], MX-2D [2]*/
+static const char * const rt5659_alg_dac1_src[] = {
+ "DAC", "Stereo DAC Mixer"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_alg_dac_l1_enum, RT5659_A_DAC_MUX,
+ RT5659_A_DACL1_SFT, rt5659_alg_dac1_src);
+
+static const struct snd_kcontrol_new rt5659_alg_dac_l1_mux =
+ SOC_DAPM_ENUM("Analog DACL1 Source", rt5659_alg_dac_l1_enum);
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_alg_dac_r1_enum, RT5659_A_DAC_MUX,
+ RT5659_A_DACR1_SFT, rt5659_alg_dac1_src);
+
+static const struct snd_kcontrol_new rt5659_alg_dac_r1_mux =
+ SOC_DAPM_ENUM("Analog DACR1 Source", rt5659_alg_dac_r1_enum);
+
+/* Analog DAC LR Source, Analog DAC R2 Source*/
+/* MX-2D [1], MX-2D [0]*/
+static const char * const rt5659_alg_dac2_src[] = {
+ "Stereo DAC Mixer", "Mono DAC Mixer"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_alg_dac_l2_enum, RT5659_A_DAC_MUX,
+ RT5659_A_DACL2_SFT, rt5659_alg_dac2_src);
+
+static const struct snd_kcontrol_new rt5659_alg_dac_l2_mux =
+ SOC_DAPM_ENUM("Analog DAC L2 Source", rt5659_alg_dac_l2_enum);
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_alg_dac_r2_enum, RT5659_A_DAC_MUX,
+ RT5659_A_DACR2_SFT, rt5659_alg_dac2_src);
+
+static const struct snd_kcontrol_new rt5659_alg_dac_r2_mux =
+ SOC_DAPM_ENUM("Analog DAC R2 Source", rt5659_alg_dac_r2_enum);
+
+/* Interface2 ADC Data Input*/
+/* MX-2F [13:12] */
+static const char * const rt5659_if2_adc_in_src[] = {
+ "IF_ADC1", "IF_ADC2", "DAC_REF", "IF_ADC3"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_if2_adc_in_enum, RT5659_DIG_INF23_DATA,
+ RT5659_IF2_ADC_IN_SFT, rt5659_if2_adc_in_src);
+
+static const struct snd_kcontrol_new rt5659_if2_adc_in_mux =
+ SOC_DAPM_ENUM("IF2 ADC IN Source", rt5659_if2_adc_in_enum);
+
+/* Interface3 ADC Data Input*/
+/* MX-2F [1:0] */
+static const char * const rt5659_if3_adc_in_src[] = {
+ "IF_ADC1", "IF_ADC2", "DAC_REF", "Stereo2_ADC_L/R"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_if3_adc_in_enum, RT5659_DIG_INF23_DATA,
+ RT5659_IF3_ADC_IN_SFT, rt5659_if3_adc_in_src);
+
+static const struct snd_kcontrol_new rt5659_if3_adc_in_mux =
+ SOC_DAPM_ENUM("IF3 ADC IN Source", rt5659_if3_adc_in_enum);
+
+/* PDM 1 L/R*/
+/* MX-31 [15] [13] */
+static const char * const rt5659_pdm_src[] = {
+ "Mono DAC", "Stereo DAC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_pdm_l_enum, RT5659_PDM_OUT_CTRL,
+ RT5659_PDM1_L_SFT, rt5659_pdm_src);
+
+static const struct snd_kcontrol_new rt5659_pdm_l_mux =
+ SOC_DAPM_ENUM("PDM L Source", rt5659_pdm_l_enum);
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_pdm_r_enum, RT5659_PDM_OUT_CTRL,
+ RT5659_PDM1_R_SFT, rt5659_pdm_src);
+
+static const struct snd_kcontrol_new rt5659_pdm_r_mux =
+ SOC_DAPM_ENUM("PDM R Source", rt5659_pdm_r_enum);
+
+/* SPDIF Output source*/
+/* MX-36 [1:0] */
+static const char * const rt5659_spdif_src[] = {
+ "IF1_DAC1", "IF1_DAC2", "IF2_DAC", "IF3_DAC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_spdif_enum, RT5659_SPDIF_CTRL,
+ RT5659_SPDIF_SEL_SFT, rt5659_spdif_src);
+
+static const struct snd_kcontrol_new rt5659_spdif_mux =
+ SOC_DAPM_ENUM("SPDIF Source", rt5659_spdif_enum);
+
+/* I2S1 TDM ADCDAT Source */
+/* MX-78[4:0] */
+static const char * const rt5659_rx_adc_data_src[] = {
+ "AD1:AD2:DAC:NUL", "AD1:AD2:NUL:DAC", "AD1:DAC:AD2:NUL",
+ "AD1:DAC:NUL:AD2", "AD1:NUL:DAC:AD2", "AD1:NUL:AD2:DAC",
+ "AD2:AD1:DAC:NUL", "AD2:AD1:NUL:DAC", "AD2:DAC:AD1:NUL",
+ "AD2:DAC:NUL:AD1", "AD2:NUL:DAC:AD1", "AD1:NUL:AD1:DAC",
+ "DAC:AD1:AD2:NUL", "DAC:AD1:NUL:AD2", "DAC:AD2:AD1:NUL",
+ "DAC:AD2:NUL:AD1", "DAC:NUL:DAC:AD2", "DAC:NUL:AD2:DAC",
+ "NUL:AD1:AD2:DAC", "NUL:AD1:DAC:AD2", "NUL:AD2:AD1:DAC",
+ "NUL:AD2:DAC:AD1", "NUL:DAC:DAC:AD2", "NUL:DAC:AD2:DAC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5659_rx_adc_data_enum, RT5659_TDM_CTRL_2,
+ RT5659_ADCDAT_SRC_SFT, rt5659_rx_adc_data_src);
+
+static const struct snd_kcontrol_new rt5659_rx_adc_dac_mux =
+ SOC_DAPM_ENUM("TDM ADCDAT Source", rt5659_rx_adc_data_enum);
+
+/* Out Volume Switch */
+static const struct snd_kcontrol_new spkvol_l_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_SPO_VOL, RT5659_VOL_L_SFT, 1, 1);
+
+static const struct snd_kcontrol_new spkvol_r_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_SPO_VOL, RT5659_VOL_R_SFT, 1, 1);
+
+static const struct snd_kcontrol_new monovol_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_MONO_OUT, RT5659_VOL_L_SFT, 1, 1);
+
+static const struct snd_kcontrol_new outvol_l_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_LOUT, RT5659_VOL_L_SFT, 1, 1);
+
+static const struct snd_kcontrol_new outvol_r_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_LOUT, RT5659_VOL_R_SFT, 1, 1);
+
+/* Out Switch */
+static const struct snd_kcontrol_new spo_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_CLASSD_2, RT5659_M_RF_DIG_SFT, 1, 1);
+
+static const struct snd_kcontrol_new mono_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_MONO_OUT, RT5659_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpo_l_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_HP_VOL, RT5659_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpo_r_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_HP_VOL, RT5659_R_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new lout_l_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_LOUT, RT5659_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new lout_r_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_LOUT, RT5659_R_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new pdm_l_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_PDM_OUT_CTRL, RT5659_M_PDM1_L_SFT, 1,
+ 1);
+
+static const struct snd_kcontrol_new pdm_r_switch =
+ SOC_DAPM_SINGLE("Switch", RT5659_PDM_OUT_CTRL, RT5659_M_PDM1_R_SFT, 1,
+ 1);
+
+static int rt5659_spk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, RT5659_CLASSD_CTRL_1,
+ RT5659_POW_CLSD_DB_MASK, RT5659_POW_CLSD_DB_EN);
+ snd_soc_update_bits(codec, RT5659_CLASSD_2,
+ RT5659_M_RI_DIG, RT5659_M_RI_DIG);
+ snd_soc_write(codec, RT5659_CLASSD_1, 0x0803);
+ snd_soc_write(codec, RT5659_SPK_DC_CAILB_CTRL_3, 0x0000);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_write(codec, RT5659_CLASSD_1, 0x0011);
+ snd_soc_update_bits(codec, RT5659_CLASSD_2,
+ RT5659_M_RI_DIG, 0x0);
+ snd_soc_write(codec, RT5659_SPK_DC_CAILB_CTRL_3, 0x0003);
+ snd_soc_update_bits(codec, RT5659_CLASSD_CTRL_1,
+ RT5659_POW_CLSD_DB_MASK, RT5659_POW_CLSD_DB_DIS);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+
+}
+
+static int rt5659_mono_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_write(codec, RT5659_MONO_AMP_CALIB_CTRL_1, 0x1e00);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_write(codec, RT5659_MONO_AMP_CALIB_CTRL_1, 0x1e04);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+
+}
+
+static int rt5659_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_write(codec, RT5659_HP_CHARGE_PUMP_1, 0x0e1e);
+ snd_soc_update_bits(codec, RT5659_DEPOP_1, 0x0010, 0x0010);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_write(codec, RT5659_DEPOP_1, 0x0000);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int set_dmic_power(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /*Add delay to avoid pop noise*/
+ msleep(450);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget rt5659_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("LDO2", RT5659_PWR_ANLG_3, RT5659_PWR_LDO2_BIT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("PLL", RT5659_PWR_ANLG_3, RT5659_PWR_PLL_BIT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5659_PWR_VOL,
+ RT5659_PWR_MIC_DET_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Mono Vref", RT5659_PWR_ANLG_1,
+ RT5659_PWR_VREF3_BIT, 0, NULL, 0),
+
+ /* ASRC */
+ SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5659_ASRC_1,
+ RT5659_I2S1_ASRC_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5659_ASRC_1,
+ RT5659_I2S2_ASRC_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2S3 ASRC", 1, RT5659_ASRC_1,
+ RT5659_I2S3_ASRC_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5659_ASRC_1,
+ RT5659_DAC_STO_ASRC_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DAC Mono L ASRC", 1, RT5659_ASRC_1,
+ RT5659_DAC_MONO_L_ASRC_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DAC Mono R ASRC", 1, RT5659_ASRC_1,
+ RT5659_DAC_MONO_R_ASRC_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5659_ASRC_1,
+ RT5659_ADC_STO1_ASRC_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ADC Mono L ASRC", 1, RT5659_ASRC_1,
+ RT5659_ADC_MONO_L_ASRC_SFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ADC Mono R ASRC", 1, RT5659_ASRC_1,
+ RT5659_ADC_MONO_R_ASRC_SFT, 0, NULL, 0),
+
+ /* Input Side */
+ SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5659_PWR_ANLG_2, RT5659_PWR_MB1_BIT,
+ 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MICBIAS2", RT5659_PWR_ANLG_2, RT5659_PWR_MB2_BIT,
+ 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MICBIAS3", RT5659_PWR_ANLG_2, RT5659_PWR_MB3_BIT,
+ 0, NULL, 0),
+
+ /* Input Lines */
+ SND_SOC_DAPM_INPUT("DMIC L1"),
+ SND_SOC_DAPM_INPUT("DMIC R1"),
+ SND_SOC_DAPM_INPUT("DMIC L2"),
+ SND_SOC_DAPM_INPUT("DMIC R2"),
+
+ SND_SOC_DAPM_INPUT("IN1P"),
+ SND_SOC_DAPM_INPUT("IN1N"),
+ SND_SOC_DAPM_INPUT("IN2P"),
+ SND_SOC_DAPM_INPUT("IN2N"),
+ SND_SOC_DAPM_INPUT("IN3P"),
+ SND_SOC_DAPM_INPUT("IN3N"),
+ SND_SOC_DAPM_INPUT("IN4P"),
+ SND_SOC_DAPM_INPUT("IN4N"),
+
+ SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
+ set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_1_EN_SFT, 0, set_dmic_power, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_2_EN_SFT, 0, set_dmic_power, SND_SOC_DAPM_POST_PMU),
+
+ /* Boost */
+ SND_SOC_DAPM_PGA("BST1", RT5659_PWR_ANLG_2,
+ RT5659_PWR_BST1_P_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("BST2", RT5659_PWR_ANLG_2,
+ RT5659_PWR_BST2_P_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("BST3", RT5659_PWR_ANLG_2,
+ RT5659_PWR_BST3_P_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("BST4", RT5659_PWR_ANLG_2,
+ RT5659_PWR_BST4_P_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("BST1 Power", RT5659_PWR_ANLG_2,
+ RT5659_PWR_BST1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("BST2 Power", RT5659_PWR_ANLG_2,
+ RT5659_PWR_BST2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("BST3 Power", RT5659_PWR_ANLG_2,
+ RT5659_PWR_BST3_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("BST4 Power", RT5659_PWR_ANLG_2,
+ RT5659_PWR_BST4_BIT, 0, NULL, 0),
+
+
+ /* Input Volume */
+ SND_SOC_DAPM_PGA("INL VOL", RT5659_PWR_VOL, RT5659_PWR_IN_L_BIT,
+ 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INR VOL", RT5659_PWR_VOL, RT5659_PWR_IN_R_BIT,
+ 0, NULL, 0),
+
+ /* REC Mixer */
+ SND_SOC_DAPM_MIXER("RECMIX1L", RT5659_PWR_MIXER, RT5659_PWR_RM1_L_BIT,
+ 0, rt5659_rec1_l_mix, ARRAY_SIZE(rt5659_rec1_l_mix)),
+ SND_SOC_DAPM_MIXER("RECMIX1R", RT5659_PWR_MIXER, RT5659_PWR_RM1_R_BIT,
+ 0, rt5659_rec1_r_mix, ARRAY_SIZE(rt5659_rec1_r_mix)),
+ SND_SOC_DAPM_MIXER("RECMIX2L", RT5659_PWR_MIXER, RT5659_PWR_RM2_L_BIT,
+ 0, rt5659_rec2_l_mix, ARRAY_SIZE(rt5659_rec2_l_mix)),
+ SND_SOC_DAPM_MIXER("RECMIX2R", RT5659_PWR_MIXER, RT5659_PWR_RM2_R_BIT,
+ 0, rt5659_rec2_r_mix, ARRAY_SIZE(rt5659_rec2_r_mix)),
+
+ /* ADCs */
+ SND_SOC_DAPM_ADC("ADC1 L", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("ADC1 R", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("ADC2 L", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("ADC2 R", NULL, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_SUPPLY("ADC1 L Power", RT5659_PWR_DIG_1,
+ RT5659_PWR_ADC_L1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC1 R Power", RT5659_PWR_DIG_1,
+ RT5659_PWR_ADC_R1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC2 L Power", RT5659_PWR_DIG_2,
+ RT5659_PWR_ADC_L2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC2 R Power", RT5659_PWR_DIG_2,
+ RT5659_PWR_ADC_R2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC1 clock", SND_SOC_NOPM, 0, 0, set_adc_clk,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("ADC2 clock", SND_SOC_NOPM, 0, 0, set_adc_clk,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ /* ADC Mux */
+ SND_SOC_DAPM_MUX("Stereo1 DMIC L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_sto1_dmic_mux),
+ SND_SOC_DAPM_MUX("Stereo1 DMIC R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_sto1_dmic_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_sto1_adc1_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_sto1_adc1_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_sto1_adc2_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_sto1_adc2_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_sto1_adc_mux),
+ SND_SOC_DAPM_MUX("Stereo1 ADC R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_sto1_adc_mux),
+ SND_SOC_DAPM_MUX("Mono ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_mono_adc_l2_mux),
+ SND_SOC_DAPM_MUX("Mono ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_mono_adc_r2_mux),
+ SND_SOC_DAPM_MUX("Mono ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_mono_adc_l1_mux),
+ SND_SOC_DAPM_MUX("Mono ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_mono_adc_r1_mux),
+ SND_SOC_DAPM_MUX("Mono DMIC L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_mono_dmic_l_mux),
+ SND_SOC_DAPM_MUX("Mono DMIC R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_mono_dmic_r_mux),
+ SND_SOC_DAPM_MUX("Mono ADC L Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_mono_adc_l_mux),
+ SND_SOC_DAPM_MUX("Mono ADC R Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_mono_adc_r_mux),
+ /* ADC Mixer */
+ SND_SOC_DAPM_SUPPLY("ADC Stereo1 Filter", RT5659_PWR_DIG_2,
+ RT5659_PWR_ADC_S1F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("ADC Stereo2 Filter", RT5659_PWR_DIG_2,
+ RT5659_PWR_ADC_S2F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Stereo1 ADC MIXL", SND_SOC_NOPM,
+ 0, 0, rt5659_sto1_adc_l_mix,
+ ARRAY_SIZE(rt5659_sto1_adc_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", SND_SOC_NOPM,
+ 0, 0, rt5659_sto1_adc_r_mix,
+ ARRAY_SIZE(rt5659_sto1_adc_r_mix)),
+ SND_SOC_DAPM_SUPPLY("ADC Mono Left Filter", RT5659_PWR_DIG_2,
+ RT5659_PWR_ADC_MF_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Mono ADC MIXL", RT5659_MONO_ADC_DIG_VOL,
+ RT5659_L_MUTE_SFT, 1, rt5659_mono_adc_l_mix,
+ ARRAY_SIZE(rt5659_mono_adc_l_mix)),
+ SND_SOC_DAPM_SUPPLY("ADC Mono Right Filter", RT5659_PWR_DIG_2,
+ RT5659_PWR_ADC_MF_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Mono ADC MIXR", RT5659_MONO_ADC_DIG_VOL,
+ RT5659_R_MUTE_SFT, 1, rt5659_mono_adc_r_mix,
+ ARRAY_SIZE(rt5659_mono_adc_r_mix)),
+
+ /* ADC PGA */
+ SND_SOC_DAPM_PGA("IF_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo2 ADC LR", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_PGA("Stereo1 ADC Volume L", RT5659_STO1_ADC_DIG_VOL,
+ RT5659_L_MUTE_SFT, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Stereo1 ADC Volume R", RT5659_STO1_ADC_DIG_VOL,
+ RT5659_R_MUTE_SFT, 1, NULL, 0),
+
+ /* Digital Interface */
+ SND_SOC_DAPM_SUPPLY("I2S1", RT5659_PWR_DIG_1, RT5659_PWR_I2S1_BIT,
+ 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("I2S2", RT5659_PWR_DIG_1, RT5659_PWR_I2S2_BIT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF2 ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("I2S3", RT5659_PWR_DIG_1, RT5659_PWR_I2S3_BIT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF3 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Digital Interface Select */
+ SND_SOC_DAPM_PGA("TDM AD1:AD2:DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("TDM AD2:DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("TDM Data Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_rx_adc_dac_mux),
+ SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if2_adc_in_mux),
+ SND_SOC_DAPM_MUX("IF3 ADC Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if3_adc_in_mux),
+ SND_SOC_DAPM_MUX("IF1 01 ADC Swap Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if1_01_adc_swap_mux),
+ SND_SOC_DAPM_MUX("IF1 23 ADC Swap Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if1_23_adc_swap_mux),
+ SND_SOC_DAPM_MUX("IF1 45 ADC Swap Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if1_45_adc_swap_mux),
+ SND_SOC_DAPM_MUX("IF1 67 ADC Swap Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if1_67_adc_swap_mux),
+ SND_SOC_DAPM_MUX("IF2 DAC Swap Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if2_dac_swap_mux),
+ SND_SOC_DAPM_MUX("IF2 ADC Swap Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if2_adc_swap_mux),
+ SND_SOC_DAPM_MUX("IF3 DAC Swap Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if3_dac_swap_mux),
+ SND_SOC_DAPM_MUX("IF3 ADC Swap Mux", SND_SOC_NOPM, 0, 0,
+ &rt5659_if3_adc_swap_mux),
+
+ /* Audio Interface */
+ SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF3RX", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF3TX", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ /* Output Side */
+ /* DAC mixer before sound effect */
+ SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0,
+ rt5659_dac_l_mix, ARRAY_SIZE(rt5659_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0,
+ rt5659_dac_r_mix, ARRAY_SIZE(rt5659_dac_r_mix)),
+
+ /* DAC channel Mux */
+ SND_SOC_DAPM_MUX("DAC L1 Mux", SND_SOC_NOPM, 0, 0, &rt5659_dac_l1_mux),
+ SND_SOC_DAPM_MUX("DAC R1 Mux", SND_SOC_NOPM, 0, 0, &rt5659_dac_r1_mux),
+ SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, &rt5659_dac_l2_mux),
+ SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, &rt5659_dac_r2_mux),
+
+ SND_SOC_DAPM_MUX("DAC L1 Source", SND_SOC_NOPM, 0, 0,
+ &rt5659_alg_dac_l1_mux),
+ SND_SOC_DAPM_MUX("DAC R1 Source", SND_SOC_NOPM, 0, 0,
+ &rt5659_alg_dac_r1_mux),
+ SND_SOC_DAPM_MUX("DAC L2 Source", SND_SOC_NOPM, 0, 0,
+ &rt5659_alg_dac_l2_mux),
+ SND_SOC_DAPM_MUX("DAC R2 Source", SND_SOC_NOPM, 0, 0,
+ &rt5659_alg_dac_r2_mux),
+
+ /* DAC Mixer */
+ SND_SOC_DAPM_SUPPLY("DAC Stereo1 Filter", RT5659_PWR_DIG_2,
+ RT5659_PWR_DAC_S1F_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DAC Mono Left Filter", RT5659_PWR_DIG_2,
+ RT5659_PWR_DAC_MF_L_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DAC Mono Right Filter", RT5659_PWR_DIG_2,
+ RT5659_PWR_DAC_MF_R_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5659_sto_dac_l_mix, ARRAY_SIZE(rt5659_sto_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5659_sto_dac_r_mix, ARRAY_SIZE(rt5659_sto_dac_r_mix)),
+ SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0,
+ rt5659_mono_dac_l_mix, ARRAY_SIZE(rt5659_mono_dac_l_mix)),
+ SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0,
+ rt5659_mono_dac_r_mix, ARRAY_SIZE(rt5659_mono_dac_r_mix)),
+ SND_SOC_DAPM_MUX("DAC MIXL", SND_SOC_NOPM, 0, 0,
+ &rt5659_dig_dac_mixl_mux),
+ SND_SOC_DAPM_MUX("DAC MIXR", SND_SOC_NOPM, 0, 0,
+ &rt5659_dig_dac_mixr_mux),
+
+ /* DACs */
+ SND_SOC_DAPM_SUPPLY_S("DAC L1 Power", 1, RT5659_PWR_DIG_1,
+ RT5659_PWR_DAC_L1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("DAC R1 Power", 1, RT5659_PWR_DIG_1,
+ RT5659_PWR_DAC_R1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_DAC("DAC L1", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("DAC R1", NULL, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_SUPPLY("DAC L2 Power", RT5659_PWR_DIG_1,
+ RT5659_PWR_DAC_L2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DAC R2 Power", RT5659_PWR_DIG_1,
+ RT5659_PWR_DAC_R2_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_DAC("DAC L2", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("DAC R2", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_PGA("DAC_REF", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* OUT Mixer */
+ SND_SOC_DAPM_MIXER("SPK MIXL", RT5659_PWR_MIXER, RT5659_PWR_SM_L_BIT,
+ 0, rt5659_spk_l_mix, ARRAY_SIZE(rt5659_spk_l_mix)),
+ SND_SOC_DAPM_MIXER("SPK MIXR", RT5659_PWR_MIXER, RT5659_PWR_SM_R_BIT,
+ 0, rt5659_spk_r_mix, ARRAY_SIZE(rt5659_spk_r_mix)),
+ SND_SOC_DAPM_MIXER("MONOVOL MIX", RT5659_PWR_MIXER, RT5659_PWR_MM_BIT,
+ 0, rt5659_monovol_mix, ARRAY_SIZE(rt5659_monovol_mix)),
+ SND_SOC_DAPM_MIXER("OUT MIXL", RT5659_PWR_MIXER, RT5659_PWR_OM_L_BIT,
+ 0, rt5659_out_l_mix, ARRAY_SIZE(rt5659_out_l_mix)),
+ SND_SOC_DAPM_MIXER("OUT MIXR", RT5659_PWR_MIXER, RT5659_PWR_OM_R_BIT,
+ 0, rt5659_out_r_mix, ARRAY_SIZE(rt5659_out_r_mix)),
+
+ /* Output Volume */
+ SND_SOC_DAPM_SWITCH("SPKVOL L", RT5659_PWR_VOL, RT5659_PWR_SV_L_BIT, 0,
+ &spkvol_l_switch),
+ SND_SOC_DAPM_SWITCH("SPKVOL R", RT5659_PWR_VOL, RT5659_PWR_SV_R_BIT, 0,
+ &spkvol_r_switch),
+ SND_SOC_DAPM_SWITCH("MONOVOL", RT5659_PWR_VOL, RT5659_PWR_MV_BIT, 0,
+ &monovol_switch),
+ SND_SOC_DAPM_SWITCH("OUTVOL L", RT5659_PWR_VOL, RT5659_PWR_OV_L_BIT, 0,
+ &outvol_l_switch),
+ SND_SOC_DAPM_SWITCH("OUTVOL R", RT5659_PWR_VOL, RT5659_PWR_OV_R_BIT, 0,
+ &outvol_r_switch),
+
+ /* SPO/MONO/HPO/LOUT */
+ SND_SOC_DAPM_MIXER("SPO L MIX", SND_SOC_NOPM, 0, 0, rt5659_spo_l_mix,
+ ARRAY_SIZE(rt5659_spo_l_mix)),
+ SND_SOC_DAPM_MIXER("SPO R MIX", SND_SOC_NOPM, 0, 0, rt5659_spo_r_mix,
+ ARRAY_SIZE(rt5659_spo_r_mix)),
+ SND_SOC_DAPM_MIXER("Mono MIX", SND_SOC_NOPM, 0, 0, rt5659_mono_mix,
+ ARRAY_SIZE(rt5659_mono_mix)),
+ SND_SOC_DAPM_MIXER("LOUT L MIX", SND_SOC_NOPM, 0, 0, rt5659_lout_l_mix,
+ ARRAY_SIZE(rt5659_lout_l_mix)),
+ SND_SOC_DAPM_MIXER("LOUT R MIX", SND_SOC_NOPM, 0, 0, rt5659_lout_r_mix,
+ ARRAY_SIZE(rt5659_lout_r_mix)),
+
+ SND_SOC_DAPM_PGA_S("SPK Amp", 1, RT5659_PWR_DIG_1, RT5659_PWR_CLS_D_BIT,
+ 0, rt5659_spk_event, SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_PGA_S("Mono Amp", 1, RT5659_PWR_ANLG_1, RT5659_PWR_MA_BIT,
+ 0, rt5659_mono_event, SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5659_hp_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA("LOUT Amp", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Charge Pump", SND_SOC_NOPM, 0, 0,
+ rt5659_charge_pump_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SWITCH("SPO Playback", SND_SOC_NOPM, 0, 0, &spo_switch),
+ SND_SOC_DAPM_SWITCH("Mono Playback", SND_SOC_NOPM, 0, 0,
+ &mono_switch),
+ SND_SOC_DAPM_SWITCH("HPO L Playback", SND_SOC_NOPM, 0, 0,
+ &hpo_l_switch),
+ SND_SOC_DAPM_SWITCH("HPO R Playback", SND_SOC_NOPM, 0, 0,
+ &hpo_r_switch),
+ SND_SOC_DAPM_SWITCH("LOUT L Playback", SND_SOC_NOPM, 0, 0,
+ &lout_l_switch),
+ SND_SOC_DAPM_SWITCH("LOUT R Playback", SND_SOC_NOPM, 0, 0,
+ &lout_r_switch),
+ SND_SOC_DAPM_SWITCH("PDM L Playback", SND_SOC_NOPM, 0, 0,
+ &pdm_l_switch),
+ SND_SOC_DAPM_SWITCH("PDM R Playback", SND_SOC_NOPM, 0, 0,
+ &pdm_r_switch),
+
+ /* PDM */
+ SND_SOC_DAPM_SUPPLY("PDM Power", RT5659_PWR_DIG_2,
+ RT5659_PWR_PDM1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("PDM L Mux", RT5659_PDM_OUT_CTRL,
+ RT5659_M_PDM1_L_SFT, 1, &rt5659_pdm_l_mux),
+ SND_SOC_DAPM_MUX("PDM R Mux", RT5659_PDM_OUT_CTRL,
+ RT5659_M_PDM1_R_SFT, 1, &rt5659_pdm_r_mux),
+
+ /* SPDIF */
+ SND_SOC_DAPM_MUX("SPDIF Mux", SND_SOC_NOPM, 0, 0, &rt5659_spdif_mux),
+
+ SND_SOC_DAPM_SUPPLY("SYS CLK DET", RT5659_CLK_DET, 3, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("CLKDET", RT5659_CLK_DET, 0, 0, NULL, 0),
+
+ /* Output Lines */
+ SND_SOC_DAPM_OUTPUT("HPOL"),
+ SND_SOC_DAPM_OUTPUT("HPOR"),
+ SND_SOC_DAPM_OUTPUT("SPOL"),
+ SND_SOC_DAPM_OUTPUT("SPOR"),
+ SND_SOC_DAPM_OUTPUT("LOUTL"),
+ SND_SOC_DAPM_OUTPUT("LOUTR"),
+ SND_SOC_DAPM_OUTPUT("MONOOUT"),
+ SND_SOC_DAPM_OUTPUT("PDML"),
+ SND_SOC_DAPM_OUTPUT("PDMR"),
+ SND_SOC_DAPM_OUTPUT("SPDIF"),
+};
+
+static const struct snd_soc_dapm_route rt5659_dapm_routes[] = {
+ /*PLL*/
+ { "ADC Stereo1 Filter", NULL, "PLL", is_sys_clk_from_pll },
+ { "ADC Stereo2 Filter", NULL, "PLL", is_sys_clk_from_pll },
+ { "ADC Mono Left Filter", NULL, "PLL", is_sys_clk_from_pll },
+ { "ADC Mono Right Filter", NULL, "PLL", is_sys_clk_from_pll },
+ { "DAC Stereo1 Filter", NULL, "PLL", is_sys_clk_from_pll },
+ { "DAC Mono Left Filter", NULL, "PLL", is_sys_clk_from_pll },
+ { "DAC Mono Right Filter", NULL, "PLL", is_sys_clk_from_pll },
+
+ /*ASRC*/
+ { "ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc },
+ { "ADC Mono Left Filter", NULL, "ADC Mono L ASRC", is_using_asrc },
+ { "ADC Mono Right Filter", NULL, "ADC Mono R ASRC", is_using_asrc },
+ { "DAC Mono Left Filter", NULL, "DAC Mono L ASRC", is_using_asrc },
+ { "DAC Mono Right Filter", NULL, "DAC Mono R ASRC", is_using_asrc },
+ { "DAC Stereo1 Filter", NULL, "DAC STO ASRC", is_using_asrc },
+
+ { "SYS CLK DET", NULL, "CLKDET" },
+
+ { "I2S1", NULL, "I2S1 ASRC" },
+ { "I2S2", NULL, "I2S2 ASRC" },
+ { "I2S3", NULL, "I2S3 ASRC" },
+
+ { "IN1P", NULL, "LDO2" },
+ { "IN2P", NULL, "LDO2" },
+ { "IN3P", NULL, "LDO2" },
+ { "IN4P", NULL, "LDO2" },
+
+ { "DMIC1", NULL, "DMIC L1" },
+ { "DMIC1", NULL, "DMIC R1" },
+ { "DMIC2", NULL, "DMIC L2" },
+ { "DMIC2", NULL, "DMIC R2" },
+
+ { "BST1", NULL, "IN1P" },
+ { "BST1", NULL, "IN1N" },
+ { "BST1", NULL, "BST1 Power" },
+ { "BST2", NULL, "IN2P" },
+ { "BST2", NULL, "IN2N" },
+ { "BST2", NULL, "BST2 Power" },
+ { "BST3", NULL, "IN3P" },
+ { "BST3", NULL, "IN3N" },
+ { "BST3", NULL, "BST3 Power" },
+ { "BST4", NULL, "IN4P" },
+ { "BST4", NULL, "IN4N" },
+ { "BST4", NULL, "BST4 Power" },
+
+ { "INL VOL", NULL, "IN2P" },
+ { "INR VOL", NULL, "IN2N" },
+
+ { "RECMIX1L", "SPKVOLL Switch", "SPKVOL L" },
+ { "RECMIX1L", "INL Switch", "INL VOL" },
+ { "RECMIX1L", "BST4 Switch", "BST4" },
+ { "RECMIX1L", "BST3 Switch", "BST3" },
+ { "RECMIX1L", "BST2 Switch", "BST2" },
+ { "RECMIX1L", "BST1 Switch", "BST1" },
+
+ { "RECMIX1R", "HPOVOLR Switch", "HPO R Playback" },
+ { "RECMIX1R", "INR Switch", "INR VOL" },
+ { "RECMIX1R", "BST4 Switch", "BST4" },
+ { "RECMIX1R", "BST3 Switch", "BST3" },
+ { "RECMIX1R", "BST2 Switch", "BST2" },
+ { "RECMIX1R", "BST1 Switch", "BST1" },
+
+ { "RECMIX2L", "SPKVOLL Switch", "SPKVOL L" },
+ { "RECMIX2L", "OUTVOLL Switch", "OUTVOL L" },
+ { "RECMIX2L", "BST4 Switch", "BST4" },
+ { "RECMIX2L", "BST3 Switch", "BST3" },
+ { "RECMIX2L", "BST2 Switch", "BST2" },
+ { "RECMIX2L", "BST1 Switch", "BST1" },
+
+ { "RECMIX2R", "MONOVOL Switch", "MONOVOL" },
+ { "RECMIX2R", "OUTVOLR Switch", "OUTVOL R" },
+ { "RECMIX2R", "BST4 Switch", "BST4" },
+ { "RECMIX2R", "BST3 Switch", "BST3" },
+ { "RECMIX2R", "BST2 Switch", "BST2" },
+ { "RECMIX2R", "BST1 Switch", "BST1" },
+
+ { "ADC1 L", NULL, "RECMIX1L" },
+ { "ADC1 L", NULL, "ADC1 L Power" },
+ { "ADC1 L", NULL, "ADC1 clock" },
+ { "ADC1 R", NULL, "RECMIX1R" },
+ { "ADC1 R", NULL, "ADC1 R Power" },
+ { "ADC1 R", NULL, "ADC1 clock" },
+
+ { "ADC2 L", NULL, "RECMIX2L" },
+ { "ADC2 L", NULL, "ADC2 L Power" },
+ { "ADC2 L", NULL, "ADC2 clock" },
+ { "ADC2 R", NULL, "RECMIX2R" },
+ { "ADC2 R", NULL, "ADC2 R Power" },
+ { "ADC2 R", NULL, "ADC2 clock" },
+
+ { "DMIC L1", NULL, "DMIC CLK" },
+ { "DMIC L1", NULL, "DMIC1 Power" },
+ { "DMIC R1", NULL, "DMIC CLK" },
+ { "DMIC R1", NULL, "DMIC1 Power" },
+ { "DMIC L2", NULL, "DMIC CLK" },
+ { "DMIC L2", NULL, "DMIC2 Power" },
+ { "DMIC R2", NULL, "DMIC CLK" },
+ { "DMIC R2", NULL, "DMIC2 Power" },
+
+ { "Stereo1 DMIC L Mux", "DMIC1", "DMIC L1" },
+ { "Stereo1 DMIC L Mux", "DMIC2", "DMIC L2" },
+
+ { "Stereo1 DMIC R Mux", "DMIC1", "DMIC R1" },
+ { "Stereo1 DMIC R Mux", "DMIC2", "DMIC R2" },
+
+ { "Mono DMIC L Mux", "DMIC1 L", "DMIC L1" },
+ { "Mono DMIC L Mux", "DMIC2 L", "DMIC L2" },
+
+ { "Mono DMIC R Mux", "DMIC1 R", "DMIC R1" },
+ { "Mono DMIC R Mux", "DMIC2 R", "DMIC R2" },
+
+ { "Stereo1 ADC L Mux", "ADC1", "ADC1 L" },
+ { "Stereo1 ADC L Mux", "ADC2", "ADC2 L" },
+ { "Stereo1 ADC R Mux", "ADC1", "ADC1 R" },
+ { "Stereo1 ADC R Mux", "ADC2", "ADC2 R" },
+
+ { "Stereo1 ADC L1 Mux", "ADC", "Stereo1 ADC L Mux" },
+ { "Stereo1 ADC L1 Mux", "DAC MIX", "DAC MIXL" },
+ { "Stereo1 ADC L2 Mux", "DMIC", "Stereo1 DMIC L Mux" },
+ { "Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL" },
+
+ { "Stereo1 ADC R1 Mux", "ADC", "Stereo1 ADC R Mux" },
+ { "Stereo1 ADC R1 Mux", "DAC MIX", "DAC MIXR" },
+ { "Stereo1 ADC R2 Mux", "DMIC", "Stereo1 DMIC R Mux" },
+ { "Stereo1 ADC R2 Mux", "DAC MIX", "DAC MIXR" },
+
+ { "Mono ADC L Mux", "ADC1 L", "ADC1 L" },
+ { "Mono ADC L Mux", "ADC1 R", "ADC1 R" },
+ { "Mono ADC L Mux", "ADC2 L", "ADC2 L" },
+ { "Mono ADC L Mux", "ADC2 R", "ADC2 R" },
+
+ { "Mono ADC R Mux", "ADC1 L", "ADC1 L" },
+ { "Mono ADC R Mux", "ADC1 R", "ADC1 R" },
+ { "Mono ADC R Mux", "ADC2 L", "ADC2 L" },
+ { "Mono ADC R Mux", "ADC2 R", "ADC2 R" },
+
+ { "Mono ADC L2 Mux", "DMIC", "Mono DMIC L Mux" },
+ { "Mono ADC L2 Mux", "Mono DAC MIXL", "Mono DAC MIXL" },
+ { "Mono ADC L1 Mux", "Mono DAC MIXL", "Mono DAC MIXL" },
+ { "Mono ADC L1 Mux", "ADC", "Mono ADC L Mux" },
+
+ { "Mono ADC R1 Mux", "Mono DAC MIXR", "Mono DAC MIXR" },
+ { "Mono ADC R1 Mux", "ADC", "Mono ADC R Mux" },
+ { "Mono ADC R2 Mux", "DMIC", "Mono DMIC R Mux" },
+ { "Mono ADC R2 Mux", "Mono DAC MIXR", "Mono DAC MIXR" },
+
+ { "Stereo1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux" },
+ { "Stereo1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux" },
+ { "Stereo1 ADC MIXL", NULL, "ADC Stereo1 Filter" },
+
+ { "Stereo1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux" },
+ { "Stereo1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux" },
+ { "Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter" },
+
+ { "Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux" },
+ { "Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux" },
+ { "Mono ADC MIXL", NULL, "ADC Mono Left Filter" },
+
+ { "Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux" },
+ { "Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux" },
+ { "Mono ADC MIXR", NULL, "ADC Mono Right Filter" },
+
+ { "Stereo1 ADC Volume L", NULL, "Stereo1 ADC MIXL" },
+ { "Stereo1 ADC Volume R", NULL, "Stereo1 ADC MIXR" },
+
+ { "IF_ADC1", NULL, "Stereo1 ADC Volume L" },
+ { "IF_ADC1", NULL, "Stereo1 ADC Volume R" },
+ { "IF_ADC2", NULL, "Mono ADC MIXL" },
+ { "IF_ADC2", NULL, "Mono ADC MIXR" },
+
+ { "TDM AD1:AD2:DAC", NULL, "IF_ADC1" },
+ { "TDM AD1:AD2:DAC", NULL, "IF_ADC2" },
+ { "TDM AD1:AD2:DAC", NULL, "DAC_REF" },
+ { "TDM AD2:DAC", NULL, "IF_ADC2" },
+ { "TDM AD2:DAC", NULL, "DAC_REF" },
+ { "TDM Data Mux", "AD1:AD2:DAC:NUL", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD1:AD2:NUL:DAC", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD1:DAC:AD2:NUL", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD1:DAC:NUL:AD2", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD1:NUL:DAC:AD2", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD1:NUL:AD2:DAC", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD2:AD1:DAC:NUL", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD2:AD1:NUL:DAC", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD2:DAC:AD1:NUL", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD2:DAC:NUL:AD1", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD2:NUL:DAC:AD1", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "AD1:NUL:AD1:DAC", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "DAC:AD1:AD2:NUL", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "DAC:AD1:NUL:AD2", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "DAC:AD2:AD1:NUL", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "DAC:AD2:NUL:AD1", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "DAC:NUL:DAC:AD2", "TDM AD2:DAC" },
+ { "TDM Data Mux", "DAC:NUL:AD2:DAC", "TDM AD2:DAC" },
+ { "TDM Data Mux", "NUL:AD1:AD2:DAC", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "NUL:AD1:DAC:AD2", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "NUL:AD2:AD1:DAC", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "NUL:AD2:DAC:AD1", "TDM AD1:AD2:DAC" },
+ { "TDM Data Mux", "NUL:DAC:DAC:AD2", "TDM AD2:DAC" },
+ { "TDM Data Mux", "NUL:DAC:AD2:DAC", "TDM AD2:DAC" },
+ { "IF1 01 ADC Swap Mux", "L/R", "TDM Data Mux" },
+ { "IF1 01 ADC Swap Mux", "R/L", "TDM Data Mux" },
+ { "IF1 01 ADC Swap Mux", "L/L", "TDM Data Mux" },
+ { "IF1 01 ADC Swap Mux", "R/R", "TDM Data Mux" },
+ { "IF1 23 ADC Swap Mux", "L/R", "TDM Data Mux" },
+ { "IF1 23 ADC Swap Mux", "R/L", "TDM Data Mux" },
+ { "IF1 23 ADC Swap Mux", "L/L", "TDM Data Mux" },
+ { "IF1 23 ADC Swap Mux", "R/R", "TDM Data Mux" },
+ { "IF1 45 ADC Swap Mux", "L/R", "TDM Data Mux" },
+ { "IF1 45 ADC Swap Mux", "R/L", "TDM Data Mux" },
+ { "IF1 45 ADC Swap Mux", "L/L", "TDM Data Mux" },
+ { "IF1 45 ADC Swap Mux", "R/R", "TDM Data Mux" },
+ { "IF1 67 ADC Swap Mux", "L/R", "TDM Data Mux" },
+ { "IF1 67 ADC Swap Mux", "R/L", "TDM Data Mux" },
+ { "IF1 67 ADC Swap Mux", "L/L", "TDM Data Mux" },
+ { "IF1 67 ADC Swap Mux", "R/R", "TDM Data Mux" },
+ { "IF1 ADC", NULL, "IF1 01 ADC Swap Mux" },
+ { "IF1 ADC", NULL, "IF1 23 ADC Swap Mux" },
+ { "IF1 ADC", NULL, "IF1 45 ADC Swap Mux" },
+ { "IF1 ADC", NULL, "IF1 67 ADC Swap Mux" },
+ { "IF1 ADC", NULL, "I2S1" },
+
+ { "IF2 ADC Mux", "IF_ADC1", "IF_ADC1" },
+ { "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" },
+ { "IF2 ADC Mux", "IF_ADC3", "IF_ADC3" },
+ { "IF2 ADC Mux", "DAC_REF", "DAC_REF" },
+ { "IF2 ADC", NULL, "IF2 ADC Mux"},
+ { "IF2 ADC", NULL, "I2S2" },
+
+ { "IF3 ADC Mux", "IF_ADC1", "IF_ADC1" },
+ { "IF3 ADC Mux", "IF_ADC2", "IF_ADC2" },
+ { "IF3 ADC Mux", "Stereo2_ADC_L/R", "Stereo2 ADC LR" },
+ { "IF3 ADC Mux", "DAC_REF", "DAC_REF" },
+ { "IF3 ADC", NULL, "IF3 ADC Mux"},
+ { "IF3 ADC", NULL, "I2S3" },
+
+ { "AIF1TX", NULL, "IF1 ADC" },
+ { "IF2 ADC Swap Mux", "L/R", "IF2 ADC" },
+ { "IF2 ADC Swap Mux", "R/L", "IF2 ADC" },
+ { "IF2 ADC Swap Mux", "L/L", "IF2 ADC" },
+ { "IF2 ADC Swap Mux", "R/R", "IF2 ADC" },
+ { "AIF2TX", NULL, "IF2 ADC Swap Mux" },
+ { "IF3 ADC Swap Mux", "L/R", "IF3 ADC" },
+ { "IF3 ADC Swap Mux", "R/L", "IF3 ADC" },
+ { "IF3 ADC Swap Mux", "L/L", "IF3 ADC" },
+ { "IF3 ADC Swap Mux", "R/R", "IF3 ADC" },
+ { "AIF3TX", NULL, "IF3 ADC Swap Mux" },
+
+ { "IF1 DAC1", NULL, "AIF1RX" },
+ { "IF1 DAC2", NULL, "AIF1RX" },
+ { "IF2 DAC Swap Mux", "L/R", "AIF2RX" },
+ { "IF2 DAC Swap Mux", "R/L", "AIF2RX" },
+ { "IF2 DAC Swap Mux", "L/L", "AIF2RX" },
+ { "IF2 DAC Swap Mux", "R/R", "AIF2RX" },
+ { "IF2 DAC", NULL, "IF2 DAC Swap Mux" },
+ { "IF3 DAC Swap Mux", "L/R", "AIF3RX" },
+ { "IF3 DAC Swap Mux", "R/L", "AIF3RX" },
+ { "IF3 DAC Swap Mux", "L/L", "AIF3RX" },
+ { "IF3 DAC Swap Mux", "R/R", "AIF3RX" },
+ { "IF3 DAC", NULL, "IF3 DAC Swap Mux" },
+
+ { "IF1 DAC1", NULL, "I2S1" },
+ { "IF1 DAC2", NULL, "I2S1" },
+ { "IF2 DAC", NULL, "I2S2" },
+ { "IF3 DAC", NULL, "I2S3" },
+
+ { "IF1 DAC2 L", NULL, "IF1 DAC2" },
+ { "IF1 DAC2 R", NULL, "IF1 DAC2" },
+ { "IF1 DAC1 L", NULL, "IF1 DAC1" },
+ { "IF1 DAC1 R", NULL, "IF1 DAC1" },
+ { "IF2 DAC L", NULL, "IF2 DAC" },
+ { "IF2 DAC R", NULL, "IF2 DAC" },
+ { "IF3 DAC L", NULL, "IF3 DAC" },
+ { "IF3 DAC R", NULL, "IF3 DAC" },
+
+ { "DAC L1 Mux", "IF1 DAC1", "IF1 DAC1 L" },
+ { "DAC L1 Mux", "IF2 DAC", "IF2 DAC L" },
+ { "DAC L1 Mux", "IF3 DAC", "IF3 DAC L" },
+ { "DAC L1 Mux", NULL, "DAC Stereo1 Filter" },
+
+ { "DAC R1 Mux", "IF1 DAC1", "IF1 DAC1 R" },
+ { "DAC R1 Mux", "IF2 DAC", "IF2 DAC R" },
+ { "DAC R1 Mux", "IF3 DAC", "IF3 DAC R" },
+ { "DAC R1 Mux", NULL, "DAC Stereo1 Filter" },
+
+ { "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC Volume L" },
+ { "DAC1 MIXL", "DAC1 Switch", "DAC L1 Mux" },
+ { "DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC Volume R" },
+ { "DAC1 MIXR", "DAC1 Switch", "DAC R1 Mux" },
+
+ { "DAC_REF", NULL, "DAC1 MIXL" },
+ { "DAC_REF", NULL, "DAC1 MIXR" },
+
+ { "DAC L2 Mux", "IF1 DAC2", "IF1 DAC2 L" },
+ { "DAC L2 Mux", "IF2 DAC", "IF2 DAC L" },
+ { "DAC L2 Mux", "IF3 DAC", "IF3 DAC L" },
+ { "DAC L2 Mux", "Mono ADC MIX", "Mono ADC MIXL" },
+ { "DAC L2 Mux", NULL, "DAC Mono Left Filter" },
+
+ { "DAC R2 Mux", "IF1 DAC2", "IF1 DAC2 R" },
+ { "DAC R2 Mux", "IF2 DAC", "IF2 DAC R" },
+ { "DAC R2 Mux", "IF3 DAC", "IF3 DAC R" },
+ { "DAC R2 Mux", "Mono ADC MIX", "Mono ADC MIXR" },
+ { "DAC R2 Mux", NULL, "DAC Mono Right Filter" },
+
+ { "Stereo DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" },
+ { "Stereo DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" },
+ { "Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux" },
+ { "Stereo DAC MIXL", "DAC R2 Switch", "DAC R2 Mux" },
+
+ { "Stereo DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" },
+ { "Stereo DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" },
+ { "Stereo DAC MIXR", "DAC L2 Switch", "DAC L2 Mux" },
+ { "Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux" },
+
+ { "Mono DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" },
+ { "Mono DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" },
+ { "Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux" },
+ { "Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux" },
+ { "Mono DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" },
+ { "Mono DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" },
+ { "Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux" },
+ { "Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux" },
+
+ { "DAC MIXL", "Stereo DAC Mixer", "Stereo DAC MIXL" },
+ { "DAC MIXL", "Mono DAC Mixer", "Mono DAC MIXL" },
+ { "DAC MIXR", "Stereo DAC Mixer", "Stereo DAC MIXR" },
+ { "DAC MIXR", "Mono DAC Mixer", "Mono DAC MIXR" },
+
+ { "DAC L1 Source", NULL, "DAC L1 Power" },
+ { "DAC L1 Source", "DAC", "DAC1 MIXL" },
+ { "DAC L1 Source", "Stereo DAC Mixer", "Stereo DAC MIXL" },
+ { "DAC R1 Source", NULL, "DAC R1 Power" },
+ { "DAC R1 Source", "DAC", "DAC1 MIXR" },
+ { "DAC R1 Source", "Stereo DAC Mixer", "Stereo DAC MIXR" },
+ { "DAC L2 Source", "Stereo DAC Mixer", "Stereo DAC MIXL" },
+ { "DAC L2 Source", "Mono DAC Mixer", "Mono DAC MIXL" },
+ { "DAC L2 Source", NULL, "DAC L2 Power" },
+ { "DAC R2 Source", "Stereo DAC Mixer", "Stereo DAC MIXR" },
+ { "DAC R2 Source", "Mono DAC Mixer", "Mono DAC MIXR" },
+ { "DAC R2 Source", NULL, "DAC R2 Power" },
+
+ { "DAC L1", NULL, "DAC L1 Source" },
+ { "DAC R1", NULL, "DAC R1 Source" },
+ { "DAC L2", NULL, "DAC L2 Source" },
+ { "DAC R2", NULL, "DAC R2 Source" },
+
+ { "SPK MIXL", "DAC L2 Switch", "DAC L2" },
+ { "SPK MIXL", "BST1 Switch", "BST1" },
+ { "SPK MIXL", "INL Switch", "INL VOL" },
+ { "SPK MIXL", "INR Switch", "INR VOL" },
+ { "SPK MIXL", "BST3 Switch", "BST3" },
+ { "SPK MIXR", "DAC R2 Switch", "DAC R2" },
+ { "SPK MIXR", "BST4 Switch", "BST4" },
+ { "SPK MIXR", "INL Switch", "INL VOL" },
+ { "SPK MIXR", "INR Switch", "INR VOL" },
+ { "SPK MIXR", "BST3 Switch", "BST3" },
+
+ { "MONOVOL MIX", "DAC L2 Switch", "DAC L2" },
+ { "MONOVOL MIX", "DAC R2 Switch", "DAC R2" },
+ { "MONOVOL MIX", "BST1 Switch", "BST1" },
+ { "MONOVOL MIX", "BST2 Switch", "BST2" },
+ { "MONOVOL MIX", "BST3 Switch", "BST3" },
+
+ { "OUT MIXL", "DAC L2 Switch", "DAC L2" },
+ { "OUT MIXL", "INL Switch", "INL VOL" },
+ { "OUT MIXL", "BST1 Switch", "BST1" },
+ { "OUT MIXL", "BST2 Switch", "BST2" },
+ { "OUT MIXL", "BST3 Switch", "BST3" },
+ { "OUT MIXR", "DAC R2 Switch", "DAC R2" },
+ { "OUT MIXR", "INR Switch", "INR VOL" },
+ { "OUT MIXR", "BST2 Switch", "BST2" },
+ { "OUT MIXR", "BST3 Switch", "BST3" },
+ { "OUT MIXR", "BST4 Switch", "BST4" },
+
+ { "SPKVOL L", "Switch", "SPK MIXL" },
+ { "SPKVOL R", "Switch", "SPK MIXR" },
+ { "SPO L MIX", "DAC L2 Switch", "DAC L2" },
+ { "SPO L MIX", "SPKVOL L Switch", "SPKVOL L" },
+ { "SPO R MIX", "DAC R2 Switch", "DAC R2" },
+ { "SPO R MIX", "SPKVOL R Switch", "SPKVOL R" },
+ { "SPK Amp", NULL, "SPO L MIX" },
+ { "SPK Amp", NULL, "SPO R MIX" },
+ { "SPK Amp", NULL, "SYS CLK DET" },
+ { "SPO Playback", "Switch", "SPK Amp" },
+ { "SPOL", NULL, "SPO Playback" },
+ { "SPOR", NULL, "SPO Playback" },
+
+ { "MONOVOL", "Switch", "MONOVOL MIX" },
+ { "Mono MIX", "DAC L2 Switch", "DAC L2" },
+ { "Mono MIX", "MONOVOL Switch", "MONOVOL" },
+ { "Mono Amp", NULL, "Mono MIX" },
+ { "Mono Amp", NULL, "Mono Vref" },
+ { "Mono Amp", NULL, "SYS CLK DET" },
+ { "Mono Playback", "Switch", "Mono Amp" },
+ { "MONOOUT", NULL, "Mono Playback" },
+
+ { "HP Amp", NULL, "DAC L1" },
+ { "HP Amp", NULL, "DAC R1" },
+ { "HP Amp", NULL, "Charge Pump" },
+ { "HP Amp", NULL, "SYS CLK DET" },
+ { "HPO L Playback", "Switch", "HP Amp"},
+ { "HPO R Playback", "Switch", "HP Amp"},
+ { "HPOL", NULL, "HPO L Playback" },
+ { "HPOR", NULL, "HPO R Playback" },
+
+ { "OUTVOL L", "Switch", "OUT MIXL" },
+ { "OUTVOL R", "Switch", "OUT MIXR" },
+ { "LOUT L MIX", "DAC L2 Switch", "DAC L2" },
+ { "LOUT L MIX", "OUTVOL L Switch", "OUTVOL L" },
+ { "LOUT R MIX", "DAC R2 Switch", "DAC R2" },
+ { "LOUT R MIX", "OUTVOL R Switch", "OUTVOL R" },
+ { "LOUT Amp", NULL, "LOUT L MIX" },
+ { "LOUT Amp", NULL, "LOUT R MIX" },
+ { "LOUT Amp", NULL, "SYS CLK DET" },
+ { "LOUT L Playback", "Switch", "LOUT Amp" },
+ { "LOUT R Playback", "Switch", "LOUT Amp" },
+ { "LOUTL", NULL, "LOUT L Playback" },
+ { "LOUTR", NULL, "LOUT R Playback" },
+
+ { "PDM L Mux", "Mono DAC", "Mono DAC MIXL" },
+ { "PDM L Mux", "Stereo DAC", "Stereo DAC MIXL" },
+ { "PDM L Mux", NULL, "PDM Power" },
+ { "PDM R Mux", "Mono DAC", "Mono DAC MIXR" },
+ { "PDM R Mux", "Stereo DAC", "Stereo DAC MIXR" },
+ { "PDM R Mux", NULL, "PDM Power" },
+ { "PDM L Playback", "Switch", "PDM L Mux" },
+ { "PDM R Playback", "Switch", "PDM R Mux" },
+ { "PDML", NULL, "PDM L Playback" },
+ { "PDMR", NULL, "PDM R Playback" },
+
+ { "SPDIF Mux", "IF3_DAC", "IF3 DAC" },
+ { "SPDIF Mux", "IF2_DAC", "IF2 DAC" },
+ { "SPDIF Mux", "IF1_DAC2", "IF1 DAC2" },
+ { "SPDIF Mux", "IF1_DAC1", "IF1 DAC1" },
+ { "SPDIF", NULL, "SPDIF Mux" },
+};
+
+static int rt5659_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+ unsigned int val_len = 0, val_clk, mask_clk;
+ int pre_div, frame_size;
+
+ rt5659->lrck[dai->id] = params_rate(params);
+ pre_div = rl6231_get_clk_info(rt5659->sysclk, rt5659->lrck[dai->id]);
+ if (pre_div < 0) {
+ dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n",
+ rt5659->lrck[dai->id], dai->id);
+ return -EINVAL;
+ }
+ frame_size = snd_soc_params_to_frame_size(params);
+ if (frame_size < 0) {
+ dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
+ return -EINVAL;
+ }
+
+ dev_dbg(dai->dev, "lrck is %dHz and pre_div is %d for iis %d\n",
+ rt5659->lrck[dai->id], pre_div, dai->id);
+
+ switch (params_width(params)) {
+ case 16:
+ break;
+ case 20:
+ val_len |= RT5659_I2S_DL_20;
+ break;
+ case 24:
+ val_len |= RT5659_I2S_DL_24;
+ break;
+ case 8:
+ val_len |= RT5659_I2S_DL_8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (dai->id) {
+ case RT5659_AIF1:
+ mask_clk = RT5659_I2S_PD1_MASK;
+ val_clk = pre_div << RT5659_I2S_PD1_SFT;
+ snd_soc_update_bits(codec, RT5659_I2S1_SDP,
+ RT5659_I2S_DL_MASK, val_len);
+ break;
+ case RT5659_AIF2:
+ mask_clk = RT5659_I2S_PD2_MASK;
+ val_clk = pre_div << RT5659_I2S_PD2_SFT;
+ snd_soc_update_bits(codec, RT5659_I2S2_SDP,
+ RT5659_I2S_DL_MASK, val_len);
+ break;
+ case RT5659_AIF3:
+ mask_clk = RT5659_I2S_PD3_MASK;
+ val_clk = pre_div << RT5659_I2S_PD3_SFT;
+ snd_soc_update_bits(codec, RT5659_I2S3_SDP,
+ RT5659_I2S_DL_MASK, val_len);
+ break;
+ default:
+ dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, RT5659_ADDA_CLK_1, mask_clk, val_clk);
+
+ switch (rt5659->lrck[dai->id]) {
+ case 192000:
+ snd_soc_update_bits(codec, RT5659_ADDA_CLK_1,
+ RT5659_DAC_OSR_MASK, RT5659_DAC_OSR_32);
+ break;
+ case 96000:
+ snd_soc_update_bits(codec, RT5659_ADDA_CLK_1,
+ RT5659_DAC_OSR_MASK, RT5659_DAC_OSR_64);
+ break;
+ default:
+ snd_soc_update_bits(codec, RT5659_ADDA_CLK_1,
+ RT5659_DAC_OSR_MASK, RT5659_DAC_OSR_128);
+ break;
+ }
+
+ return 0;
+}
+
+static int rt5659_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ rt5659->master[dai->id] = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ reg_val |= RT5659_I2S_MS_S;
+ rt5659->master[dai->id] = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ reg_val |= RT5659_I2S_BP_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ reg_val |= RT5659_I2S_DF_LEFT;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ reg_val |= RT5659_I2S_DF_PCM_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ reg_val |= RT5659_I2S_DF_PCM_B;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (dai->id) {
+ case RT5659_AIF1:
+ snd_soc_update_bits(codec, RT5659_I2S1_SDP,
+ RT5659_I2S_MS_MASK | RT5659_I2S_BP_MASK |
+ RT5659_I2S_DF_MASK, reg_val);
+ break;
+ case RT5659_AIF2:
+ snd_soc_update_bits(codec, RT5659_I2S2_SDP,
+ RT5659_I2S_MS_MASK | RT5659_I2S_BP_MASK |
+ RT5659_I2S_DF_MASK, reg_val);
+ break;
+ case RT5659_AIF3:
+ snd_soc_update_bits(codec, RT5659_I2S3_SDP,
+ RT5659_I2S_MS_MASK | RT5659_I2S_BP_MASK |
+ RT5659_I2S_DF_MASK, reg_val);
+ break;
+ default:
+ dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int rt5659_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg_val = 0;
+
+ if (freq == rt5659->sysclk && clk_id == rt5659->sysclk_src)
+ return 0;
+
+ switch (clk_id) {
+ case RT5659_SCLK_S_MCLK:
+ reg_val |= RT5659_SCLK_SRC_MCLK;
+ break;
+ case RT5659_SCLK_S_PLL1:
+ reg_val |= RT5659_SCLK_SRC_PLL1;
+ break;
+ case RT5659_SCLK_S_RCCLK:
+ reg_val |= RT5659_SCLK_SRC_RCCLK;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, RT5659_GLB_CLK,
+ RT5659_SCLK_SRC_MASK, reg_val);
+ rt5659->sysclk = freq;
+ rt5659->sysclk_src = clk_id;
+
+ dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
+
+ return 0;
+}
+
+static int rt5659_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int Source,
+ unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+ struct rl6231_pll_code pll_code;
+ int ret;
+
+ if (Source == rt5659->pll_src && freq_in == rt5659->pll_in &&
+ freq_out == rt5659->pll_out)
+ return 0;
+
+ if (!freq_in || !freq_out) {
+ dev_dbg(codec->dev, "PLL disabled\n");
+
+ rt5659->pll_in = 0;
+ rt5659->pll_out = 0;
+ snd_soc_update_bits(codec, RT5659_GLB_CLK,
+ RT5659_SCLK_SRC_MASK, RT5659_SCLK_SRC_MCLK);
+ return 0;
+ }
+
+ switch (Source) {
+ case RT5659_PLL1_S_MCLK:
+ snd_soc_update_bits(codec, RT5659_GLB_CLK,
+ RT5659_PLL1_SRC_MASK, RT5659_PLL1_SRC_MCLK);
+ break;
+ case RT5659_PLL1_S_BCLK1:
+ snd_soc_update_bits(codec, RT5659_GLB_CLK,
+ RT5659_PLL1_SRC_MASK, RT5659_PLL1_SRC_BCLK1);
+ break;
+ case RT5659_PLL1_S_BCLK2:
+ snd_soc_update_bits(codec, RT5659_GLB_CLK,
+ RT5659_PLL1_SRC_MASK, RT5659_PLL1_SRC_BCLK2);
+ break;
+ case RT5659_PLL1_S_BCLK3:
+ snd_soc_update_bits(codec, RT5659_GLB_CLK,
+ RT5659_PLL1_SRC_MASK, RT5659_PLL1_SRC_BCLK3);
+ break;
+ default:
+ dev_err(codec->dev, "Unknown PLL Source %d\n", Source);
+ return -EINVAL;
+ }
+
+ ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
+ if (ret < 0) {
+ dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
+ return ret;
+ }
+
+ dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
+ pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+ pll_code.n_code, pll_code.k_code);
+
+ snd_soc_write(codec, RT5659_PLL_CTRL_1,
+ pll_code.n_code << RT5659_PLL_N_SFT | pll_code.k_code);
+ snd_soc_write(codec, RT5659_PLL_CTRL_2,
+ (pll_code.m_bp ? 0 : pll_code.m_code) << RT5659_PLL_M_SFT |
+ pll_code.m_bp << RT5659_PLL_M_BP_SFT);
+
+ rt5659->pll_in = freq_in;
+ rt5659->pll_out = freq_out;
+ rt5659->pll_src = Source;
+
+ return 0;
+}
+
+static int rt5659_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+ unsigned int rx_mask, int slots, int slot_width)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val = 0;
+
+ if (rx_mask || tx_mask)
+ val |= (1 << 15);
+
+ switch (slots) {
+ case 4:
+ val |= (1 << 10);
+ val |= (1 << 8);
+ break;
+ case 6:
+ val |= (2 << 10);
+ val |= (2 << 8);
+ break;
+ case 8:
+ val |= (3 << 10);
+ val |= (3 << 8);
+ break;
+ case 2:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (slot_width) {
+ case 20:
+ val |= (1 << 6);
+ val |= (1 << 4);
+ break;
+ case 24:
+ val |= (2 << 6);
+ val |= (2 << 4);
+ break;
+ case 32:
+ val |= (3 << 6);
+ val |= (3 << 4);
+ break;
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, RT5659_TDM_CTRL_1, 0x8ff0, val);
+
+ return 0;
+}
+
+static int rt5659_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio);
+
+ rt5659->bclk[dai->id] = ratio;
+
+ if (ratio == 64) {
+ switch (dai->id) {
+ case RT5659_AIF2:
+ snd_soc_update_bits(codec, RT5659_ADDA_CLK_1,
+ RT5659_I2S_BCLK_MS2_MASK,
+ RT5659_I2S_BCLK_MS2_64);
+ break;
+ case RT5659_AIF3:
+ snd_soc_update_bits(codec, RT5659_ADDA_CLK_1,
+ RT5659_I2S_BCLK_MS3_MASK,
+ RT5659_I2S_BCLK_MS3_64);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int rt5659_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+
+ switch (level) {
+ case SND_SOC_BIAS_PREPARE:
+ regmap_update_bits(rt5659->regmap, RT5659_DIG_MISC,
+ RT5659_DIG_GATE_CTRL, RT5659_DIG_GATE_CTRL);
+ regmap_update_bits(rt5659->regmap, RT5659_PWR_DIG_1,
+ RT5659_PWR_LDO, RT5659_PWR_LDO);
+ regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_1,
+ RT5659_PWR_MB | RT5659_PWR_VREF1 | RT5659_PWR_VREF2,
+ RT5659_PWR_MB | RT5659_PWR_VREF1 | RT5659_PWR_VREF2);
+ msleep(20);
+ regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_1,
+ RT5659_PWR_FV1 | RT5659_PWR_FV2,
+ RT5659_PWR_FV1 | RT5659_PWR_FV2);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ regmap_update_bits(rt5659->regmap, RT5659_PWR_DIG_1,
+ RT5659_PWR_LDO, 0);
+ regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_1,
+ RT5659_PWR_MB | RT5659_PWR_VREF1 | RT5659_PWR_VREF2
+ | RT5659_PWR_FV1 | RT5659_PWR_FV2,
+ RT5659_PWR_MB | RT5659_PWR_VREF2);
+ regmap_update_bits(rt5659->regmap, RT5659_DIG_MISC,
+ RT5659_DIG_GATE_CTRL, 0);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int rt5659_probe(struct snd_soc_codec *codec)
+{
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+
+ rt5659->codec = codec;
+
+ return 0;
+}
+
+static int rt5659_remove(struct snd_soc_codec *codec)
+{
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+
+ regmap_write(rt5659->regmap, RT5659_RESET, 0);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5659_suspend(struct snd_soc_codec *codec)
+{
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5659->regmap, true);
+ regcache_mark_dirty(rt5659->regmap);
+ return 0;
+}
+
+static int rt5659_resume(struct snd_soc_codec *codec)
+{
+ struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_cache_only(rt5659->regmap, false);
+ regcache_sync(rt5659->regmap);
+
+ return 0;
+}
+#else
+#define rt5659_suspend NULL
+#define rt5659_resume NULL
+#endif
+
+#define RT5659_STEREO_RATES SNDRV_PCM_RATE_8000_192000
+#define RT5659_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+static const struct snd_soc_dai_ops rt5659_aif_dai_ops = {
+ .hw_params = rt5659_hw_params,
+ .set_fmt = rt5659_set_dai_fmt,
+ .set_sysclk = rt5659_set_dai_sysclk,
+ .set_tdm_slot = rt5659_set_tdm_slot,
+ .set_pll = rt5659_set_dai_pll,
+ .set_bclk_ratio = rt5659_set_bclk_ratio,
+};
+
+static struct snd_soc_dai_driver rt5659_dai[] = {
+ {
+ .name = "rt5659-aif1",
+ .id = RT5659_AIF1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5659_STEREO_RATES,
+ .formats = RT5659_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5659_STEREO_RATES,
+ .formats = RT5659_FORMATS,
+ },
+ .ops = &rt5659_aif_dai_ops,
+ },
+ {
+ .name = "rt5659-aif2",
+ .id = RT5659_AIF2,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5659_STEREO_RATES,
+ .formats = RT5659_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5659_STEREO_RATES,
+ .formats = RT5659_FORMATS,
+ },
+ .ops = &rt5659_aif_dai_ops,
+ },
+ {
+ .name = "rt5659-aif3",
+ .id = RT5659_AIF3,
+ .playback = {
+ .stream_name = "AIF3 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5659_STEREO_RATES,
+ .formats = RT5659_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF3 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5659_STEREO_RATES,
+ .formats = RT5659_FORMATS,
+ },
+ .ops = &rt5659_aif_dai_ops,
+ },
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5659 = {
+ .probe = rt5659_probe,
+ .remove = rt5659_remove,
+ .suspend = rt5659_suspend,
+ .resume = rt5659_resume,
+ .set_bias_level = rt5659_set_bias_level,
+ .idle_bias_off = true,
+ .controls = rt5659_snd_controls,
+ .num_controls = ARRAY_SIZE(rt5659_snd_controls),
+ .dapm_widgets = rt5659_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt5659_dapm_widgets),
+ .dapm_routes = rt5659_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(rt5659_dapm_routes),
+};
+
+
+static const struct regmap_config rt5659_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+ .max_register = 0x0400,
+ .volatile_reg = rt5659_volatile_register,
+ .readable_reg = rt5659_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = rt5659_reg,
+ .num_reg_defaults = ARRAY_SIZE(rt5659_reg),
+};
+
+static const struct i2c_device_id rt5659_i2c_id[] = {
+ { "rt5658", 0 },
+ { "rt5659", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rt5659_i2c_id);
+
+static int rt5659_parse_dt(struct rt5659_priv *rt5659, struct device *dev)
+{
+ rt5659->pdata.in1_diff = device_property_read_bool(dev,
+ "realtek,in1-differential");
+ rt5659->pdata.in3_diff = device_property_read_bool(dev,
+ "realtek,in3-differential");
+ rt5659->pdata.in4_diff = device_property_read_bool(dev,
+ "realtek,in4-differential");
+
+
+ device_property_read_u32(dev, "realtek,dmic1-data-pin",
+ &rt5659->pdata.dmic1_data_pin);
+ device_property_read_u32(dev, "realtek,dmic2-data-pin",
+ &rt5659->pdata.dmic2_data_pin);
+ device_property_read_u32(dev, "realtek,jd-src",
+ &rt5659->pdata.jd_src);
+
+ return 0;
+}
+
+static void rt5659_calibrate(struct rt5659_priv *rt5659)
+{
+ int value, count;
+
+ /* Calibrate HPO Start */
+ /* Fine tune HP Performance */
+ regmap_write(rt5659->regmap, RT5659_BIAS_CUR_CTRL_8, 0xa502);
+ regmap_write(rt5659->regmap, RT5659_CHOP_DAC, 0x3030);
+
+ regmap_write(rt5659->regmap, RT5659_PRE_DIV_1, 0xef00);
+ regmap_write(rt5659->regmap, RT5659_PRE_DIV_2, 0xeffc);
+ regmap_write(rt5659->regmap, RT5659_MICBIAS_2, 0x0280);
+ regmap_write(rt5659->regmap, RT5659_DIG_MISC, 0x0001);
+ regmap_write(rt5659->regmap, RT5659_GLB_CLK, 0x8000);
+
+ regmap_write(rt5659->regmap, RT5659_PWR_ANLG_1, 0xaa7e);
+ msleep(60);
+ regmap_write(rt5659->regmap, RT5659_PWR_ANLG_1, 0xfe7e);
+ msleep(50);
+ regmap_write(rt5659->regmap, RT5659_PWR_ANLG_3, 0x0004);
+ regmap_write(rt5659->regmap, RT5659_PWR_DIG_2, 0x0400);
+ msleep(50);
+ regmap_write(rt5659->regmap, RT5659_PWR_DIG_1, 0x0080);
+ usleep_range(10000, 10005);
+ regmap_write(rt5659->regmap, RT5659_DEPOP_1, 0x0009);
+ msleep(50);
+ regmap_write(rt5659->regmap, RT5659_PWR_DIG_1, 0x0f80);
+ msleep(50);
+ regmap_write(rt5659->regmap, RT5659_HP_CHARGE_PUMP_1, 0x0e16);
+ msleep(50);
+
+ /* Enalbe K ADC Power And Clock */
+ regmap_write(rt5659->regmap, RT5659_CAL_REC, 0x0505);
+ msleep(50);
+ regmap_write(rt5659->regmap, RT5659_PWR_ANLG_3, 0x0184);
+ regmap_write(rt5659->regmap, RT5659_CALIB_ADC_CTRL, 0x3c05);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_2, 0x20c1);
+
+ /* K Headphone */
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_2, 0x2cc1);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_1, 0x5100);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_7, 0x0014);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_1, 0xd100);
+ msleep(60);
+
+ /* Manual K ADC Offset */
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_2, 0x2cc1);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_1, 0x4900);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_7, 0x0016);
+ regmap_update_bits(rt5659->regmap, RT5659_HP_CALIB_CTRL_1,
+ 0x8000, 0x8000);
+
+ count = 0;
+ while (true) {
+ regmap_read(rt5659->regmap, RT5659_HP_CALIB_CTRL_1, &value);
+ if (value & 0x8000)
+ usleep_range(10000, 10005);
+ else
+ break;
+
+ if (count > 30) {
+ dev_err(rt5659->codec->dev,
+ "HP Calibration 1 Failure\n");
+ return;
+ }
+
+ count++;
+ }
+
+ /* Manual K Internal Path Offset */
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_2, 0x2cc1);
+ regmap_write(rt5659->regmap, RT5659_HP_VOL, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_1, 0x4500);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_7, 0x001f);
+ regmap_update_bits(rt5659->regmap, RT5659_HP_CALIB_CTRL_1,
+ 0x8000, 0x8000);
+
+ count = 0;
+ while (true) {
+ regmap_read(rt5659->regmap, RT5659_HP_CALIB_CTRL_1, &value);
+ if (value & 0x8000)
+ usleep_range(10000, 10005);
+ else
+ break;
+
+ if (count > 85) {
+ dev_err(rt5659->codec->dev,
+ "HP Calibration 2 Failure\n");
+ return;
+ }
+
+ count++;
+ }
+
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_7, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_2, 0x20c0);
+ /* Calibrate HPO End */
+
+ /* Calibrate SPO Start */
+ regmap_write(rt5659->regmap, RT5659_CLASSD_0, 0x2021);
+ regmap_write(rt5659->regmap, RT5659_CLASSD_CTRL_1, 0x0260);
+ regmap_write(rt5659->regmap, RT5659_PWR_MIXER, 0x3000);
+ regmap_write(rt5659->regmap, RT5659_PWR_VOL, 0xc000);
+ regmap_write(rt5659->regmap, RT5659_A_DAC_MUX, 0x000c);
+ regmap_write(rt5659->regmap, RT5659_DIG_MISC, 0x8000);
+ regmap_write(rt5659->regmap, RT5659_SPO_VOL, 0x0808);
+ regmap_write(rt5659->regmap, RT5659_SPK_L_MIXER, 0x001e);
+ regmap_write(rt5659->regmap, RT5659_SPK_R_MIXER, 0x001e);
+ regmap_write(rt5659->regmap, RT5659_CLASSD_1, 0x0803);
+ regmap_write(rt5659->regmap, RT5659_CLASSD_2, 0x0554);
+ regmap_write(rt5659->regmap, RT5659_SPO_AMP_GAIN, 0x1103);
+
+ /* Enalbe K ADC Power And Clock */
+ regmap_write(rt5659->regmap, RT5659_CAL_REC, 0x0909);
+ regmap_update_bits(rt5659->regmap, RT5659_HP_CALIB_CTRL_2, 0x0001,
+ 0x0001);
+
+ /* Start Calibration */
+ regmap_write(rt5659->regmap, RT5659_SPK_DC_CAILB_CTRL_3, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_CLASSD_0, 0x0021);
+ regmap_write(rt5659->regmap, RT5659_SPK_DC_CAILB_CTRL_1, 0x3e80);
+ regmap_update_bits(rt5659->regmap, RT5659_SPK_DC_CAILB_CTRL_1,
+ 0x8000, 0x8000);
+
+ count = 0;
+ while (true) {
+ regmap_read(rt5659->regmap,
+ RT5659_SPK_DC_CAILB_CTRL_1, &value);
+ if (value & 0x8000)
+ usleep_range(10000, 10005);
+ else
+ break;
+
+ if (count > 10) {
+ dev_err(rt5659->codec->dev,
+ "SPK Calibration Failure\n");
+ return;
+ }
+
+ count++;
+ }
+ /* Calibrate SPO End */
+
+ /* Calibrate MONO Start */
+ regmap_write(rt5659->regmap, RT5659_DIG_MISC, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_MONOMIX_IN_GAIN, 0x021f);
+ regmap_write(rt5659->regmap, RT5659_MONO_OUT, 0x480a);
+ /* MONO NG2 GAIN 5dB */
+ regmap_write(rt5659->regmap, RT5659_MONO_GAIN, 0x0003);
+ regmap_write(rt5659->regmap, RT5659_MONO_NG2_CTRL_5, 0x0009);
+
+ /* Start Calibration */
+ regmap_write(rt5659->regmap, RT5659_SPK_DC_CAILB_CTRL_3, 0x000f);
+ regmap_write(rt5659->regmap, RT5659_MONO_AMP_CALIB_CTRL_1, 0x1e00);
+ regmap_update_bits(rt5659->regmap, RT5659_MONO_AMP_CALIB_CTRL_1,
+ 0x8000, 0x8000);
+
+ count = 0;
+ while (true) {
+ regmap_read(rt5659->regmap, RT5659_MONO_AMP_CALIB_CTRL_1,
+ &value);
+ if (value & 0x8000)
+ usleep_range(10000, 10005);
+ else
+ break;
+
+ if (count > 35) {
+ dev_err(rt5659->codec->dev,
+ "Mono Calibration Failure\n");
+ return;
+ }
+
+ count++;
+ }
+
+ regmap_write(rt5659->regmap, RT5659_SPK_DC_CAILB_CTRL_3, 0x0003);
+ /* Calibrate MONO End */
+
+ /* Power Off */
+ regmap_write(rt5659->regmap, RT5659_CAL_REC, 0x0808);
+ regmap_write(rt5659->regmap, RT5659_PWR_ANLG_3, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_CALIB_ADC_CTRL, 0x2005);
+ regmap_write(rt5659->regmap, RT5659_HP_CALIB_CTRL_2, 0x20c0);
+ regmap_write(rt5659->regmap, RT5659_DEPOP_1, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_CLASSD_1, 0x0011);
+ regmap_write(rt5659->regmap, RT5659_CLASSD_2, 0x0150);
+ regmap_write(rt5659->regmap, RT5659_PWR_ANLG_1, 0xfe3e);
+ regmap_write(rt5659->regmap, RT5659_MONO_OUT, 0xc80a);
+ regmap_write(rt5659->regmap, RT5659_MONO_AMP_CALIB_CTRL_1, 0x1e04);
+ regmap_write(rt5659->regmap, RT5659_PWR_MIXER, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_PWR_VOL, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_PWR_DIG_1, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_PWR_DIG_2, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_PWR_ANLG_1, 0x003e);
+ regmap_write(rt5659->regmap, RT5659_CLASSD_CTRL_1, 0x0060);
+ regmap_write(rt5659->regmap, RT5659_CLASSD_0, 0x2021);
+ regmap_write(rt5659->regmap, RT5659_GLB_CLK, 0x0000);
+ regmap_write(rt5659->regmap, RT5659_MICBIAS_2, 0x0080);
+ regmap_write(rt5659->regmap, RT5659_HP_VOL, 0x8080);
+ regmap_write(rt5659->regmap, RT5659_HP_CHARGE_PUMP_1, 0x0c16);
+}
+
+static int rt5659_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt5659_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ struct rt5659_priv *rt5659;
+ int ret;
+ unsigned int val;
+
+ rt5659 = devm_kzalloc(&i2c->dev, sizeof(struct rt5659_priv),
+ GFP_KERNEL);
+
+ if (rt5659 == NULL)
+ return -ENOMEM;
+
+ rt5659->i2c = i2c;
+ i2c_set_clientdata(i2c, rt5659);
+
+ if (pdata)
+ rt5659->pdata = *pdata;
+ else
+ rt5659_parse_dt(rt5659, &i2c->dev);
+
+ rt5659->gpiod_ldo1_en = devm_gpiod_get_optional(&i2c->dev, "ldo1-en",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(rt5659->gpiod_ldo1_en))
+ dev_warn(&i2c->dev, "Request ldo1-en GPIO failed\n");
+
+ rt5659->gpiod_reset = devm_gpiod_get_optional(&i2c->dev, "reset",
+ GPIOD_OUT_HIGH);
+
+ /* Sleep for 300 ms miniumum */
+ usleep_range(300000, 350000);
+
+ rt5659->regmap = devm_regmap_init_i2c(i2c, &rt5659_regmap);
+ if (IS_ERR(rt5659->regmap)) {
+ ret = PTR_ERR(rt5659->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ regmap_read(rt5659->regmap, RT5659_DEVICE_ID, &val);
+ if (val != DEVICE_ID) {
+ dev_err(&i2c->dev,
+ "Device with ID register %x is not rt5659\n", val);
+ return -ENODEV;
+ }
+
+ regmap_write(rt5659->regmap, RT5659_RESET, 0);
+
+ rt5659_calibrate(rt5659);
+
+ /* line in diff mode*/
+ if (rt5659->pdata.in1_diff)
+ regmap_update_bits(rt5659->regmap, RT5659_IN1_IN2,
+ RT5659_IN1_DF_MASK, RT5659_IN1_DF_MASK);
+ if (rt5659->pdata.in3_diff)
+ regmap_update_bits(rt5659->regmap, RT5659_IN3_IN4,
+ RT5659_IN3_DF_MASK, RT5659_IN3_DF_MASK);
+ if (rt5659->pdata.in4_diff)
+ regmap_update_bits(rt5659->regmap, RT5659_IN3_IN4,
+ RT5659_IN4_DF_MASK, RT5659_IN4_DF_MASK);
+
+ /* DMIC pin*/
+ if (rt5659->pdata.dmic1_data_pin != RT5659_DMIC1_NULL ||
+ rt5659->pdata.dmic2_data_pin != RT5659_DMIC2_NULL) {
+ regmap_update_bits(rt5659->regmap, RT5659_GPIO_CTRL_1,
+ RT5659_GP2_PIN_MASK, RT5659_GP2_PIN_DMIC1_SCL);
+
+ switch (rt5659->pdata.dmic1_data_pin) {
+ case RT5659_DMIC1_DATA_IN2N:
+ regmap_update_bits(rt5659->regmap, RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_1_DP_MASK, RT5659_DMIC_1_DP_IN2N);
+ break;
+
+ case RT5659_DMIC1_DATA_GPIO5:
+ regmap_update_bits(rt5659->regmap,
+ RT5659_GPIO_CTRL_3,
+ RT5659_I2S2_PIN_MASK,
+ RT5659_I2S2_PIN_GPIO);
+ regmap_update_bits(rt5659->regmap, RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_1_DP_MASK, RT5659_DMIC_1_DP_GPIO5);
+ regmap_update_bits(rt5659->regmap, RT5659_GPIO_CTRL_1,
+ RT5659_GP5_PIN_MASK, RT5659_GP5_PIN_DMIC1_SDA);
+ break;
+
+ case RT5659_DMIC1_DATA_GPIO9:
+ regmap_update_bits(rt5659->regmap, RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_1_DP_MASK, RT5659_DMIC_1_DP_GPIO9);
+ regmap_update_bits(rt5659->regmap, RT5659_GPIO_CTRL_1,
+ RT5659_GP9_PIN_MASK, RT5659_GP9_PIN_DMIC1_SDA);
+ break;
+
+ case RT5659_DMIC1_DATA_GPIO11:
+ regmap_update_bits(rt5659->regmap, RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_1_DP_MASK, RT5659_DMIC_1_DP_GPIO11);
+ regmap_update_bits(rt5659->regmap, RT5659_GPIO_CTRL_1,
+ RT5659_GP11_PIN_MASK,
+ RT5659_GP11_PIN_DMIC1_SDA);
+ break;
+
+ default:
+ dev_dbg(&i2c->dev, "no DMIC1\n");
+ break;
+ }
+
+ switch (rt5659->pdata.dmic2_data_pin) {
+ case RT5659_DMIC2_DATA_IN2P:
+ regmap_update_bits(rt5659->regmap,
+ RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_2_DP_MASK,
+ RT5659_DMIC_2_DP_IN2P);
+ break;
+
+ case RT5659_DMIC2_DATA_GPIO6:
+ regmap_update_bits(rt5659->regmap,
+ RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_2_DP_MASK,
+ RT5659_DMIC_2_DP_GPIO6);
+ regmap_update_bits(rt5659->regmap,
+ RT5659_GPIO_CTRL_1,
+ RT5659_GP6_PIN_MASK,
+ RT5659_GP6_PIN_DMIC2_SDA);
+ break;
+
+ case RT5659_DMIC2_DATA_GPIO10:
+ regmap_update_bits(rt5659->regmap,
+ RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_2_DP_MASK,
+ RT5659_DMIC_2_DP_GPIO10);
+ regmap_update_bits(rt5659->regmap,
+ RT5659_GPIO_CTRL_1,
+ RT5659_GP10_PIN_MASK,
+ RT5659_GP10_PIN_DMIC2_SDA);
+ break;
+
+ case RT5659_DMIC2_DATA_GPIO12:
+ regmap_update_bits(rt5659->regmap,
+ RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_2_DP_MASK,
+ RT5659_DMIC_2_DP_GPIO12);
+ regmap_update_bits(rt5659->regmap,
+ RT5659_GPIO_CTRL_1,
+ RT5659_GP12_PIN_MASK,
+ RT5659_GP12_PIN_DMIC2_SDA);
+ break;
+
+ default:
+ dev_dbg(&i2c->dev, "no DMIC2\n");
+ break;
+
+ }
+ } else {
+ regmap_update_bits(rt5659->regmap, RT5659_GPIO_CTRL_1,
+ RT5659_GP2_PIN_MASK | RT5659_GP5_PIN_MASK |
+ RT5659_GP9_PIN_MASK | RT5659_GP11_PIN_MASK |
+ RT5659_GP6_PIN_MASK | RT5659_GP10_PIN_MASK |
+ RT5659_GP12_PIN_MASK,
+ RT5659_GP2_PIN_GPIO2 | RT5659_GP5_PIN_GPIO5 |
+ RT5659_GP9_PIN_GPIO9 | RT5659_GP11_PIN_GPIO11 |
+ RT5659_GP6_PIN_GPIO6 | RT5659_GP10_PIN_GPIO10 |
+ RT5659_GP12_PIN_GPIO12);
+ regmap_update_bits(rt5659->regmap, RT5659_DMIC_CTRL_1,
+ RT5659_DMIC_1_DP_MASK | RT5659_DMIC_2_DP_MASK,
+ RT5659_DMIC_1_DP_IN2N | RT5659_DMIC_2_DP_IN2P);
+ }
+
+ switch (rt5659->pdata.jd_src) {
+ case RT5659_JD3:
+ regmap_write(rt5659->regmap, RT5659_EJD_CTRL_1, 0xa880);
+ regmap_write(rt5659->regmap, RT5659_RC_CLK_CTRL, 0x9000);
+ regmap_write(rt5659->regmap, RT5659_GPIO_CTRL_1, 0xc800);
+ regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_1,
+ RT5659_PWR_MB, RT5659_PWR_MB);
+ regmap_write(rt5659->regmap, RT5659_PWR_ANLG_2, 0x0001);
+ regmap_write(rt5659->regmap, RT5659_IRQ_CTRL_2, 0x0040);
+ break;
+ case RT5659_JD_NULL:
+ break;
+ default:
+ dev_warn(&i2c->dev, "Currently, support JD3 only\n");
+ break;
+ }
+
+ INIT_DELAYED_WORK(&rt5659->jack_detect_work, rt5659_jack_detect_work);
+
+ if (rt5659->i2c->irq) {
+ ret = request_threaded_irq(rt5659->i2c->irq, NULL, rt5659_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+ | IRQF_ONESHOT, "rt5659", rt5659);
+ if (ret)
+ dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+
+ }
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5659,
+ rt5659_dai, ARRAY_SIZE(rt5659_dai));
+
+ if (ret) {
+ if (rt5659->i2c->irq)
+ free_irq(rt5659->i2c->irq, rt5659);
+ }
+
+ return 0;
+}
+
+static int rt5659_i2c_remove(struct i2c_client *i2c)
+{
+ snd_soc_unregister_codec(&i2c->dev);
+
+ return 0;
+}
+
+void rt5659_i2c_shutdown(struct i2c_client *client)
+{
+ struct rt5659_priv *rt5659 = i2c_get_clientdata(client);
+
+ regmap_write(rt5659->regmap, RT5659_RESET, 0);
+}
+
+static const struct of_device_id rt5659_of_match[] = {
+ { .compatible = "realtek,rt5658", },
+ { .compatible = "realtek,rt5659", },
+ {},
+};
+
+static struct acpi_device_id rt5659_acpi_match[] = {
+ { "10EC5658", 0},
+ { "10EC5659", 0},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, rt5659_acpi_match);
+
+struct i2c_driver rt5659_i2c_driver = {
+ .driver = {
+ .name = "rt5659",
+ .owner = THIS_MODULE,
+ .of_match_table = rt5659_of_match,
+ .acpi_match_table = ACPI_PTR(rt5659_acpi_match),
+ },
+ .probe = rt5659_i2c_probe,
+ .remove = rt5659_i2c_remove,
+ .shutdown = rt5659_i2c_shutdown,
+ .id_table = rt5659_i2c_id,
+};
+module_i2c_driver(rt5659_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT5659 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5659.h b/sound/soc/codecs/rt5659.h
new file mode 100644
index 000000000000..8f07ee903eaa
--- /dev/null
+++ b/sound/soc/codecs/rt5659.h
@@ -0,0 +1,1819 @@
+/*
+ * rt5659.h -- RT5659/RT5658 ALSA SoC audio driver
+ *
+ * Copyright 2015 Realtek Microelectronics
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __RT5659_H__
+#define __RT5659_H__
+
+#include <sound/rt5659.h>
+
+#define DEVICE_ID 0x6311
+
+/* Info */
+#define RT5659_RESET 0x0000
+#define RT5659_VENDOR_ID 0x00fd
+#define RT5659_VENDOR_ID_1 0x00fe
+#define RT5659_DEVICE_ID 0x00ff
+/* I/O - Output */
+#define RT5659_SPO_VOL 0x0001
+#define RT5659_HP_VOL 0x0002
+#define RT5659_LOUT 0x0003
+#define RT5659_MONO_OUT 0x0004
+#define RT5659_HPL_GAIN 0x0005
+#define RT5659_HPR_GAIN 0x0006
+#define RT5659_MONO_GAIN 0x0007
+#define RT5659_SPDIF_CTRL_1 0x0008
+#define RT5659_SPDIF_CTRL_2 0x0009
+/* I/O - Input */
+#define RT5659_CAL_BST_CTRL 0x000a
+#define RT5659_IN1_IN2 0x000c
+#define RT5659_IN3_IN4 0x000d
+#define RT5659_INL1_INR1_VOL 0x000f
+/* I/O - Speaker */
+#define RT5659_EJD_CTRL_1 0x0010
+#define RT5659_EJD_CTRL_2 0x0011
+#define RT5659_EJD_CTRL_3 0x0012
+#define RT5659_SILENCE_CTRL 0x0015
+#define RT5659_PSV_CTRL 0x0016
+/* I/O - Sidetone */
+#define RT5659_SIDETONE_CTRL 0x0018
+/* I/O - ADC/DAC/DMIC */
+#define RT5659_DAC1_DIG_VOL 0x0019
+#define RT5659_DAC2_DIG_VOL 0x001a
+#define RT5659_DAC_CTRL 0x001b
+#define RT5659_STO1_ADC_DIG_VOL 0x001c
+#define RT5659_MONO_ADC_DIG_VOL 0x001d
+#define RT5659_STO2_ADC_DIG_VOL 0x001e
+#define RT5659_STO1_BOOST 0x001f
+#define RT5659_MONO_BOOST 0x0020
+#define RT5659_STO2_BOOST 0x0021
+#define RT5659_HP_IMP_GAIN_1 0x0022
+#define RT5659_HP_IMP_GAIN_2 0x0023
+/* Mixer - D-D */
+#define RT5659_STO1_ADC_MIXER 0x0026
+#define RT5659_MONO_ADC_MIXER 0x0027
+#define RT5659_AD_DA_MIXER 0x0029
+#define RT5659_STO_DAC_MIXER 0x002a
+#define RT5659_MONO_DAC_MIXER 0x002b
+#define RT5659_DIG_MIXER 0x002c
+#define RT5659_A_DAC_MUX 0x002d
+#define RT5659_DIG_INF23_DATA 0x002f
+/* Mixer - PDM */
+#define RT5659_PDM_OUT_CTRL 0x0031
+#define RT5659_PDM_DATA_CTRL_1 0x0032
+#define RT5659_PDM_DATA_CTRL_2 0x0033
+#define RT5659_PDM_DATA_CTRL_3 0x0034
+#define RT5659_PDM_DATA_CTRL_4 0x0035
+#define RT5659_SPDIF_CTRL 0x0036
+
+/* Mixer - ADC */
+#define RT5659_REC1_GAIN 0x003a
+#define RT5659_REC1_L1_MIXER 0x003b
+#define RT5659_REC1_L2_MIXER 0x003c
+#define RT5659_REC1_R1_MIXER 0x003d
+#define RT5659_REC1_R2_MIXER 0x003e
+#define RT5659_CAL_REC 0x0040
+#define RT5659_REC2_L1_MIXER 0x009b
+#define RT5659_REC2_L2_MIXER 0x009c
+#define RT5659_REC2_R1_MIXER 0x009d
+#define RT5659_REC2_R2_MIXER 0x009e
+#define RT5659_RC_CLK_CTRL 0x009f
+/* Mixer - DAC */
+#define RT5659_SPK_L_MIXER 0x0046
+#define RT5659_SPK_R_MIXER 0x0047
+#define RT5659_SPO_AMP_GAIN 0x0048
+#define RT5659_ALC_BACK_GAIN 0x0049
+#define RT5659_MONOMIX_GAIN 0x004a
+#define RT5659_MONOMIX_IN_GAIN 0x004b
+#define RT5659_OUT_L_GAIN 0x004d
+#define RT5659_OUT_L_MIXER 0x004e
+#define RT5659_OUT_R_GAIN 0x004f
+#define RT5659_OUT_R_MIXER 0x0050
+#define RT5659_LOUT_MIXER 0x0052
+
+#define RT5659_HAPTIC_GEN_CTRL_1 0x0053
+#define RT5659_HAPTIC_GEN_CTRL_2 0x0054
+#define RT5659_HAPTIC_GEN_CTRL_3 0x0055
+#define RT5659_HAPTIC_GEN_CTRL_4 0x0056
+#define RT5659_HAPTIC_GEN_CTRL_5 0x0057
+#define RT5659_HAPTIC_GEN_CTRL_6 0x0058
+#define RT5659_HAPTIC_GEN_CTRL_7 0x0059
+#define RT5659_HAPTIC_GEN_CTRL_8 0x005a
+#define RT5659_HAPTIC_GEN_CTRL_9 0x005b
+#define RT5659_HAPTIC_GEN_CTRL_10 0x005c
+#define RT5659_HAPTIC_GEN_CTRL_11 0x005d
+#define RT5659_HAPTIC_LPF_CTRL_1 0x005e
+#define RT5659_HAPTIC_LPF_CTRL_2 0x005f
+#define RT5659_HAPTIC_LPF_CTRL_3 0x0060
+/* Power */
+#define RT5659_PWR_DIG_1 0x0061
+#define RT5659_PWR_DIG_2 0x0062
+#define RT5659_PWR_ANLG_1 0x0063
+#define RT5659_PWR_ANLG_2 0x0064
+#define RT5659_PWR_ANLG_3 0x0065
+#define RT5659_PWR_MIXER 0x0066
+#define RT5659_PWR_VOL 0x0067
+/* Private Register Control */
+#define RT5659_PRIV_INDEX 0x006a
+#define RT5659_CLK_DET 0x006b
+#define RT5659_PRIV_DATA 0x006c
+/* System Clock Pre Divider Gating Control */
+#define RT5659_PRE_DIV_1 0x006e
+#define RT5659_PRE_DIV_2 0x006f
+/* Format - ADC/DAC */
+#define RT5659_I2S1_SDP 0x0070
+#define RT5659_I2S2_SDP 0x0071
+#define RT5659_I2S3_SDP 0x0072
+#define RT5659_ADDA_CLK_1 0x0073
+#define RT5659_ADDA_CLK_2 0x0074
+#define RT5659_DMIC_CTRL_1 0x0075
+#define RT5659_DMIC_CTRL_2 0x0076
+/* Format - TDM Control */
+#define RT5659_TDM_CTRL_1 0x0077
+#define RT5659_TDM_CTRL_2 0x0078
+#define RT5659_TDM_CTRL_3 0x0079
+#define RT5659_TDM_CTRL_4 0x007a
+#define RT5659_TDM_CTRL_5 0x007b
+
+/* Function - Analog */
+#define RT5659_GLB_CLK 0x0080
+#define RT5659_PLL_CTRL_1 0x0081
+#define RT5659_PLL_CTRL_2 0x0082
+#define RT5659_ASRC_1 0x0083
+#define RT5659_ASRC_2 0x0084
+#define RT5659_ASRC_3 0x0085
+#define RT5659_ASRC_4 0x0086
+#define RT5659_ASRC_5 0x0087
+#define RT5659_ASRC_6 0x0088
+#define RT5659_ASRC_7 0x0089
+#define RT5659_ASRC_8 0x008a
+#define RT5659_ASRC_9 0x008b
+#define RT5659_ASRC_10 0x008c
+#define RT5659_DEPOP_1 0x008e
+#define RT5659_DEPOP_2 0x008f
+#define RT5659_DEPOP_3 0x0090
+#define RT5659_HP_CHARGE_PUMP_1 0x0091
+#define RT5659_HP_CHARGE_PUMP_2 0x0092
+#define RT5659_MICBIAS_1 0x0093
+#define RT5659_MICBIAS_2 0x0094
+#define RT5659_ASRC_11 0x0097
+#define RT5659_ASRC_12 0x0098
+#define RT5659_ASRC_13 0x0099
+#define RT5659_REC_M1_M2_GAIN_CTRL 0x009a
+#define RT5659_CLASSD_CTRL_1 0x00a0
+#define RT5659_CLASSD_CTRL_2 0x00a1
+
+/* Function - Digital */
+#define RT5659_ADC_EQ_CTRL_1 0x00ae
+#define RT5659_ADC_EQ_CTRL_2 0x00af
+#define RT5659_DAC_EQ_CTRL_1 0x00b0
+#define RT5659_DAC_EQ_CTRL_2 0x00b1
+#define RT5659_DAC_EQ_CTRL_3 0x00b2
+
+#define RT5659_IRQ_CTRL_1 0x00b6
+#define RT5659_IRQ_CTRL_2 0x00b7
+#define RT5659_IRQ_CTRL_3 0x00b8
+#define RT5659_IRQ_CTRL_4 0x00b9
+#define RT5659_IRQ_CTRL_5 0x00ba
+#define RT5659_IRQ_CTRL_6 0x00bb
+#define RT5659_INT_ST_1 0x00be
+#define RT5659_INT_ST_2 0x00bf
+#define RT5659_GPIO_CTRL_1 0x00c0
+#define RT5659_GPIO_CTRL_2 0x00c1
+#define RT5659_GPIO_CTRL_3 0x00c2
+#define RT5659_GPIO_CTRL_4 0x00c3
+#define RT5659_GPIO_CTRL_5 0x00c4
+#define RT5659_GPIO_STA 0x00c5
+#define RT5659_SINE_GEN_CTRL_1 0x00cb
+#define RT5659_SINE_GEN_CTRL_2 0x00cc
+#define RT5659_SINE_GEN_CTRL_3 0x00cd
+#define RT5659_HP_AMP_DET_CTRL_1 0x00d6
+#define RT5659_HP_AMP_DET_CTRL_2 0x00d7
+#define RT5659_SV_ZCD_1 0x00d9
+#define RT5659_SV_ZCD_2 0x00da
+#define RT5659_IL_CMD_1 0x00db
+#define RT5659_IL_CMD_2 0x00dc
+#define RT5659_IL_CMD_3 0x00dd
+#define RT5659_IL_CMD_4 0x00de
+#define RT5659_4BTN_IL_CMD_1 0x00df
+#define RT5659_4BTN_IL_CMD_2 0x00e0
+#define RT5659_4BTN_IL_CMD_3 0x00e1
+#define RT5659_PSV_IL_CMD_1 0x00e4
+#define RT5659_PSV_IL_CMD_2 0x00e5
+
+#define RT5659_ADC_STO1_HP_CTRL_1 0x00ea
+#define RT5659_ADC_STO1_HP_CTRL_2 0x00eb
+#define RT5659_ADC_MONO_HP_CTRL_1 0x00ec
+#define RT5659_ADC_MONO_HP_CTRL_2 0x00ed
+#define RT5659_AJD1_CTRL 0x00f0
+#define RT5659_AJD2_AJD3_CTRL 0x00f1
+#define RT5659_JD1_THD 0x00f2
+#define RT5659_JD2_THD 0x00f3
+#define RT5659_JD3_THD 0x00f4
+#define RT5659_JD_CTRL_1 0x00f6
+#define RT5659_JD_CTRL_2 0x00f7
+#define RT5659_JD_CTRL_3 0x00f8
+#define RT5659_JD_CTRL_4 0x00f9
+/* General Control */
+#define RT5659_DIG_MISC 0x00fa
+#define RT5659_DUMMY_2 0x00fb
+#define RT5659_DUMMY_3 0x00fc
+
+#define RT5659_DAC_ADC_DIG_VOL 0x0100
+#define RT5659_BIAS_CUR_CTRL_1 0x010a
+#define RT5659_BIAS_CUR_CTRL_2 0x010b
+#define RT5659_BIAS_CUR_CTRL_3 0x010c
+#define RT5659_BIAS_CUR_CTRL_4 0x010d
+#define RT5659_BIAS_CUR_CTRL_5 0x010e
+#define RT5659_BIAS_CUR_CTRL_6 0x010f
+#define RT5659_BIAS_CUR_CTRL_7 0x0110
+#define RT5659_BIAS_CUR_CTRL_8 0x0111
+#define RT5659_BIAS_CUR_CTRL_9 0x0112
+#define RT5659_BIAS_CUR_CTRL_10 0x0113
+#define RT5659_MEMORY_TEST 0x0116
+#define RT5659_VREF_REC_OP_FB_CAP_CTRL 0x0117
+#define RT5659_CLASSD_0 0x011a
+#define RT5659_CLASSD_1 0x011b
+#define RT5659_CLASSD_2 0x011c
+#define RT5659_CLASSD_3 0x011d
+#define RT5659_CLASSD_4 0x011e
+#define RT5659_CLASSD_5 0x011f
+#define RT5659_CLASSD_6 0x0120
+#define RT5659_CLASSD_7 0x0121
+#define RT5659_CLASSD_8 0x0122
+#define RT5659_CLASSD_9 0x0123
+#define RT5659_CLASSD_10 0x0124
+#define RT5659_CHARGE_PUMP_1 0x0125
+#define RT5659_CHARGE_PUMP_2 0x0126
+#define RT5659_DIG_IN_CTRL_1 0x0132
+#define RT5659_DIG_IN_CTRL_2 0x0133
+#define RT5659_PAD_DRIVING_CTRL 0x0137
+#define RT5659_SOFT_RAMP_DEPOP 0x0138
+#define RT5659_PLL 0x0139
+#define RT5659_CHOP_DAC 0x013a
+#define RT5659_CHOP_ADC 0x013b
+#define RT5659_CALIB_ADC_CTRL 0x013c
+#define RT5659_SOFT_RAMP_DEPOP_DAC_CLK_CTRL 0x013e
+#define RT5659_VOL_TEST 0x013f
+#define RT5659_TEST_MODE_CTRL_1 0x0145
+#define RT5659_TEST_MODE_CTRL_2 0x0146
+#define RT5659_TEST_MODE_CTRL_3 0x0147
+#define RT5659_TEST_MODE_CTRL_4 0x0148
+#define RT5659_BASSBACK_CTRL 0x0150
+#define RT5659_MP3_PLUS_CTRL_1 0x0151
+#define RT5659_MP3_PLUS_CTRL_2 0x0152
+#define RT5659_MP3_HPF_A1 0x0153
+#define RT5659_MP3_HPF_A2 0x0154
+#define RT5659_MP3_HPF_H0 0x0155
+#define RT5659_MP3_LPF_H0 0x0156
+#define RT5659_3D_SPK_CTRL 0x0157
+#define RT5659_3D_SPK_COEF_1 0x0158
+#define RT5659_3D_SPK_COEF_2 0x0159
+#define RT5659_3D_SPK_COEF_3 0x015a
+#define RT5659_3D_SPK_COEF_4 0x015b
+#define RT5659_3D_SPK_COEF_5 0x015c
+#define RT5659_3D_SPK_COEF_6 0x015d
+#define RT5659_3D_SPK_COEF_7 0x015e
+#define RT5659_STO_NG2_CTRL_1 0x0160
+#define RT5659_STO_NG2_CTRL_2 0x0161
+#define RT5659_STO_NG2_CTRL_3 0x0162
+#define RT5659_STO_NG2_CTRL_4 0x0163
+#define RT5659_STO_NG2_CTRL_5 0x0164
+#define RT5659_STO_NG2_CTRL_6 0x0165
+#define RT5659_STO_NG2_CTRL_7 0x0166
+#define RT5659_STO_NG2_CTRL_8 0x0167
+#define RT5659_MONO_NG2_CTRL_1 0x0170
+#define RT5659_MONO_NG2_CTRL_2 0x0171
+#define RT5659_MONO_NG2_CTRL_3 0x0172
+#define RT5659_MONO_NG2_CTRL_4 0x0173
+#define RT5659_MONO_NG2_CTRL_5 0x0174
+#define RT5659_MONO_NG2_CTRL_6 0x0175
+#define RT5659_MID_HP_AMP_DET 0x0190
+#define RT5659_LOW_HP_AMP_DET 0x0191
+#define RT5659_LDO_CTRL 0x0192
+#define RT5659_HP_DECROSS_CTRL_1 0x01b0
+#define RT5659_HP_DECROSS_CTRL_2 0x01b1
+#define RT5659_HP_DECROSS_CTRL_3 0x01b2
+#define RT5659_HP_DECROSS_CTRL_4 0x01b3
+#define RT5659_HP_IMP_SENS_CTRL_1 0x01c0
+#define RT5659_HP_IMP_SENS_CTRL_2 0x01c1
+#define RT5659_HP_IMP_SENS_CTRL_3 0x01c2
+#define RT5659_HP_IMP_SENS_CTRL_4 0x01c3
+#define RT5659_HP_IMP_SENS_MAP_1 0x01c7
+#define RT5659_HP_IMP_SENS_MAP_2 0x01c8
+#define RT5659_HP_IMP_SENS_MAP_3 0x01c9
+#define RT5659_HP_IMP_SENS_MAP_4 0x01ca
+#define RT5659_HP_IMP_SENS_MAP_5 0x01cb
+#define RT5659_HP_IMP_SENS_MAP_6 0x01cc
+#define RT5659_HP_IMP_SENS_MAP_7 0x01cd
+#define RT5659_HP_IMP_SENS_MAP_8 0x01ce
+#define RT5659_HP_LOGIC_CTRL_1 0x01da
+#define RT5659_HP_LOGIC_CTRL_2 0x01db
+#define RT5659_HP_CALIB_CTRL_1 0x01de
+#define RT5659_HP_CALIB_CTRL_2 0x01df
+#define RT5659_HP_CALIB_CTRL_3 0x01e0
+#define RT5659_HP_CALIB_CTRL_4 0x01e1
+#define RT5659_HP_CALIB_CTRL_5 0x01e2
+#define RT5659_HP_CALIB_CTRL_6 0x01e3
+#define RT5659_HP_CALIB_CTRL_7 0x01e4
+#define RT5659_HP_CALIB_CTRL_9 0x01e6
+#define RT5659_HP_CALIB_CTRL_10 0x01e7
+#define RT5659_HP_CALIB_CTRL_11 0x01e8
+#define RT5659_HP_CALIB_STA_1 0x01ea
+#define RT5659_HP_CALIB_STA_2 0x01eb
+#define RT5659_HP_CALIB_STA_3 0x01ec
+#define RT5659_HP_CALIB_STA_4 0x01ed
+#define RT5659_HP_CALIB_STA_5 0x01ee
+#define RT5659_HP_CALIB_STA_6 0x01ef
+#define RT5659_HP_CALIB_STA_7 0x01f0
+#define RT5659_HP_CALIB_STA_8 0x01f1
+#define RT5659_HP_CALIB_STA_9 0x01f2
+#define RT5659_MONO_AMP_CALIB_CTRL_1 0x01f6
+#define RT5659_MONO_AMP_CALIB_CTRL_2 0x01f7
+#define RT5659_MONO_AMP_CALIB_CTRL_3 0x01f8
+#define RT5659_MONO_AMP_CALIB_CTRL_4 0x01f9
+#define RT5659_MONO_AMP_CALIB_CTRL_5 0x01fa
+#define RT5659_MONO_AMP_CALIB_STA_1 0x01fb
+#define RT5659_MONO_AMP_CALIB_STA_2 0x01fc
+#define RT5659_MONO_AMP_CALIB_STA_3 0x01fd
+#define RT5659_MONO_AMP_CALIB_STA_4 0x01fe
+#define RT5659_SPK_PWR_LMT_CTRL_1 0x0200
+#define RT5659_SPK_PWR_LMT_CTRL_2 0x0201
+#define RT5659_SPK_PWR_LMT_CTRL_3 0x0202
+#define RT5659_SPK_PWR_LMT_STA_1 0x0203
+#define RT5659_SPK_PWR_LMT_STA_2 0x0204
+#define RT5659_SPK_PWR_LMT_STA_3 0x0205
+#define RT5659_SPK_PWR_LMT_STA_4 0x0206
+#define RT5659_SPK_PWR_LMT_STA_5 0x0207
+#define RT5659_SPK_PWR_LMT_STA_6 0x0208
+#define RT5659_FLEX_SPK_BST_CTRL_1 0x0256
+#define RT5659_FLEX_SPK_BST_CTRL_2 0x0257
+#define RT5659_FLEX_SPK_BST_CTRL_3 0x0258
+#define RT5659_FLEX_SPK_BST_CTRL_4 0x0259
+#define RT5659_SPK_EX_LMT_CTRL_1 0x025a
+#define RT5659_SPK_EX_LMT_CTRL_2 0x025b
+#define RT5659_SPK_EX_LMT_CTRL_3 0x025c
+#define RT5659_SPK_EX_LMT_CTRL_4 0x025d
+#define RT5659_SPK_EX_LMT_CTRL_5 0x025e
+#define RT5659_SPK_EX_LMT_CTRL_6 0x025f
+#define RT5659_SPK_EX_LMT_CTRL_7 0x0260
+#define RT5659_ADJ_HPF_CTRL_1 0x0261
+#define RT5659_ADJ_HPF_CTRL_2 0x0262
+#define RT5659_SPK_DC_CAILB_CTRL_1 0x0265
+#define RT5659_SPK_DC_CAILB_CTRL_2 0x0266
+#define RT5659_SPK_DC_CAILB_CTRL_3 0x0267
+#define RT5659_SPK_DC_CAILB_CTRL_4 0x0268
+#define RT5659_SPK_DC_CAILB_CTRL_5 0x0269
+#define RT5659_SPK_DC_CAILB_STA_1 0x026a
+#define RT5659_SPK_DC_CAILB_STA_2 0x026b
+#define RT5659_SPK_DC_CAILB_STA_3 0x026c
+#define RT5659_SPK_DC_CAILB_STA_4 0x026d
+#define RT5659_SPK_DC_CAILB_STA_5 0x026e
+#define RT5659_SPK_DC_CAILB_STA_6 0x026f
+#define RT5659_SPK_DC_CAILB_STA_7 0x0270
+#define RT5659_SPK_DC_CAILB_STA_8 0x0271
+#define RT5659_SPK_DC_CAILB_STA_9 0x0272
+#define RT5659_SPK_DC_CAILB_STA_10 0x0273
+#define RT5659_SPK_VDD_STA_1 0x0280
+#define RT5659_SPK_VDD_STA_2 0x0281
+#define RT5659_SPK_DC_DET_CTRL_1 0x0282
+#define RT5659_SPK_DC_DET_CTRL_2 0x0283
+#define RT5659_SPK_DC_DET_CTRL_3 0x0284
+#define RT5659_PURE_DC_DET_CTRL_1 0x0290
+#define RT5659_PURE_DC_DET_CTRL_2 0x0291
+#define RT5659_DUMMY_4 0x02fa
+#define RT5659_DUMMY_5 0x02fb
+#define RT5659_DUMMY_6 0x02fc
+#define RT5659_DRC1_CTRL_1 0x0300
+#define RT5659_DRC1_CTRL_2 0x0301
+#define RT5659_DRC1_CTRL_3 0x0302
+#define RT5659_DRC1_CTRL_4 0x0303
+#define RT5659_DRC1_CTRL_5 0x0304
+#define RT5659_DRC1_CTRL_6 0x0305
+#define RT5659_DRC1_HARD_LMT_CTRL_1 0x0306
+#define RT5659_DRC1_HARD_LMT_CTRL_2 0x0307
+#define RT5659_DRC2_CTRL_1 0x0308
+#define RT5659_DRC2_CTRL_2 0x0309
+#define RT5659_DRC2_CTRL_3 0x030a
+#define RT5659_DRC2_CTRL_4 0x030b
+#define RT5659_DRC2_CTRL_5 0x030c
+#define RT5659_DRC2_CTRL_6 0x030d
+#define RT5659_DRC2_HARD_LMT_CTRL_1 0x030e
+#define RT5659_DRC2_HARD_LMT_CTRL_2 0x030f
+#define RT5659_DRC1_PRIV_1 0x0310
+#define RT5659_DRC1_PRIV_2 0x0311
+#define RT5659_DRC1_PRIV_3 0x0312
+#define RT5659_DRC1_PRIV_4 0x0313
+#define RT5659_DRC1_PRIV_5 0x0314
+#define RT5659_DRC1_PRIV_6 0x0315
+#define RT5659_DRC1_PRIV_7 0x0316
+#define RT5659_DRC2_PRIV_1 0x0317
+#define RT5659_DRC2_PRIV_2 0x0318
+#define RT5659_DRC2_PRIV_3 0x0319
+#define RT5659_DRC2_PRIV_4 0x031a
+#define RT5659_DRC2_PRIV_5 0x031b
+#define RT5659_DRC2_PRIV_6 0x031c
+#define RT5659_DRC2_PRIV_7 0x031d
+#define RT5659_MULTI_DRC_CTRL 0x0320
+#define RT5659_CROSS_OVER_1 0x0321
+#define RT5659_CROSS_OVER_2 0x0322
+#define RT5659_CROSS_OVER_3 0x0323
+#define RT5659_CROSS_OVER_4 0x0324
+#define RT5659_CROSS_OVER_5 0x0325
+#define RT5659_CROSS_OVER_6 0x0326
+#define RT5659_CROSS_OVER_7 0x0327
+#define RT5659_CROSS_OVER_8 0x0328
+#define RT5659_CROSS_OVER_9 0x0329
+#define RT5659_CROSS_OVER_10 0x032a
+#define RT5659_ALC_PGA_CTRL_1 0x0330
+#define RT5659_ALC_PGA_CTRL_2 0x0331
+#define RT5659_ALC_PGA_CTRL_3 0x0332
+#define RT5659_ALC_PGA_CTRL_4 0x0333
+#define RT5659_ALC_PGA_CTRL_5 0x0334
+#define RT5659_ALC_PGA_CTRL_6 0x0335
+#define RT5659_ALC_PGA_CTRL_7 0x0336
+#define RT5659_ALC_PGA_CTRL_8 0x0337
+#define RT5659_ALC_PGA_STA_1 0x0338
+#define RT5659_ALC_PGA_STA_2 0x0339
+#define RT5659_ALC_PGA_STA_3 0x033a
+#define RT5659_DAC_L_EQ_PRE_VOL 0x0340
+#define RT5659_DAC_R_EQ_PRE_VOL 0x0341
+#define RT5659_DAC_L_EQ_POST_VOL 0x0342
+#define RT5659_DAC_R_EQ_POST_VOL 0x0343
+#define RT5659_DAC_L_EQ_LPF1_A1 0x0344
+#define RT5659_DAC_L_EQ_LPF1_H0 0x0345
+#define RT5659_DAC_R_EQ_LPF1_A1 0x0346
+#define RT5659_DAC_R_EQ_LPF1_H0 0x0347
+#define RT5659_DAC_L_EQ_BPF2_A1 0x0348
+#define RT5659_DAC_L_EQ_BPF2_A2 0x0349
+#define RT5659_DAC_L_EQ_BPF2_H0 0x034a
+#define RT5659_DAC_R_EQ_BPF2_A1 0x034b
+#define RT5659_DAC_R_EQ_BPF2_A2 0x034c
+#define RT5659_DAC_R_EQ_BPF2_H0 0x034d
+#define RT5659_DAC_L_EQ_BPF3_A1 0x034e
+#define RT5659_DAC_L_EQ_BPF3_A2 0x034f
+#define RT5659_DAC_L_EQ_BPF3_H0 0x0350
+#define RT5659_DAC_R_EQ_BPF3_A1 0x0351
+#define RT5659_DAC_R_EQ_BPF3_A2 0x0352
+#define RT5659_DAC_R_EQ_BPF3_H0 0x0353
+#define RT5659_DAC_L_EQ_BPF4_A1 0x0354
+#define RT5659_DAC_L_EQ_BPF4_A2 0x0355
+#define RT5659_DAC_L_EQ_BPF4_H0 0x0356
+#define RT5659_DAC_R_EQ_BPF4_A1 0x0357
+#define RT5659_DAC_R_EQ_BPF4_A2 0x0358
+#define RT5659_DAC_R_EQ_BPF4_H0 0x0359
+#define RT5659_DAC_L_EQ_HPF1_A1 0x035a
+#define RT5659_DAC_L_EQ_HPF1_H0 0x035b
+#define RT5659_DAC_R_EQ_HPF1_A1 0x035c
+#define RT5659_DAC_R_EQ_HPF1_H0 0x035d
+#define RT5659_DAC_L_EQ_HPF2_A1 0x035e
+#define RT5659_DAC_L_EQ_HPF2_A2 0x035f
+#define RT5659_DAC_L_EQ_HPF2_H0 0x0360
+#define RT5659_DAC_R_EQ_HPF2_A1 0x0361
+#define RT5659_DAC_R_EQ_HPF2_A2 0x0362
+#define RT5659_DAC_R_EQ_HPF2_H0 0x0363
+#define RT5659_DAC_L_BI_EQ_BPF1_H0_1 0x0364
+#define RT5659_DAC_L_BI_EQ_BPF1_H0_2 0x0365
+#define RT5659_DAC_L_BI_EQ_BPF1_B1_1 0x0366
+#define RT5659_DAC_L_BI_EQ_BPF1_B1_2 0x0367
+#define RT5659_DAC_L_BI_EQ_BPF1_B2_1 0x0368
+#define RT5659_DAC_L_BI_EQ_BPF1_B2_2 0x0369
+#define RT5659_DAC_L_BI_EQ_BPF1_A1_1 0x036a
+#define RT5659_DAC_L_BI_EQ_BPF1_A1_2 0x036b
+#define RT5659_DAC_L_BI_EQ_BPF1_A2_1 0x036c
+#define RT5659_DAC_L_BI_EQ_BPF1_A2_2 0x036d
+#define RT5659_DAC_R_BI_EQ_BPF1_H0_1 0x036e
+#define RT5659_DAC_R_BI_EQ_BPF1_H0_2 0x036f
+#define RT5659_DAC_R_BI_EQ_BPF1_B1_1 0x0370
+#define RT5659_DAC_R_BI_EQ_BPF1_B1_2 0x0371
+#define RT5659_DAC_R_BI_EQ_BPF1_B2_1 0x0372
+#define RT5659_DAC_R_BI_EQ_BPF1_B2_2 0x0373
+#define RT5659_DAC_R_BI_EQ_BPF1_A1_1 0x0374
+#define RT5659_DAC_R_BI_EQ_BPF1_A1_2 0x0375
+#define RT5659_DAC_R_BI_EQ_BPF1_A2_1 0x0376
+#define RT5659_DAC_R_BI_EQ_BPF1_A2_2 0x0377
+#define RT5659_ADC_L_EQ_LPF1_A1 0x03d0
+#define RT5659_ADC_R_EQ_LPF1_A1 0x03d1
+#define RT5659_ADC_L_EQ_LPF1_H0 0x03d2
+#define RT5659_ADC_R_EQ_LPF1_H0 0x03d3
+#define RT5659_ADC_L_EQ_BPF1_A1 0x03d4
+#define RT5659_ADC_R_EQ_BPF1_A1 0x03d5
+#define RT5659_ADC_L_EQ_BPF1_A2 0x03d6
+#define RT5659_ADC_R_EQ_BPF1_A2 0x03d7
+#define RT5659_ADC_L_EQ_BPF1_H0 0x03d8
+#define RT5659_ADC_R_EQ_BPF1_H0 0x03d9
+#define RT5659_ADC_L_EQ_BPF2_A1 0x03da
+#define RT5659_ADC_R_EQ_BPF2_A1 0x03db
+#define RT5659_ADC_L_EQ_BPF2_A2 0x03dc
+#define RT5659_ADC_R_EQ_BPF2_A2 0x03dd
+#define RT5659_ADC_L_EQ_BPF2_H0 0x03de
+#define RT5659_ADC_R_EQ_BPF2_H0 0x03df
+#define RT5659_ADC_L_EQ_BPF3_A1 0x03e0
+#define RT5659_ADC_R_EQ_BPF3_A1 0x03e1
+#define RT5659_ADC_L_EQ_BPF3_A2 0x03e2
+#define RT5659_ADC_R_EQ_BPF3_A2 0x03e3
+#define RT5659_ADC_L_EQ_BPF3_H0 0x03e4
+#define RT5659_ADC_R_EQ_BPF3_H0 0x03e5
+#define RT5659_ADC_L_EQ_BPF4_A1 0x03e6
+#define RT5659_ADC_R_EQ_BPF4_A1 0x03e7
+#define RT5659_ADC_L_EQ_BPF4_A2 0x03e8
+#define RT5659_ADC_R_EQ_BPF4_A2 0x03e9
+#define RT5659_ADC_L_EQ_BPF4_H0 0x03ea
+#define RT5659_ADC_R_EQ_BPF4_H0 0x03eb
+#define RT5659_ADC_L_EQ_HPF1_A1 0x03ec
+#define RT5659_ADC_R_EQ_HPF1_A1 0x03ed
+#define RT5659_ADC_L_EQ_HPF1_H0 0x03ee
+#define RT5659_ADC_R_EQ_HPF1_H0 0x03ef
+#define RT5659_ADC_L_EQ_PRE_VOL 0x03f0
+#define RT5659_ADC_R_EQ_PRE_VOL 0x03f1
+#define RT5659_ADC_L_EQ_POST_VOL 0x03f2
+#define RT5659_ADC_R_EQ_POST_VOL 0x03f3
+
+
+
+/* global definition */
+#define RT5659_L_MUTE (0x1 << 15)
+#define RT5659_L_MUTE_SFT 15
+#define RT5659_VOL_L_MUTE (0x1 << 14)
+#define RT5659_VOL_L_SFT 14
+#define RT5659_R_MUTE (0x1 << 7)
+#define RT5659_R_MUTE_SFT 7
+#define RT5659_VOL_R_MUTE (0x1 << 6)
+#define RT5659_VOL_R_SFT 6
+#define RT5659_L_VOL_MASK (0x3f << 8)
+#define RT5659_L_VOL_SFT 8
+#define RT5659_R_VOL_MASK (0x3f)
+#define RT5659_R_VOL_SFT 0
+
+/*Headphone Amp L/R Analog Gain and Digital NG2 Gain Control (0x0005 0x0006)*/
+#define RT5659_G_HP (0x1f << 8)
+#define RT5659_G_HP_SFT 8
+#define RT5659_G_STO_DA_DMIX (0x1f)
+#define RT5659_G_STO_DA_SFT 0
+
+/* IN1/IN2 Control (0x000c) */
+#define RT5659_IN1_DF_MASK (0x1 << 15)
+#define RT5659_IN1_DF 15
+#define RT5659_BST1_MASK (0x7f << 8)
+#define RT5659_BST1_SFT 8
+#define RT5659_BST2_MASK (0x7f)
+#define RT5659_BST2_SFT 0
+
+/* IN3/IN4 Control (0x000d) */
+#define RT5659_IN3_DF_MASK (0x1 << 15)
+#define RT5659_IN3_DF 15
+#define RT5659_BST3_MASK (0x7f << 8)
+#define RT5659_BST3_SFT 8
+#define RT5659_IN4_DF_MASK (0x1 << 7)
+#define RT5659_IN4_DF 7
+#define RT5659_BST4_MASK (0x7f)
+#define RT5659_BST4_SFT 0
+
+/* INL and INR Volume Control (0x000f) */
+#define RT5659_INL_VOL_MASK (0x1f << 8)
+#define RT5659_INL_VOL_SFT 8
+#define RT5659_INR_VOL_MASK (0x1f)
+#define RT5659_INR_VOL_SFT 0
+
+/* Embeeded Jack and Type Detection Control 1 (0x0010) */
+#define RT5659_EMB_JD_EN (0x1 << 15)
+#define RT5659_EMB_JD_EN_SFT 15
+#define RT5659_JD_MODE (0x1 << 13)
+#define RT5659_JD_MODE_SFT 13
+#define RT5659_EXT_JD_EN (0x1 << 11)
+#define RT5659_EXT_JD_EN_SFT 11
+#define RT5659_EXT_JD_DIG (0x1 << 9)
+
+/* Embeeded Jack and Type Detection Control 2 (0x0011) */
+#define RT5659_EXT_JD_SRC (0x7 << 4)
+#define RT5659_EXT_JD_SRC_SFT 4
+#define RT5659_EXT_JD_SRC_GPIO_JD1 (0x0 << 4)
+#define RT5659_EXT_JD_SRC_GPIO_JD2 (0x1 << 4)
+#define RT5659_EXT_JD_SRC_JD1_1 (0x2 << 4)
+#define RT5659_EXT_JD_SRC_JD1_2 (0x3 << 4)
+#define RT5659_EXT_JD_SRC_JD2 (0x4 << 4)
+#define RT5659_EXT_JD_SRC_JD3 (0x5 << 4)
+#define RT5659_EXT_JD_SRC_MANUAL (0x6 << 4)
+
+/* Slience Detection Control (0x0015) */
+#define RT5659_SIL_DET_MASK (0x1 << 15)
+#define RT5659_SIL_DET_DIS (0x0 << 15)
+#define RT5659_SIL_DET_EN (0x1 << 15)
+
+/* Sidetone Control (0x0018) */
+#define RT5659_ST_SEL_MASK (0x7 << 9)
+#define RT5659_ST_SEL_SFT 9
+#define RT5659_ST_EN (0x1 << 6)
+#define RT5659_ST_EN_SFT 6
+
+/* DAC1 Digital Volume (0x0019) */
+#define RT5659_DAC_L1_VOL_MASK (0xff << 8)
+#define RT5659_DAC_L1_VOL_SFT 8
+#define RT5659_DAC_R1_VOL_MASK (0xff)
+#define RT5659_DAC_R1_VOL_SFT 0
+
+/* DAC2 Digital Volume (0x001a) */
+#define RT5659_DAC_L2_VOL_MASK (0xff << 8)
+#define RT5659_DAC_L2_VOL_SFT 8
+#define RT5659_DAC_R2_VOL_MASK (0xff)
+#define RT5659_DAC_R2_VOL_SFT 0
+
+/* DAC2 Control (0x001b) */
+#define RT5659_M_DAC2_L_VOL (0x1 << 13)
+#define RT5659_M_DAC2_L_VOL_SFT 13
+#define RT5659_M_DAC2_R_VOL (0x1 << 12)
+#define RT5659_M_DAC2_R_VOL_SFT 12
+#define RT5659_DAC_L2_SEL_MASK (0x7 << 4)
+#define RT5659_DAC_L2_SEL_SFT 4
+#define RT5659_DAC_R2_SEL_MASK (0x7 << 0)
+#define RT5659_DAC_R2_SEL_SFT 0
+
+/* ADC Digital Volume Control (0x001c) */
+#define RT5659_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5659_ADC_L_VOL_SFT 8
+#define RT5659_ADC_R_VOL_MASK (0x7f)
+#define RT5659_ADC_R_VOL_SFT 0
+
+/* Mono ADC Digital Volume Control (0x001d) */
+#define RT5659_MONO_ADC_L_VOL_MASK (0x7f << 8)
+#define RT5659_MONO_ADC_L_VOL_SFT 8
+#define RT5659_MONO_ADC_R_VOL_MASK (0x7f)
+#define RT5659_MONO_ADC_R_VOL_SFT 0
+
+/* Stereo1 ADC Boost Gain Control (0x001f) */
+#define RT5659_STO1_ADC_L_BST_MASK (0x3 << 14)
+#define RT5659_STO1_ADC_L_BST_SFT 14
+#define RT5659_STO1_ADC_R_BST_MASK (0x3 << 12)
+#define RT5659_STO1_ADC_R_BST_SFT 12
+
+/* Mono ADC Boost Gain Control (0x0020) */
+#define RT5659_MONO_ADC_L_BST_MASK (0x3 << 14)
+#define RT5659_MONO_ADC_L_BST_SFT 14
+#define RT5659_MONO_ADC_R_BST_MASK (0x3 << 12)
+#define RT5659_MONO_ADC_R_BST_SFT 12
+
+/* Stereo1 ADC Boost Gain Control (0x001f) */
+#define RT5659_STO2_ADC_L_BST_MASK (0x3 << 14)
+#define RT5659_STO2_ADC_L_BST_SFT 14
+#define RT5659_STO2_ADC_R_BST_MASK (0x3 << 12)
+#define RT5659_STO2_ADC_R_BST_SFT 12
+
+/* Stereo ADC Mixer Control (0x0026) */
+#define RT5659_M_STO1_ADC_L1 (0x1 << 15)
+#define RT5659_M_STO1_ADC_L1_SFT 15
+#define RT5659_M_STO1_ADC_L2 (0x1 << 14)
+#define RT5659_M_STO1_ADC_L2_SFT 14
+#define RT5659_STO1_ADC1_SRC_MASK (0x1 << 13)
+#define RT5659_STO1_ADC1_SRC_SFT 13
+#define RT5659_STO1_ADC1_SRC_ADC (0x1 << 13)
+#define RT5659_STO1_ADC1_SRC_DACMIX (0x0 << 13)
+#define RT5659_STO1_ADC_SRC_MASK (0x1 << 12)
+#define RT5659_STO1_ADC_SRC_SFT 12
+#define RT5659_STO1_ADC_SRC_ADC1 (0x1 << 12)
+#define RT5659_STO1_ADC_SRC_ADC2 (0x0 << 12)
+#define RT5659_STO1_ADC2_SRC_MASK (0x1 << 11)
+#define RT5659_STO1_ADC2_SRC_SFT 11
+#define RT5659_STO1_DMIC_SRC_MASK (0x1 << 8)
+#define RT5659_STO1_DMIC_SRC_SFT 8
+#define RT5659_STO1_DMIC_SRC_DMIC2 (0x1 << 8)
+#define RT5659_STO1_DMIC_SRC_DMIC1 (0x0 << 8)
+#define RT5659_M_STO1_ADC_R1 (0x1 << 6)
+#define RT5659_M_STO1_ADC_R1_SFT 6
+#define RT5659_M_STO1_ADC_R2 (0x1 << 5)
+#define RT5659_M_STO1_ADC_R2_SFT 5
+
+/* Mono1 ADC Mixer control (0x0027) */
+#define RT5659_M_MONO_ADC_L1 (0x1 << 15)
+#define RT5659_M_MONO_ADC_L1_SFT 15
+#define RT5659_M_MONO_ADC_L2 (0x1 << 14)
+#define RT5659_M_MONO_ADC_L2_SFT 14
+#define RT5659_MONO_ADC_L2_SRC_MASK (0x1 << 12)
+#define RT5659_MONO_ADC_L2_SRC_SFT 12
+#define RT5659_MONO_ADC_L1_SRC_MASK (0x1 << 11)
+#define RT5659_MONO_ADC_L1_SRC_SFT 11
+#define RT5659_MONO_ADC_L_SRC_MASK (0x3 << 9)
+#define RT5659_MONO_ADC_L_SRC_SFT 9
+#define RT5659_MONO_DMIC_L_SRC_MASK (0x1 << 8)
+#define RT5659_MONO_DMIC_L_SRC_SFT 8
+#define RT5659_M_MONO_ADC_R1 (0x1 << 7)
+#define RT5659_M_MONO_ADC_R1_SFT 7
+#define RT5659_M_MONO_ADC_R2 (0x1 << 6)
+#define RT5659_M_MONO_ADC_R2_SFT 6
+#define RT5659_STO2_ADC_SRC_MASK (0x1 << 5)
+#define RT5659_STO2_ADC_SRC_SFT 5
+#define RT5659_MONO_ADC_R2_SRC_MASK (0x1 << 4)
+#define RT5659_MONO_ADC_R2_SRC_SFT 4
+#define RT5659_MONO_ADC_R1_SRC_MASK (0x1 << 3)
+#define RT5659_MONO_ADC_R1_SRC_SFT 3
+#define RT5659_MONO_ADC_R_SRC_MASK (0x3 << 1)
+#define RT5659_MONO_ADC_R_SRC_SFT 1
+#define RT5659_MONO_DMIC_R_SRC_MASK 0x1
+#define RT5659_MONO_DMIC_R_SRC_SFT 0
+
+/* ADC Mixer to DAC Mixer Control (0x0029) */
+#define RT5659_M_ADCMIX_L (0x1 << 15)
+#define RT5659_M_ADCMIX_L_SFT 15
+#define RT5659_M_DAC1_L (0x1 << 14)
+#define RT5659_M_DAC1_L_SFT 14
+#define RT5659_DAC1_R_SEL_MASK (0x3 << 10)
+#define RT5659_DAC1_R_SEL_SFT 10
+#define RT5659_DAC1_R_SEL_IF1 (0x0 << 10)
+#define RT5659_DAC1_R_SEL_IF2 (0x1 << 10)
+#define RT5659_DAC1_R_SEL_IF3 (0x2 << 10)
+#define RT5659_DAC1_L_SEL_MASK (0x3 << 8)
+#define RT5659_DAC1_L_SEL_SFT 8
+#define RT5659_DAC1_L_SEL_IF1 (0x0 << 8)
+#define RT5659_DAC1_L_SEL_IF2 (0x1 << 8)
+#define RT5659_DAC1_L_SEL_IF3 (0x2 << 8)
+#define RT5659_M_ADCMIX_R (0x1 << 7)
+#define RT5659_M_ADCMIX_R_SFT 7
+#define RT5659_M_DAC1_R (0x1 << 6)
+#define RT5659_M_DAC1_R_SFT 6
+
+/* Stereo DAC Mixer Control (0x002a) */
+#define RT5659_M_DAC_L1_STO_L (0x1 << 15)
+#define RT5659_M_DAC_L1_STO_L_SFT 15
+#define RT5659_G_DAC_L1_STO_L_MASK (0x1 << 14)
+#define RT5659_G_DAC_L1_STO_L_SFT 14
+#define RT5659_M_DAC_R1_STO_L (0x1 << 13)
+#define RT5659_M_DAC_R1_STO_L_SFT 13
+#define RT5659_G_DAC_R1_STO_L_MASK (0x1 << 12)
+#define RT5659_G_DAC_R1_STO_L_SFT 12
+#define RT5659_M_DAC_L2_STO_L (0x1 << 11)
+#define RT5659_M_DAC_L2_STO_L_SFT 11
+#define RT5659_G_DAC_L2_STO_L_MASK (0x1 << 10)
+#define RT5659_G_DAC_L2_STO_L_SFT 10
+#define RT5659_M_DAC_R2_STO_L (0x1 << 9)
+#define RT5659_M_DAC_R2_STO_L_SFT 9
+#define RT5659_G_DAC_R2_STO_L_MASK (0x1 << 8)
+#define RT5659_G_DAC_R2_STO_L_SFT 8
+#define RT5659_M_DAC_L1_STO_R (0x1 << 7)
+#define RT5659_M_DAC_L1_STO_R_SFT 7
+#define RT5659_G_DAC_L1_STO_R_MASK (0x1 << 6)
+#define RT5659_G_DAC_L1_STO_R_SFT 6
+#define RT5659_M_DAC_R1_STO_R (0x1 << 5)
+#define RT5659_M_DAC_R1_STO_R_SFT 5
+#define RT5659_G_DAC_R1_STO_R_MASK (0x1 << 4)
+#define RT5659_G_DAC_R1_STO_R_SFT 4
+#define RT5659_M_DAC_L2_STO_R (0x1 << 3)
+#define RT5659_M_DAC_L2_STO_R_SFT 3
+#define RT5659_G_DAC_L2_STO_R_MASK (0x1 << 2)
+#define RT5659_G_DAC_L2_STO_R_SFT 2
+#define RT5659_M_DAC_R2_STO_R (0x1 << 1)
+#define RT5659_M_DAC_R2_STO_R_SFT 1
+#define RT5659_G_DAC_R2_STO_R_MASK (0x1)
+#define RT5659_G_DAC_R2_STO_R_SFT 0
+
+/* Mono DAC Mixer Control (0x002b) */
+#define RT5659_M_DAC_L1_MONO_L (0x1 << 15)
+#define RT5659_M_DAC_L1_MONO_L_SFT 15
+#define RT5659_G_DAC_L1_MONO_L_MASK (0x1 << 14)
+#define RT5659_G_DAC_L1_MONO_L_SFT 14
+#define RT5659_M_DAC_R1_MONO_L (0x1 << 13)
+#define RT5659_M_DAC_R1_MONO_L_SFT 13
+#define RT5659_G_DAC_R1_MONO_L_MASK (0x1 << 12)
+#define RT5659_G_DAC_R1_MONO_L_SFT 12
+#define RT5659_M_DAC_L2_MONO_L (0x1 << 11)
+#define RT5659_M_DAC_L2_MONO_L_SFT 11
+#define RT5659_G_DAC_L2_MONO_L_MASK (0x1 << 10)
+#define RT5659_G_DAC_L2_MONO_L_SFT 10
+#define RT5659_M_DAC_R2_MONO_L (0x1 << 9)
+#define RT5659_M_DAC_R2_MONO_L_SFT 9
+#define RT5659_G_DAC_R2_MONO_L_MASK (0x1 << 8)
+#define RT5659_G_DAC_R2_MONO_L_SFT 8
+#define RT5659_M_DAC_L1_MONO_R (0x1 << 7)
+#define RT5659_M_DAC_L1_MONO_R_SFT 7
+#define RT5659_G_DAC_L1_MONO_R_MASK (0x1 << 6)
+#define RT5659_G_DAC_L1_MONO_R_SFT 6
+#define RT5659_M_DAC_R1_MONO_R (0x1 << 5)
+#define RT5659_M_DAC_R1_MONO_R_SFT 5
+#define RT5659_G_DAC_R1_MONO_R_MASK (0x1 << 4)
+#define RT5659_G_DAC_R1_MONO_R_SFT 4
+#define RT5659_M_DAC_L2_MONO_R (0x1 << 3)
+#define RT5659_M_DAC_L2_MONO_R_SFT 3
+#define RT5659_G_DAC_L2_MONO_R_MASK (0x1 << 2)
+#define RT5659_G_DAC_L2_MONO_R_SFT 2
+#define RT5659_M_DAC_R2_MONO_R (0x1 << 1)
+#define RT5659_M_DAC_R2_MONO_R_SFT 1
+#define RT5659_G_DAC_R2_MONO_R_MASK (0x1)
+#define RT5659_G_DAC_R2_MONO_R_SFT 0
+
+/* Digital Mixer Control (0x002c) */
+#define RT5659_M_DAC_MIX_L (0x1 << 7)
+#define RT5659_M_DAC_MIX_L_SFT 7
+#define RT5659_DAC_MIX_L_MASK (0x1 << 6)
+#define RT5659_DAC_MIX_L_SFT 6
+#define RT5659_M_DAC_MIX_R (0x1 << 5)
+#define RT5659_M_DAC_MIX_R_SFT 5
+#define RT5659_DAC_MIX_R_MASK (0x1 << 4)
+#define RT5659_DAC_MIX_R_SFT 4
+
+/* Analog DAC Input Source Control (0x002d) */
+#define RT5659_A_DACL1_SEL (0x1 << 3)
+#define RT5659_A_DACL1_SFT 3
+#define RT5659_A_DACR1_SEL (0x1 << 2)
+#define RT5659_A_DACR1_SFT 2
+#define RT5659_A_DACL2_SEL (0x1 << 1)
+#define RT5659_A_DACL2_SFT 1
+#define RT5659_A_DACR2_SEL (0x1 << 0)
+#define RT5659_A_DACR2_SFT 0
+
+/* Digital Interface Data Control (0x002f) */
+#define RT5659_IF2_ADC3_IN_MASK (0x3 << 14)
+#define RT5659_IF2_ADC3_IN_SFT 14
+#define RT5659_IF2_ADC_IN_MASK (0x3 << 12)
+#define RT5659_IF2_ADC_IN_SFT 12
+#define RT5659_IF2_DAC_SEL_MASK (0x3 << 10)
+#define RT5659_IF2_DAC_SEL_SFT 10
+#define RT5659_IF2_ADC_SEL_MASK (0x3 << 8)
+#define RT5659_IF2_ADC_SEL_SFT 8
+#define RT5659_IF3_DAC_SEL_MASK (0x3 << 6)
+#define RT5659_IF3_DAC_SEL_SFT 6
+#define RT5659_IF3_ADC_SEL_MASK (0x3 << 4)
+#define RT5659_IF3_ADC_SEL_SFT 4
+#define RT5659_IF3_ADC_IN_MASK (0x3 << 0)
+#define RT5659_IF3_ADC_IN_SFT 0
+
+/* PDM Output Control (0x0031) */
+#define RT5659_PDM1_L_MASK (0x1 << 15)
+#define RT5659_PDM1_L_SFT 15
+#define RT5659_M_PDM1_L (0x1 << 14)
+#define RT5659_M_PDM1_L_SFT 14
+#define RT5659_PDM1_R_MASK (0x1 << 13)
+#define RT5659_PDM1_R_SFT 13
+#define RT5659_M_PDM1_R (0x1 << 12)
+#define RT5659_M_PDM1_R_SFT 12
+#define RT5659_PDM2_BUSY (0x1 << 7)
+#define RT5659_PDM1_BUSY (0x1 << 6)
+#define RT5659_PDM_PATTERN (0x1 << 5)
+#define RT5659_PDM_GAIN (0x1 << 4)
+#define RT5659_PDM_DIV_MASK (0x3)
+
+/*S/PDIF Output Control (0x0036) */
+#define RT5659_SPDIF_SEL_MASK (0x3 << 0)
+#define RT5659_SPDIF_SEL_SFT 0
+
+/* REC Left Mixer Control 2 (0x003c) */
+#define RT5659_M_BST1_RM1_L (0x1 << 5)
+#define RT5659_M_BST1_RM1_L_SFT 5
+#define RT5659_M_BST2_RM1_L (0x1 << 4)
+#define RT5659_M_BST2_RM1_L_SFT 4
+#define RT5659_M_BST3_RM1_L (0x1 << 3)
+#define RT5659_M_BST3_RM1_L_SFT 3
+#define RT5659_M_BST4_RM1_L (0x1 << 2)
+#define RT5659_M_BST4_RM1_L_SFT 2
+#define RT5659_M_INL_RM1_L (0x1 << 1)
+#define RT5659_M_INL_RM1_L_SFT 1
+#define RT5659_M_SPKVOLL_RM1_L (0x1)
+#define RT5659_M_SPKVOLL_RM1_L_SFT 0
+
+/* REC Right Mixer Control 2 (0x003e) */
+#define RT5659_M_BST1_RM1_R (0x1 << 5)
+#define RT5659_M_BST1_RM1_R_SFT 5
+#define RT5659_M_BST2_RM1_R (0x1 << 4)
+#define RT5659_M_BST2_RM1_R_SFT 4
+#define RT5659_M_BST3_RM1_R (0x1 << 3)
+#define RT5659_M_BST3_RM1_R_SFT 3
+#define RT5659_M_BST4_RM1_R (0x1 << 2)
+#define RT5659_M_BST4_RM1_R_SFT 2
+#define RT5659_M_INR_RM1_R (0x1 << 1)
+#define RT5659_M_INR_RM1_R_SFT 1
+#define RT5659_M_HPOVOLR_RM1_R (0x1)
+#define RT5659_M_HPOVOLR_RM1_R_SFT 0
+
+/* SPK Left Mixer Control (0x0046) */
+#define RT5659_M_BST3_SM_L (0x1 << 4)
+#define RT5659_M_BST3_SM_L_SFT 4
+#define RT5659_M_IN_R_SM_L (0x1 << 3)
+#define RT5659_M_IN_R_SM_L_SFT 3
+#define RT5659_M_IN_L_SM_L (0x1 << 2)
+#define RT5659_M_IN_L_SM_L_SFT 2
+#define RT5659_M_BST1_SM_L (0x1 << 1)
+#define RT5659_M_BST1_SM_L_SFT 1
+#define RT5659_M_DAC_L2_SM_L (0x1)
+#define RT5659_M_DAC_L2_SM_L_SFT 0
+
+/* SPK Right Mixer Control (0x0047) */
+#define RT5659_M_BST3_SM_R (0x1 << 4)
+#define RT5659_M_BST3_SM_R_SFT 4
+#define RT5659_M_IN_R_SM_R (0x1 << 3)
+#define RT5659_M_IN_R_SM_R_SFT 3
+#define RT5659_M_IN_L_SM_R (0x1 << 2)
+#define RT5659_M_IN_L_SM_R_SFT 2
+#define RT5659_M_BST4_SM_R (0x1 << 1)
+#define RT5659_M_BST4_SM_R_SFT 1
+#define RT5659_M_DAC_R2_SM_R (0x1)
+#define RT5659_M_DAC_R2_SM_R_SFT 0
+
+/* SPO Amp Input and Gain Control (0x0048) */
+#define RT5659_M_DAC_L2_SPKOMIX (0x1 << 13)
+#define RT5659_M_DAC_L2_SPKOMIX_SFT 13
+#define RT5659_M_SPKVOLL_SPKOMIX (0x1 << 12)
+#define RT5659_M_SPKVOLL_SPKOMIX_SFT 12
+#define RT5659_M_DAC_R2_SPKOMIX (0x1 << 9)
+#define RT5659_M_DAC_R2_SPKOMIX_SFT 9
+#define RT5659_M_SPKVOLR_SPKOMIX (0x1 << 8)
+#define RT5659_M_SPKVOLR_SPKOMIX_SFT 8
+
+/* MONOMIX Input and Gain Control (0x004b) */
+#define RT5659_M_MONOVOL_MA (0x1 << 9)
+#define RT5659_M_MONOVOL_MA_SFT 9
+#define RT5659_M_DAC_L2_MA (0x1 << 8)
+#define RT5659_M_DAC_L2_MA_SFT 8
+#define RT5659_M_BST3_MM (0x1 << 4)
+#define RT5659_M_BST3_MM_SFT 4
+#define RT5659_M_BST2_MM (0x1 << 3)
+#define RT5659_M_BST2_MM_SFT 3
+#define RT5659_M_BST1_MM (0x1 << 2)
+#define RT5659_M_BST1_MM_SFT 2
+#define RT5659_M_DAC_R2_MM (0x1 << 1)
+#define RT5659_M_DAC_R2_MM_SFT 1
+#define RT5659_M_DAC_L2_MM (0x1)
+#define RT5659_M_DAC_L2_MM_SFT 0
+
+/* Output Left Mixer Control 1 (0x004d) */
+#define RT5659_G_BST3_OM_L_MASK (0x7 << 12)
+#define RT5659_G_BST3_OM_L_SFT 12
+#define RT5659_G_BST2_OM_L_MASK (0x7 << 9)
+#define RT5659_G_BST2_OM_L_SFT 9
+#define RT5659_G_BST1_OM_L_MASK (0x7 << 6)
+#define RT5659_G_BST1_OM_L_SFT 6
+#define RT5659_G_IN_L_OM_L_MASK (0x7 << 3)
+#define RT5659_G_IN_L_OM_L_SFT 3
+#define RT5659_G_DAC_L2_OM_L_MASK (0x7 << 0)
+#define RT5659_G_DAC_L2_OM_L_SFT 0
+
+/* Output Left Mixer Input Control (0x004e) */
+#define RT5659_M_BST3_OM_L (0x1 << 4)
+#define RT5659_M_BST3_OM_L_SFT 4
+#define RT5659_M_BST2_OM_L (0x1 << 3)
+#define RT5659_M_BST2_OM_L_SFT 3
+#define RT5659_M_BST1_OM_L (0x1 << 2)
+#define RT5659_M_BST1_OM_L_SFT 2
+#define RT5659_M_IN_L_OM_L (0x1 << 1)
+#define RT5659_M_IN_L_OM_L_SFT 1
+#define RT5659_M_DAC_L2_OM_L (0x1)
+#define RT5659_M_DAC_L2_OM_L_SFT 0
+
+/* Output Right Mixer Input Control (0x0050) */
+#define RT5659_M_BST4_OM_R (0x1 << 4)
+#define RT5659_M_BST4_OM_R_SFT 4
+#define RT5659_M_BST3_OM_R (0x1 << 3)
+#define RT5659_M_BST3_OM_R_SFT 3
+#define RT5659_M_BST2_OM_R (0x1 << 2)
+#define RT5659_M_BST2_OM_R_SFT 2
+#define RT5659_M_IN_R_OM_R (0x1 << 1)
+#define RT5659_M_IN_R_OM_R_SFT 1
+#define RT5659_M_DAC_R2_OM_R (0x1)
+#define RT5659_M_DAC_R2_OM_R_SFT 0
+
+/* LOUT Mixer Control (0x0052) */
+#define RT5659_M_DAC_L2_LM (0x1 << 15)
+#define RT5659_M_DAC_L2_LM_SFT 15
+#define RT5659_M_DAC_R2_LM (0x1 << 14)
+#define RT5659_M_DAC_R2_LM_SFT 14
+#define RT5659_M_OV_L_LM (0x1 << 13)
+#define RT5659_M_OV_L_LM_SFT 13
+#define RT5659_M_OV_R_LM (0x1 << 12)
+#define RT5659_M_OV_R_LM_SFT 12
+
+/* Power Management for Digital 1 (0x0061) */
+#define RT5659_PWR_I2S1 (0x1 << 15)
+#define RT5659_PWR_I2S1_BIT 15
+#define RT5659_PWR_I2S2 (0x1 << 14)
+#define RT5659_PWR_I2S2_BIT 14
+#define RT5659_PWR_I2S3 (0x1 << 13)
+#define RT5659_PWR_I2S3_BIT 13
+#define RT5659_PWR_SPDIF (0x1 << 12)
+#define RT5659_PWR_SPDIF_BIT 12
+#define RT5659_PWR_DAC_L1 (0x1 << 11)
+#define RT5659_PWR_DAC_L1_BIT 11
+#define RT5659_PWR_DAC_R1 (0x1 << 10)
+#define RT5659_PWR_DAC_R1_BIT 10
+#define RT5659_PWR_DAC_L2 (0x1 << 9)
+#define RT5659_PWR_DAC_L2_BIT 9
+#define RT5659_PWR_DAC_R2 (0x1 << 8)
+#define RT5659_PWR_DAC_R2_BIT 8
+#define RT5659_PWR_LDO (0x1 << 7)
+#define RT5659_PWR_LDO_BIT 7
+#define RT5659_PWR_ADC_L1 (0x1 << 4)
+#define RT5659_PWR_ADC_L1_BIT 4
+#define RT5659_PWR_ADC_R1 (0x1 << 3)
+#define RT5659_PWR_ADC_R1_BIT 3
+#define RT5659_PWR_ADC_L2 (0x1 << 2)
+#define RT5659_PWR_ADC_L2_BIT 4
+#define RT5659_PWR_ADC_R2 (0x1 << 1)
+#define RT5659_PWR_ADC_R2_BIT 1
+#define RT5659_PWR_CLS_D (0x1)
+#define RT5659_PWR_CLS_D_BIT 0
+
+/* Power Management for Digital 2 (0x0062) */
+#define RT5659_PWR_ADC_S1F (0x1 << 15)
+#define RT5659_PWR_ADC_S1F_BIT 15
+#define RT5659_PWR_ADC_S2F (0x1 << 14)
+#define RT5659_PWR_ADC_S2F_BIT 14
+#define RT5659_PWR_ADC_MF_L (0x1 << 13)
+#define RT5659_PWR_ADC_MF_L_BIT 13
+#define RT5659_PWR_ADC_MF_R (0x1 << 12)
+#define RT5659_PWR_ADC_MF_R_BIT 12
+#define RT5659_PWR_DAC_S1F (0x1 << 10)
+#define RT5659_PWR_DAC_S1F_BIT 10
+#define RT5659_PWR_DAC_MF_L (0x1 << 9)
+#define RT5659_PWR_DAC_MF_L_BIT 9
+#define RT5659_PWR_DAC_MF_R (0x1 << 8)
+#define RT5659_PWR_DAC_MF_R_BIT 8
+#define RT5659_PWR_PDM1 (0x1 << 7)
+#define RT5659_PWR_PDM1_BIT 7
+
+/* Power Management for Analog 1 (0x0063) */
+#define RT5659_PWR_VREF1 (0x1 << 15)
+#define RT5659_PWR_VREF1_BIT 15
+#define RT5659_PWR_FV1 (0x1 << 14)
+#define RT5659_PWR_FV1_BIT 14
+#define RT5659_PWR_VREF2 (0x1 << 13)
+#define RT5659_PWR_VREF2_BIT 13
+#define RT5659_PWR_FV2 (0x1 << 12)
+#define RT5659_PWR_FV2_BIT 12
+#define RT5659_PWR_VREF3 (0x1 << 11)
+#define RT5659_PWR_VREF3_BIT 11
+#define RT5659_PWR_FV3 (0x1 << 10)
+#define RT5659_PWR_FV3_BIT 10
+#define RT5659_PWR_MB (0x1 << 9)
+#define RT5659_PWR_MB_BIT 9
+#define RT5659_PWR_LM (0x1 << 8)
+#define RT5659_PWR_LM_BIT 8
+#define RT5659_PWR_BG (0x1 << 7)
+#define RT5659_PWR_BG_BIT 7
+#define RT5659_PWR_MA (0x1 << 6)
+#define RT5659_PWR_MA_BIT 6
+#define RT5659_PWR_HA_L (0x1 << 5)
+#define RT5659_PWR_HA_L_BIT 5
+#define RT5659_PWR_HA_R (0x1 << 4)
+#define RT5659_PWR_HA_R_BIT 4
+
+/* Power Management for Analog 2 (0x0064) */
+#define RT5659_PWR_BST1 (0x1 << 15)
+#define RT5659_PWR_BST1_BIT 15
+#define RT5659_PWR_BST2 (0x1 << 14)
+#define RT5659_PWR_BST2_BIT 14
+#define RT5659_PWR_BST3 (0x1 << 13)
+#define RT5659_PWR_BST3_BIT 13
+#define RT5659_PWR_BST4 (0x1 << 12)
+#define RT5659_PWR_BST4_BIT 12
+#define RT5659_PWR_MB1 (0x1 << 11)
+#define RT5659_PWR_MB1_BIT 11
+#define RT5659_PWR_MB2 (0x1 << 10)
+#define RT5659_PWR_MB2_BIT 10
+#define RT5659_PWR_MB3 (0x1 << 9)
+#define RT5659_PWR_MB3_BIT 9
+#define RT5659_PWR_BST1_P (0x1 << 6)
+#define RT5659_PWR_BST1_P_BIT 6
+#define RT5659_PWR_BST2_P (0x1 << 5)
+#define RT5659_PWR_BST2_P_BIT 5
+#define RT5659_PWR_BST3_P (0x1 << 4)
+#define RT5659_PWR_BST3_P_BIT 4
+#define RT5659_PWR_BST4_P (0x1 << 3)
+#define RT5659_PWR_BST4_P_BIT 3
+#define RT5659_PWR_JD1 (0x1 << 2)
+#define RT5659_PWR_JD1_BIT 2
+#define RT5659_PWR_JD2 (0x1 << 1)
+#define RT5659_PWR_JD2_BIT 1
+#define RT5659_PWR_JD3 (0x1)
+#define RT5659_PWR_JD3_BIT 0
+
+/* Power Management for Analog 3 (0x0065) */
+#define RT5659_PWR_BST_L (0x1 << 8)
+#define RT5659_PWR_BST_L_BIT 8
+#define RT5659_PWR_BST_R (0x1 << 7)
+#define RT5659_PWR_BST_R_BIT 7
+#define RT5659_PWR_PLL (0x1 << 6)
+#define RT5659_PWR_PLL_BIT 6
+#define RT5659_PWR_LDO5 (0x1 << 5)
+#define RT5659_PWR_LDO5_BIT 5
+#define RT5659_PWR_LDO4 (0x1 << 4)
+#define RT5659_PWR_LDO4_BIT 4
+#define RT5659_PWR_LDO3 (0x1 << 3)
+#define RT5659_PWR_LDO3_BIT 3
+#define RT5659_PWR_LDO2 (0x1 << 2)
+#define RT5659_PWR_LDO2_BIT 2
+#define RT5659_PWR_SVD (0x1 << 1)
+#define RT5659_PWR_SVD_BIT 1
+
+/* Power Management for Mixer (0x0066) */
+#define RT5659_PWR_OM_L (0x1 << 15)
+#define RT5659_PWR_OM_L_BIT 15
+#define RT5659_PWR_OM_R (0x1 << 14)
+#define RT5659_PWR_OM_R_BIT 14
+#define RT5659_PWR_SM_L (0x1 << 13)
+#define RT5659_PWR_SM_L_BIT 13
+#define RT5659_PWR_SM_R (0x1 << 12)
+#define RT5659_PWR_SM_R_BIT 12
+#define RT5659_PWR_RM1_L (0x1 << 11)
+#define RT5659_PWR_RM1_L_BIT 11
+#define RT5659_PWR_RM1_R (0x1 << 10)
+#define RT5659_PWR_RM1_R_BIT 10
+#define RT5659_PWR_MM (0x1 << 8)
+#define RT5659_PWR_MM_BIT 8
+#define RT5659_PWR_RM2_L (0x1 << 3)
+#define RT5659_PWR_RM2_L_BIT 3
+#define RT5659_PWR_RM2_R (0x1 << 2)
+#define RT5659_PWR_RM2_R_BIT 2
+
+/* Power Management for Volume (0x0067) */
+#define RT5659_PWR_SV_L (0x1 << 15)
+#define RT5659_PWR_SV_L_BIT 15
+#define RT5659_PWR_SV_R (0x1 << 14)
+#define RT5659_PWR_SV_R_BIT 14
+#define RT5659_PWR_OV_L (0x1 << 13)
+#define RT5659_PWR_OV_L_BIT 13
+#define RT5659_PWR_OV_R (0x1 << 12)
+#define RT5659_PWR_OV_R_BIT 12
+#define RT5659_PWR_IN_L (0x1 << 9)
+#define RT5659_PWR_IN_L_BIT 9
+#define RT5659_PWR_IN_R (0x1 << 8)
+#define RT5659_PWR_IN_R_BIT 8
+#define RT5659_PWR_MV (0x1 << 7)
+#define RT5659_PWR_MV_BIT 7
+#define RT5659_PWR_MIC_DET (0x1 << 5)
+#define RT5659_PWR_MIC_DET_BIT 5
+
+/* I2S1/2/3 Audio Serial Data Port Control (0x0070 0x0071 0x0072) */
+#define RT5659_I2S_MS_MASK (0x1 << 15)
+#define RT5659_I2S_MS_SFT 15
+#define RT5659_I2S_MS_M (0x0 << 15)
+#define RT5659_I2S_MS_S (0x1 << 15)
+#define RT5659_I2S_O_CP_MASK (0x3 << 12)
+#define RT5659_I2S_O_CP_SFT 12
+#define RT5659_I2S_O_CP_OFF (0x0 << 12)
+#define RT5659_I2S_O_CP_U_LAW (0x1 << 12)
+#define RT5659_I2S_O_CP_A_LAW (0x2 << 12)
+#define RT5659_I2S_I_CP_MASK (0x3 << 10)
+#define RT5659_I2S_I_CP_SFT 10
+#define RT5659_I2S_I_CP_OFF (0x0 << 10)
+#define RT5659_I2S_I_CP_U_LAW (0x1 << 10)
+#define RT5659_I2S_I_CP_A_LAW (0x2 << 10)
+#define RT5659_I2S_BP_MASK (0x1 << 8)
+#define RT5659_I2S_BP_SFT 8
+#define RT5659_I2S_BP_NOR (0x0 << 8)
+#define RT5659_I2S_BP_INV (0x1 << 8)
+#define RT5659_I2S_DL_MASK (0x3 << 4)
+#define RT5659_I2S_DL_SFT 4
+#define RT5659_I2S_DL_16 (0x0 << 4)
+#define RT5659_I2S_DL_20 (0x1 << 4)
+#define RT5659_I2S_DL_24 (0x2 << 4)
+#define RT5659_I2S_DL_8 (0x3 << 4)
+#define RT5659_I2S_DF_MASK (0x7)
+#define RT5659_I2S_DF_SFT 0
+#define RT5659_I2S_DF_I2S (0x0)
+#define RT5659_I2S_DF_LEFT (0x1)
+#define RT5659_I2S_DF_PCM_A (0x2)
+#define RT5659_I2S_DF_PCM_B (0x3)
+#define RT5659_I2S_DF_PCM_A_N (0x6)
+#define RT5659_I2S_DF_PCM_B_N (0x7)
+
+/* ADC/DAC Clock Control 1 (0x0073) */
+#define RT5659_I2S_PD1_MASK (0x7 << 12)
+#define RT5659_I2S_PD1_SFT 12
+#define RT5659_I2S_PD1_1 (0x0 << 12)
+#define RT5659_I2S_PD1_2 (0x1 << 12)
+#define RT5659_I2S_PD1_3 (0x2 << 12)
+#define RT5659_I2S_PD1_4 (0x3 << 12)
+#define RT5659_I2S_PD1_6 (0x4 << 12)
+#define RT5659_I2S_PD1_8 (0x5 << 12)
+#define RT5659_I2S_PD1_12 (0x6 << 12)
+#define RT5659_I2S_PD1_16 (0x7 << 12)
+#define RT5659_I2S_BCLK_MS2_MASK (0x1 << 11)
+#define RT5659_I2S_BCLK_MS2_SFT 11
+#define RT5659_I2S_BCLK_MS2_32 (0x0 << 11)
+#define RT5659_I2S_BCLK_MS2_64 (0x1 << 11)
+#define RT5659_I2S_PD2_MASK (0x7 << 8)
+#define RT5659_I2S_PD2_SFT 8
+#define RT5659_I2S_PD2_1 (0x0 << 8)
+#define RT5659_I2S_PD2_2 (0x1 << 8)
+#define RT5659_I2S_PD2_3 (0x2 << 8)
+#define RT5659_I2S_PD2_4 (0x3 << 8)
+#define RT5659_I2S_PD2_6 (0x4 << 8)
+#define RT5659_I2S_PD2_8 (0x5 << 8)
+#define RT5659_I2S_PD2_12 (0x6 << 8)
+#define RT5659_I2S_PD2_16 (0x7 << 8)
+#define RT5659_I2S_BCLK_MS3_MASK (0x1 << 7)
+#define RT5659_I2S_BCLK_MS3_SFT 7
+#define RT5659_I2S_BCLK_MS3_32 (0x0 << 7)
+#define RT5659_I2S_BCLK_MS3_64 (0x1 << 7)
+#define RT5659_I2S_PD3_MASK (0x7 << 4)
+#define RT5659_I2S_PD3_SFT 4
+#define RT5659_I2S_PD3_1 (0x0 << 4)
+#define RT5659_I2S_PD3_2 (0x1 << 4)
+#define RT5659_I2S_PD3_3 (0x2 << 4)
+#define RT5659_I2S_PD3_4 (0x3 << 4)
+#define RT5659_I2S_PD3_6 (0x4 << 4)
+#define RT5659_I2S_PD3_8 (0x5 << 4)
+#define RT5659_I2S_PD3_12 (0x6 << 4)
+#define RT5659_I2S_PD3_16 (0x7 << 4)
+#define RT5659_DAC_OSR_MASK (0x3 << 2)
+#define RT5659_DAC_OSR_SFT 2
+#define RT5659_DAC_OSR_128 (0x0 << 2)
+#define RT5659_DAC_OSR_64 (0x1 << 2)
+#define RT5659_DAC_OSR_32 (0x2 << 2)
+#define RT5659_DAC_OSR_16 (0x3 << 2)
+#define RT5659_ADC_OSR_MASK (0x3)
+#define RT5659_ADC_OSR_SFT 0
+#define RT5659_ADC_OSR_128 (0x0)
+#define RT5659_ADC_OSR_64 (0x1)
+#define RT5659_ADC_OSR_32 (0x2)
+#define RT5659_ADC_OSR_16 (0x3)
+
+/* Digital Microphone Control (0x0075) */
+#define RT5659_DMIC_1_EN_MASK (0x1 << 15)
+#define RT5659_DMIC_1_EN_SFT 15
+#define RT5659_DMIC_1_DIS (0x0 << 15)
+#define RT5659_DMIC_1_EN (0x1 << 15)
+#define RT5659_DMIC_2_EN_MASK (0x1 << 14)
+#define RT5659_DMIC_2_EN_SFT 14
+#define RT5659_DMIC_2_DIS (0x0 << 14)
+#define RT5659_DMIC_2_EN (0x1 << 14)
+#define RT5659_DMIC_1L_LH_MASK (0x1 << 13)
+#define RT5659_DMIC_1L_LH_SFT 13
+#define RT5659_DMIC_1L_LH_RISING (0x0 << 13)
+#define RT5659_DMIC_1L_LH_FALLING (0x1 << 13)
+#define RT5659_DMIC_1R_LH_MASK (0x1 << 12)
+#define RT5659_DMIC_1R_LH_SFT 12
+#define RT5659_DMIC_1R_LH_RISING (0x0 << 12)
+#define RT5659_DMIC_1R_LH_FALLING (0x1 << 12)
+#define RT5659_DMIC_2_DP_MASK (0x3 << 10)
+#define RT5659_DMIC_2_DP_SFT 10
+#define RT5659_DMIC_2_DP_GPIO6 (0x0 << 10)
+#define RT5659_DMIC_2_DP_GPIO10 (0x1 << 10)
+#define RT5659_DMIC_2_DP_GPIO12 (0x2 << 10)
+#define RT5659_DMIC_2_DP_IN2P (0x3 << 10)
+#define RT5659_DMIC_CLK_MASK (0x7 << 5)
+#define RT5659_DMIC_CLK_SFT 5
+#define RT5659_DMIC_1_DP_MASK (0x3 << 0)
+#define RT5659_DMIC_1_DP_SFT 0
+#define RT5659_DMIC_1_DP_GPIO5 (0x0 << 0)
+#define RT5659_DMIC_1_DP_GPIO9 (0x1 << 0)
+#define RT5659_DMIC_1_DP_GPIO11 (0x2 << 0)
+#define RT5659_DMIC_1_DP_IN2N (0x3 << 0)
+
+/* TDM control 1 (0x0078)*/
+#define RT5659_DS_ADC_SLOT01_SFT 14
+#define RT5659_DS_ADC_SLOT23_SFT 12
+#define RT5659_DS_ADC_SLOT45_SFT 10
+#define RT5659_DS_ADC_SLOT67_SFT 8
+#define RT5659_ADCDAT_SRC_MASK 0x1f
+#define RT5659_ADCDAT_SRC_SFT 0
+
+/* Global Clock Control (0x0080) */
+#define RT5659_SCLK_SRC_MASK (0x3 << 14)
+#define RT5659_SCLK_SRC_SFT 14
+#define RT5659_SCLK_SRC_MCLK (0x0 << 14)
+#define RT5659_SCLK_SRC_PLL1 (0x1 << 14)
+#define RT5659_SCLK_SRC_RCCLK (0x2 << 14)
+#define RT5659_PLL1_SRC_MASK (0x7 << 11)
+#define RT5659_PLL1_SRC_SFT 11
+#define RT5659_PLL1_SRC_MCLK (0x0 << 11)
+#define RT5659_PLL1_SRC_BCLK1 (0x1 << 11)
+#define RT5659_PLL1_SRC_BCLK2 (0x2 << 11)
+#define RT5659_PLL1_SRC_BCLK3 (0x3 << 11)
+#define RT5659_PLL1_PD_MASK (0x1 << 3)
+#define RT5659_PLL1_PD_SFT 3
+#define RT5659_PLL1_PD_1 (0x0 << 3)
+#define RT5659_PLL1_PD_2 (0x1 << 3)
+
+#define RT5659_PLL_INP_MAX 40000000
+#define RT5659_PLL_INP_MIN 256000
+/* PLL M/N/K Code Control 1 (0x0081) */
+#define RT5659_PLL_N_MAX 0x001ff
+#define RT5659_PLL_N_MASK (RT5659_PLL_N_MAX << 7)
+#define RT5659_PLL_N_SFT 7
+#define RT5659_PLL_K_MAX 0x001f
+#define RT5659_PLL_K_MASK (RT5659_PLL_K_MAX)
+#define RT5659_PLL_K_SFT 0
+
+/* PLL M/N/K Code Control 2 (0x0082) */
+#define RT5659_PLL_M_MAX 0x00f
+#define RT5659_PLL_M_MASK (RT5659_PLL_M_MAX << 12)
+#define RT5659_PLL_M_SFT 12
+#define RT5659_PLL_M_BP (0x1 << 11)
+#define RT5659_PLL_M_BP_SFT 11
+
+/* PLL tracking mode 1 (0x0083) */
+#define RT5659_I2S3_ASRC_MASK (0x1 << 13)
+#define RT5659_I2S3_ASRC_SFT 13
+#define RT5659_I2S2_ASRC_MASK (0x1 << 12)
+#define RT5659_I2S2_ASRC_SFT 12
+#define RT5659_I2S1_ASRC_MASK (0x1 << 11)
+#define RT5659_I2S1_ASRC_SFT 11
+#define RT5659_DAC_STO_ASRC_MASK (0x1 << 10)
+#define RT5659_DAC_STO_ASRC_SFT 10
+#define RT5659_DAC_MONO_L_ASRC_MASK (0x1 << 9)
+#define RT5659_DAC_MONO_L_ASRC_SFT 9
+#define RT5659_DAC_MONO_R_ASRC_MASK (0x1 << 8)
+#define RT5659_DAC_MONO_R_ASRC_SFT 8
+#define RT5659_DMIC_STO1_ASRC_MASK (0x1 << 7)
+#define RT5659_DMIC_STO1_ASRC_SFT 7
+#define RT5659_DMIC_MONO_L_ASRC_MASK (0x1 << 5)
+#define RT5659_DMIC_MONO_L_ASRC_SFT 5
+#define RT5659_DMIC_MONO_R_ASRC_MASK (0x1 << 4)
+#define RT5659_DMIC_MONO_R_ASRC_SFT 4
+#define RT5659_ADC_STO1_ASRC_MASK (0x1 << 3)
+#define RT5659_ADC_STO1_ASRC_SFT 3
+#define RT5659_ADC_MONO_L_ASRC_MASK (0x1 << 1)
+#define RT5659_ADC_MONO_L_ASRC_SFT 1
+#define RT5659_ADC_MONO_R_ASRC_MASK (0x1)
+#define RT5659_ADC_MONO_R_ASRC_SFT 0
+
+/* PLL tracking mode 2 (0x0084)*/
+#define RT5659_DA_STO_T_MASK (0x7 << 12)
+#define RT5659_DA_STO_T_SFT 12
+#define RT5659_DA_MONO_L_T_MASK (0x7 << 8)
+#define RT5659_DA_MONO_L_T_SFT 8
+#define RT5659_DA_MONO_R_T_MASK (0x7 << 4)
+#define RT5659_DA_MONO_R_T_SFT 4
+#define RT5659_AD_STO1_T_MASK (0x7)
+#define RT5659_AD_STO1_T_SFT 0
+
+/* PLL tracking mode 3 (0x0085)*/
+#define RT5659_AD_STO2_T_MASK (0x7 << 8)
+#define RT5659_AD_STO2_T_SFT 8
+#define RT5659_AD_MONO_L_T_MASK (0x7 << 4)
+#define RT5659_AD_MONO_L_T_SFT 4
+#define RT5659_AD_MONO_R_T_MASK (0x7)
+#define RT5659_AD_MONO_R_T_SFT 0
+
+/* ASRC Control 4 (0x0086) */
+#define RT5659_I2S1_RATE_MASK (0xf << 12)
+#define RT5659_I2S1_RATE_SFT 12
+#define RT5659_I2S2_RATE_MASK (0xf << 8)
+#define RT5659_I2S2_RATE_SFT 8
+#define RT5659_I2S3_RATE_MASK (0xf << 4)
+#define RT5659_I2S3_RATE_SFT 4
+
+/* Depop Mode Control 1 (0x8e) */
+#define RT5659_SMT_TRIG_MASK (0x1 << 15)
+#define RT5659_SMT_TRIG_SFT 15
+#define RT5659_SMT_TRIG_DIS (0x0 << 15)
+#define RT5659_SMT_TRIG_EN (0x1 << 15)
+#define RT5659_HP_L_SMT_MASK (0x1 << 9)
+#define RT5659_HP_L_SMT_SFT 9
+#define RT5659_HP_L_SMT_DIS (0x0 << 9)
+#define RT5659_HP_L_SMT_EN (0x1 << 9)
+#define RT5659_HP_R_SMT_MASK (0x1 << 8)
+#define RT5659_HP_R_SMT_SFT 8
+#define RT5659_HP_R_SMT_DIS (0x0 << 8)
+#define RT5659_HP_R_SMT_EN (0x1 << 8)
+#define RT5659_HP_CD_PD_MASK (0x1 << 7)
+#define RT5659_HP_CD_PD_SFT 7
+#define RT5659_HP_CD_PD_DIS (0x0 << 7)
+#define RT5659_HP_CD_PD_EN (0x1 << 7)
+#define RT5659_RSTN_MASK (0x1 << 6)
+#define RT5659_RSTN_SFT 6
+#define RT5659_RSTN_DIS (0x0 << 6)
+#define RT5659_RSTN_EN (0x1 << 6)
+#define RT5659_RSTP_MASK (0x1 << 5)
+#define RT5659_RSTP_SFT 5
+#define RT5659_RSTP_DIS (0x0 << 5)
+#define RT5659_RSTP_EN (0x1 << 5)
+#define RT5659_HP_CO_MASK (0x1 << 4)
+#define RT5659_HP_CO_SFT 4
+#define RT5659_HP_CO_DIS (0x0 << 4)
+#define RT5659_HP_CO_EN (0x1 << 4)
+#define RT5659_HP_CP_MASK (0x1 << 3)
+#define RT5659_HP_CP_SFT 3
+#define RT5659_HP_CP_PD (0x0 << 3)
+#define RT5659_HP_CP_PU (0x1 << 3)
+#define RT5659_HP_SG_MASK (0x1 << 2)
+#define RT5659_HP_SG_SFT 2
+#define RT5659_HP_SG_DIS (0x0 << 2)
+#define RT5659_HP_SG_EN (0x1 << 2)
+#define RT5659_HP_DP_MASK (0x1 << 1)
+#define RT5659_HP_DP_SFT 1
+#define RT5659_HP_DP_PD (0x0 << 1)
+#define RT5659_HP_DP_PU (0x1 << 1)
+#define RT5659_HP_CB_MASK (0x1)
+#define RT5659_HP_CB_SFT 0
+#define RT5659_HP_CB_PD (0x0)
+#define RT5659_HP_CB_PU (0x1)
+
+/* Depop Mode Control 2 (0x8f) */
+#define RT5659_DEPOP_MASK (0x1 << 13)
+#define RT5659_DEPOP_SFT 13
+#define RT5659_DEPOP_AUTO (0x0 << 13)
+#define RT5659_DEPOP_MAN (0x1 << 13)
+#define RT5659_RAMP_MASK (0x1 << 12)
+#define RT5659_RAMP_SFT 12
+#define RT5659_RAMP_DIS (0x0 << 12)
+#define RT5659_RAMP_EN (0x1 << 12)
+#define RT5659_BPS_MASK (0x1 << 11)
+#define RT5659_BPS_SFT 11
+#define RT5659_BPS_DIS (0x0 << 11)
+#define RT5659_BPS_EN (0x1 << 11)
+#define RT5659_FAST_UPDN_MASK (0x1 << 10)
+#define RT5659_FAST_UPDN_SFT 10
+#define RT5659_FAST_UPDN_DIS (0x0 << 10)
+#define RT5659_FAST_UPDN_EN (0x1 << 10)
+#define RT5659_MRES_MASK (0x3 << 8)
+#define RT5659_MRES_SFT 8
+#define RT5659_MRES_15MO (0x0 << 8)
+#define RT5659_MRES_25MO (0x1 << 8)
+#define RT5659_MRES_35MO (0x2 << 8)
+#define RT5659_MRES_45MO (0x3 << 8)
+#define RT5659_VLO_MASK (0x1 << 7)
+#define RT5659_VLO_SFT 7
+#define RT5659_VLO_3V (0x0 << 7)
+#define RT5659_VLO_32V (0x1 << 7)
+#define RT5659_DIG_DP_MASK (0x1 << 6)
+#define RT5659_DIG_DP_SFT 6
+#define RT5659_DIG_DP_DIS (0x0 << 6)
+#define RT5659_DIG_DP_EN (0x1 << 6)
+#define RT5659_DP_TH_MASK (0x3 << 4)
+#define RT5659_DP_TH_SFT 4
+
+/* Depop Mode Control 3 (0x90) */
+#define RT5659_CP_SYS_MASK (0x7 << 12)
+#define RT5659_CP_SYS_SFT 12
+#define RT5659_CP_FQ1_MASK (0x7 << 8)
+#define RT5659_CP_FQ1_SFT 8
+#define RT5659_CP_FQ2_MASK (0x7 << 4)
+#define RT5659_CP_FQ2_SFT 4
+#define RT5659_CP_FQ3_MASK (0x7)
+#define RT5659_CP_FQ3_SFT 0
+#define RT5659_CP_FQ_1_5_KHZ 0
+#define RT5659_CP_FQ_3_KHZ 1
+#define RT5659_CP_FQ_6_KHZ 2
+#define RT5659_CP_FQ_12_KHZ 3
+#define RT5659_CP_FQ_24_KHZ 4
+#define RT5659_CP_FQ_48_KHZ 5
+#define RT5659_CP_FQ_96_KHZ 6
+#define RT5659_CP_FQ_192_KHZ 7
+
+/* HPOUT charge pump 1 (0x0091) */
+#define RT5659_OSW_L_MASK (0x1 << 11)
+#define RT5659_OSW_L_SFT 11
+#define RT5659_OSW_L_DIS (0x0 << 11)
+#define RT5659_OSW_L_EN (0x1 << 11)
+#define RT5659_OSW_R_MASK (0x1 << 10)
+#define RT5659_OSW_R_SFT 10
+#define RT5659_OSW_R_DIS (0x0 << 10)
+#define RT5659_OSW_R_EN (0x1 << 10)
+#define RT5659_PM_HP_MASK (0x3 << 8)
+#define RT5659_PM_HP_SFT 8
+#define RT5659_PM_HP_LV (0x0 << 8)
+#define RT5659_PM_HP_MV (0x1 << 8)
+#define RT5659_PM_HP_HV (0x2 << 8)
+#define RT5659_IB_HP_MASK (0x3 << 6)
+#define RT5659_IB_HP_SFT 6
+#define RT5659_IB_HP_125IL (0x0 << 6)
+#define RT5659_IB_HP_25IL (0x1 << 6)
+#define RT5659_IB_HP_5IL (0x2 << 6)
+#define RT5659_IB_HP_1IL (0x3 << 6)
+
+/* PV detection and SPK gain control (0x92) */
+#define RT5659_PVDD_DET_MASK (0x1 << 15)
+#define RT5659_PVDD_DET_SFT 15
+#define RT5659_PVDD_DET_DIS (0x0 << 15)
+#define RT5659_PVDD_DET_EN (0x1 << 15)
+#define RT5659_SPK_AG_MASK (0x1 << 14)
+#define RT5659_SPK_AG_SFT 14
+#define RT5659_SPK_AG_DIS (0x0 << 14)
+#define RT5659_SPK_AG_EN (0x1 << 14)
+
+/* Micbias Control (0x93) */
+#define RT5659_MIC1_BS_MASK (0x1 << 15)
+#define RT5659_MIC1_BS_SFT 15
+#define RT5659_MIC1_BS_9AV (0x0 << 15)
+#define RT5659_MIC1_BS_75AV (0x1 << 15)
+#define RT5659_MIC2_BS_MASK (0x1 << 14)
+#define RT5659_MIC2_BS_SFT 14
+#define RT5659_MIC2_BS_9AV (0x0 << 14)
+#define RT5659_MIC2_BS_75AV (0x1 << 14)
+#define RT5659_MIC1_CLK_MASK (0x1 << 13)
+#define RT5659_MIC1_CLK_SFT 13
+#define RT5659_MIC1_CLK_DIS (0x0 << 13)
+#define RT5659_MIC1_CLK_EN (0x1 << 13)
+#define RT5659_MIC2_CLK_MASK (0x1 << 12)
+#define RT5659_MIC2_CLK_SFT 12
+#define RT5659_MIC2_CLK_DIS (0x0 << 12)
+#define RT5659_MIC2_CLK_EN (0x1 << 12)
+#define RT5659_MIC1_OVCD_MASK (0x1 << 11)
+#define RT5659_MIC1_OVCD_SFT 11
+#define RT5659_MIC1_OVCD_DIS (0x0 << 11)
+#define RT5659_MIC1_OVCD_EN (0x1 << 11)
+#define RT5659_MIC1_OVTH_MASK (0x3 << 9)
+#define RT5659_MIC1_OVTH_SFT 9
+#define RT5659_MIC1_OVTH_600UA (0x0 << 9)
+#define RT5659_MIC1_OVTH_1500UA (0x1 << 9)
+#define RT5659_MIC1_OVTH_2000UA (0x2 << 9)
+#define RT5659_MIC2_OVCD_MASK (0x1 << 8)
+#define RT5659_MIC2_OVCD_SFT 8
+#define RT5659_MIC2_OVCD_DIS (0x0 << 8)
+#define RT5659_MIC2_OVCD_EN (0x1 << 8)
+#define RT5659_MIC2_OVTH_MASK (0x3 << 6)
+#define RT5659_MIC2_OVTH_SFT 6
+#define RT5659_MIC2_OVTH_600UA (0x0 << 6)
+#define RT5659_MIC2_OVTH_1500UA (0x1 << 6)
+#define RT5659_MIC2_OVTH_2000UA (0x2 << 6)
+#define RT5659_PWR_MB_MASK (0x1 << 5)
+#define RT5659_PWR_MB_SFT 5
+#define RT5659_PWR_MB_PD (0x0 << 5)
+#define RT5659_PWR_MB_PU (0x1 << 5)
+#define RT5659_PWR_CLK25M_MASK (0x1 << 4)
+#define RT5659_PWR_CLK25M_SFT 4
+#define RT5659_PWR_CLK25M_PD (0x0 << 4)
+#define RT5659_PWR_CLK25M_PU (0x1 << 4)
+
+/* REC Mixer 2 Left Control 2 (0x009c) */
+#define RT5659_M_BST1_RM2_L (0x1 << 5)
+#define RT5659_M_BST1_RM2_L_SFT 5
+#define RT5659_M_BST2_RM2_L (0x1 << 4)
+#define RT5659_M_BST2_RM2_L_SFT 4
+#define RT5659_M_BST3_RM2_L (0x1 << 3)
+#define RT5659_M_BST3_RM2_L_SFT 3
+#define RT5659_M_BST4_RM2_L (0x1 << 2)
+#define RT5659_M_BST4_RM2_L_SFT 2
+#define RT5659_M_OUTVOLL_RM2_L (0x1 << 1)
+#define RT5659_M_OUTVOLL_RM2_L_SFT 1
+#define RT5659_M_SPKVOL_RM2_L (0x1)
+#define RT5659_M_SPKVOL_RM2_L_SFT 0
+
+/* REC Mixer 2 Right Control 2 (0x009e) */
+#define RT5659_M_BST1_RM2_R (0x1 << 5)
+#define RT5659_M_BST1_RM2_R_SFT 5
+#define RT5659_M_BST2_RM2_R (0x1 << 4)
+#define RT5659_M_BST2_RM2_R_SFT 4
+#define RT5659_M_BST3_RM2_R (0x1 << 3)
+#define RT5659_M_BST3_RM2_R_SFT 3
+#define RT5659_M_BST4_RM2_R (0x1 << 2)
+#define RT5659_M_BST4_RM2_R_SFT 2
+#define RT5659_M_OUTVOLR_RM2_R (0x1 << 1)
+#define RT5659_M_OUTVOLR_RM2_R_SFT 1
+#define RT5659_M_MONOVOL_RM2_R (0x1)
+#define RT5659_M_MONOVOL_RM2_R_SFT 0
+
+/* Class D Output Control (0x00a0) */
+#define RT5659_POW_CLSD_DB_MASK (0x1 << 9)
+#define RT5659_POW_CLSD_DB_EN (0x1 << 9)
+#define RT5659_POW_CLSD_DB_DIS (0x0 << 9)
+
+/* EQ Control 1 (0x00b0) */
+#define RT5659_EQ_SRC_DAC (0x0 << 15)
+#define RT5659_EQ_SRC_ADC (0x1 << 15)
+#define RT5659_EQ_UPD (0x1 << 14)
+#define RT5659_EQ_UPD_BIT 14
+#define RT5659_EQ_CD_MASK (0x1 << 13)
+#define RT5659_EQ_CD_SFT 13
+#define RT5659_EQ_CD_DIS (0x0 << 13)
+#define RT5659_EQ_CD_EN (0x1 << 13)
+#define RT5659_EQ_DITH_MASK (0x3 << 8)
+#define RT5659_EQ_DITH_SFT 8
+#define RT5659_EQ_DITH_NOR (0x0 << 8)
+#define RT5659_EQ_DITH_LSB (0x1 << 8)
+#define RT5659_EQ_DITH_LSB_1 (0x2 << 8)
+#define RT5659_EQ_DITH_LSB_2 (0x3 << 8)
+
+/* IRQ Control 1 (0x00b7) */
+#define RT5659_JD1_1_EN_MASK (0x1 << 15)
+#define RT5659_JD1_1_EN_SFT 15
+#define RT5659_JD1_1_DIS (0x0 << 15)
+#define RT5659_JD1_1_EN (0x1 << 15)
+#define RT5659_JD1_2_EN_MASK (0x1 << 12)
+#define RT5659_JD1_2_EN_SFT 12
+#define RT5659_JD1_2_DIS (0x0 << 12)
+#define RT5659_JD1_2_EN (0x1 << 12)
+#define RT5659_IL_IRQ_MASK (0x1 << 3)
+#define RT5659_IL_IRQ_DIS (0x0 << 3)
+#define RT5659_IL_IRQ_EN (0x1 << 3)
+
+/* IRQ Control 5 (0x00ba) */
+#define RT5659_IRQ_JD_EN (0x1 << 3)
+#define RT5659_IRQ_JD_EN_SFT 3
+
+/* GPIO Control 1 (0x00c0) */
+#define RT5659_GP1_PIN_MASK (0x1 << 15)
+#define RT5659_GP1_PIN_SFT 15
+#define RT5659_GP1_PIN_GPIO1 (0x0 << 15)
+#define RT5659_GP1_PIN_IRQ (0x1 << 15)
+#define RT5659_GP2_PIN_MASK (0x1 << 14)
+#define RT5659_GP2_PIN_SFT 14
+#define RT5659_GP2_PIN_GPIO2 (0x0 << 14)
+#define RT5659_GP2_PIN_DMIC1_SCL (0x1 << 14)
+#define RT5659_GP3_PIN_MASK (0x1 << 13)
+#define RT5659_GP3_PIN_SFT 13
+#define RT5659_GP3_PIN_GPIO3 (0x0 << 13)
+#define RT5659_GP3_PIN_PDM_SCL (0x1 << 13)
+#define RT5659_GP4_PIN_MASK (0x1 << 12)
+#define RT5659_GP4_PIN_SFT 12
+#define RT5659_GP4_PIN_GPIO4 (0x0 << 12)
+#define RT5659_GP4_PIN_PDM_SDA (0x1 << 12)
+#define RT5659_GP5_PIN_MASK (0x1 << 11)
+#define RT5659_GP5_PIN_SFT 11
+#define RT5659_GP5_PIN_GPIO5 (0x0 << 11)
+#define RT5659_GP5_PIN_DMIC1_SDA (0x1 << 11)
+#define RT5659_GP6_PIN_MASK (0x1 << 10)
+#define RT5659_GP6_PIN_SFT 10
+#define RT5659_GP6_PIN_GPIO6 (0x0 << 10)
+#define RT5659_GP6_PIN_DMIC2_SDA (0x1 << 10)
+#define RT5659_GP7_PIN_MASK (0x1 << 9)
+#define RT5659_GP7_PIN_SFT 9
+#define RT5659_GP7_PIN_GPIO7 (0x0 << 9)
+#define RT5659_GP7_PIN_PDM_SCL (0x1 << 9)
+#define RT5659_GP8_PIN_MASK (0x1 << 8)
+#define RT5659_GP8_PIN_SFT 8
+#define RT5659_GP8_PIN_GPIO8 (0x0 << 8)
+#define RT5659_GP8_PIN_PDM_SDA (0x1 << 8)
+#define RT5659_GP9_PIN_MASK (0x1 << 7)
+#define RT5659_GP9_PIN_SFT 7
+#define RT5659_GP9_PIN_GPIO9 (0x0 << 7)
+#define RT5659_GP9_PIN_DMIC1_SDA (0x1 << 7)
+#define RT5659_GP10_PIN_MASK (0x1 << 6)
+#define RT5659_GP10_PIN_SFT 6
+#define RT5659_GP10_PIN_GPIO10 (0x0 << 6)
+#define RT5659_GP10_PIN_DMIC2_SDA (0x1 << 6)
+#define RT5659_GP11_PIN_MASK (0x1 << 5)
+#define RT5659_GP11_PIN_SFT 5
+#define RT5659_GP11_PIN_GPIO11 (0x0 << 5)
+#define RT5659_GP11_PIN_DMIC1_SDA (0x1 << 5)
+#define RT5659_GP12_PIN_MASK (0x1 << 4)
+#define RT5659_GP12_PIN_SFT 4
+#define RT5659_GP12_PIN_GPIO12 (0x0 << 4)
+#define RT5659_GP12_PIN_DMIC2_SDA (0x1 << 4)
+#define RT5659_GP13_PIN_MASK (0x3 << 2)
+#define RT5659_GP13_PIN_SFT 2
+#define RT5659_GP13_PIN_GPIO13 (0x0 << 2)
+#define RT5659_GP13_PIN_SPDIF_SDA (0x1 << 2)
+#define RT5659_GP13_PIN_DMIC2_SCL (0x2 << 2)
+#define RT5659_GP13_PIN_PDM_SCL (0x3 << 2)
+#define RT5659_GP15_PIN_MASK (0x3)
+#define RT5659_GP15_PIN_SFT 0
+#define RT5659_GP15_PIN_GPIO15 (0x0)
+#define RT5659_GP15_PIN_DMIC3_SCL (0x1)
+#define RT5659_GP15_PIN_PDM_SDA (0x2)
+
+/* GPIO Control 2 (0x00c1)*/
+#define RT5659_GP1_PF_IN (0x0 << 2)
+#define RT5659_GP1_PF_OUT (0x1 << 2)
+#define RT5659_GP1_PF_MASK (0x1 << 2)
+#define RT5659_GP1_PF_SFT 2
+
+/* GPIO Control 3 (0x00c2) */
+#define RT5659_I2S2_PIN_MASK (0x1 << 15)
+#define RT5659_I2S2_PIN_SFT 15
+#define RT5659_I2S2_PIN_I2S (0x0 << 15)
+#define RT5659_I2S2_PIN_GPIO (0x1 << 15)
+
+/* Soft volume and zero cross control 1 (0x00d9) */
+#define RT5659_SV_MASK (0x1 << 15)
+#define RT5659_SV_SFT 15
+#define RT5659_SV_DIS (0x0 << 15)
+#define RT5659_SV_EN (0x1 << 15)
+#define RT5659_OUT_SV_MASK (0x1 << 13)
+#define RT5659_OUT_SV_SFT 13
+#define RT5659_OUT_SV_DIS (0x0 << 13)
+#define RT5659_OUT_SV_EN (0x1 << 13)
+#define RT5659_HP_SV_MASK (0x1 << 12)
+#define RT5659_HP_SV_SFT 12
+#define RT5659_HP_SV_DIS (0x0 << 12)
+#define RT5659_HP_SV_EN (0x1 << 12)
+#define RT5659_ZCD_DIG_MASK (0x1 << 11)
+#define RT5659_ZCD_DIG_SFT 11
+#define RT5659_ZCD_DIG_DIS (0x0 << 11)
+#define RT5659_ZCD_DIG_EN (0x1 << 11)
+#define RT5659_ZCD_MASK (0x1 << 10)
+#define RT5659_ZCD_SFT 10
+#define RT5659_ZCD_PD (0x0 << 10)
+#define RT5659_ZCD_PU (0x1 << 10)
+#define RT5659_SV_DLY_MASK (0xf)
+#define RT5659_SV_DLY_SFT 0
+
+/* Soft volume and zero cross control 2 (0x00da) */
+#define RT5659_ZCD_HP_MASK (0x1 << 15)
+#define RT5659_ZCD_HP_SFT 15
+#define RT5659_ZCD_HP_DIS (0x0 << 15)
+#define RT5659_ZCD_HP_EN (0x1 << 15)
+
+/* 4 Button Inline Command Control 2 (0x00e0) */
+#define RT5659_4BTN_IL_MASK (0x1 << 15)
+#define RT5659_4BTN_IL_EN (0x1 << 15)
+#define RT5659_4BTN_IL_DIS (0x0 << 15)
+
+/* Analog JD Control 1 (0x00f0) */
+#define RT5659_JD1_MODE_MASK (0x3 << 0)
+#define RT5659_JD1_MODE_0 (0x0 << 0)
+#define RT5659_JD1_MODE_1 (0x1 << 0)
+#define RT5659_JD1_MODE_2 (0x2 << 0)
+
+/* Jack Detect Control 3 (0x00f8) */
+#define RT5659_JD_TRI_HPO_SEL_MASK (0x7)
+#define RT5659_JD_TRI_HPO_SEL_SFT (0)
+#define RT5659_JD_HPO_GPIO_JD1 (0x0)
+#define RT5659_JD_HPO_JD1_1 (0x1)
+#define RT5659_JD_HPO_JD1_2 (0x2)
+#define RT5659_JD_HPO_JD2 (0x3)
+#define RT5659_JD_HPO_GPIO_JD2 (0x4)
+#define RT5659_JD_HPO_JD3 (0x5)
+#define RT5659_JD_HPO_JD_D (0x6)
+
+/* Digital Misc Control (0x00fa) */
+#define RT5659_AM_MASK (0x1 << 7)
+#define RT5659_AM_EN (0x1 << 7)
+#define RT5659_AM_DIS (0x1 << 7)
+#define RT5659_DIG_GATE_CTRL 0x1
+#define RT5659_DIG_GATE_CTRL_SFT (0)
+
+/* Chopper and Clock control for ADC (0x011c)*/
+#define RT5659_M_RF_DIG_MASK (0x1 << 12)
+#define RT5659_M_RF_DIG_SFT 12
+#define RT5659_M_RI_DIG (0x1 << 11)
+
+/* Chopper and Clock control for DAC (0x013a)*/
+#define RT5659_CKXEN_DAC1_MASK (0x1 << 13)
+#define RT5659_CKXEN_DAC1_SFT 13
+#define RT5659_CKGEN_DAC1_MASK (0x1 << 12)
+#define RT5659_CKGEN_DAC1_SFT 12
+#define RT5659_CKXEN_DAC2_MASK (0x1 << 5)
+#define RT5659_CKXEN_DAC2_SFT 5
+#define RT5659_CKGEN_DAC2_MASK (0x1 << 4)
+#define RT5659_CKGEN_DAC2_SFT 4
+
+/* Chopper and Clock control for ADC (0x013b)*/
+#define RT5659_CKXEN_ADCC_MASK (0x1 << 13)
+#define RT5659_CKXEN_ADCC_SFT 13
+#define RT5659_CKGEN_ADCC_MASK (0x1 << 12)
+#define RT5659_CKGEN_ADCC_SFT 12
+
+/* Test Mode Control 1 (0x0145) */
+#define RT5659_AD2DA_LB_MASK (0x1 << 9)
+#define RT5659_AD2DA_LB_SFT 9
+
+/* Stereo Noise Gate Control 1 (0x0160) */
+#define RT5659_NG2_EN_MASK (0x1 << 15)
+#define RT5659_NG2_EN (0x1 << 15)
+#define RT5659_NG2_DIS (0x0 << 15)
+
+/* System Clock Source */
+enum {
+ RT5659_SCLK_S_MCLK,
+ RT5659_SCLK_S_PLL1,
+ RT5659_SCLK_S_RCCLK,
+};
+
+/* PLL1 Source */
+enum {
+ RT5659_PLL1_S_MCLK,
+ RT5659_PLL1_S_BCLK1,
+ RT5659_PLL1_S_BCLK2,
+ RT5659_PLL1_S_BCLK3,
+ RT5659_PLL1_S_BCLK4,
+};
+
+enum {
+ RT5659_AIF1,
+ RT5659_AIF2,
+ RT5659_AIF3,
+ RT5659_AIF4,
+ RT5659_AIFS,
+};
+
+struct rt5659_pll_code {
+ bool m_bp;
+ int m_code;
+ int n_code;
+ int k_code;
+};
+
+struct rt5659_priv {
+ struct snd_soc_codec *codec;
+ struct rt5659_platform_data pdata;
+ struct regmap *regmap;
+ struct i2c_client *i2c;
+ struct gpio_desc *gpiod_ldo1_en;
+ struct gpio_desc *gpiod_reset;
+ struct snd_soc_jack *hs_jack;
+ struct delayed_work jack_detect_work;
+
+ int sysclk;
+ int sysclk_src;
+ int lrck[RT5659_AIFS];
+ int bclk[RT5659_AIFS];
+ int master[RT5659_AIFS];
+ int v_id;
+
+ int pll_src;
+ int pll_in;
+ int pll_out;
+
+ int jack_type;
+
+};
+
+int rt5659_set_jack_detect(struct snd_soc_codec *codec,
+ struct snd_soc_jack *hs_jack);
+
+#endif /* __RT5659_H__ */
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index 69d987a9935c..967678e7f48e 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -297,8 +297,6 @@ static bool rt5677_volatile_register(struct device *dev, unsigned int reg)
case RT5677_HAP_GENE_CTRL2:
case RT5677_PWR_DSP_ST:
case RT5677_PRIV_DATA:
- case RT5677_PLL1_CTRL2:
- case RT5677_PLL2_CTRL2:
case RT5677_ASRC_22:
case RT5677_ASRC_23:
case RT5677_VAD_CTRL5:
@@ -4788,7 +4786,7 @@ static int rt5677_remove(struct snd_soc_codec *codec)
regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec);
gpiod_set_value_cansleep(rt5677->pow_ldo2, 0);
- gpiod_set_value_cansleep(rt5677->reset_pin, 0);
+ gpiod_set_value_cansleep(rt5677->reset_pin, 1);
return 0;
}
@@ -4803,7 +4801,7 @@ static int rt5677_suspend(struct snd_soc_codec *codec)
regcache_mark_dirty(rt5677->regmap);
gpiod_set_value_cansleep(rt5677->pow_ldo2, 0);
- gpiod_set_value_cansleep(rt5677->reset_pin, 0);
+ gpiod_set_value_cansleep(rt5677->reset_pin, 1);
}
return 0;
@@ -4814,8 +4812,11 @@ static int rt5677_resume(struct snd_soc_codec *codec)
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
if (!rt5677->dsp_vad_en) {
+ rt5677->pll_src = 0;
+ rt5677->pll_in = 0;
+ rt5677->pll_out = 0;
gpiod_set_value_cansleep(rt5677->pow_ldo2, 1);
- gpiod_set_value_cansleep(rt5677->reset_pin, 1);
+ gpiod_set_value_cansleep(rt5677->reset_pin, 0);
if (rt5677->pow_ldo2 || rt5677->reset_pin)
msleep(10);
@@ -5160,7 +5161,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
return ret;
}
rt5677->reset_pin = devm_gpiod_get_optional(&i2c->dev,
- "realtek,reset", GPIOD_OUT_HIGH);
+ "realtek,reset", GPIOD_OUT_LOW);
if (IS_ERR(rt5677->reset_pin)) {
ret = PTR_ERR(rt5677->reset_pin);
dev_err(&i2c->dev, "Failed to request RESET: %d\n", ret);
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c
index 86b81a60ac52..e2e0bfa7ec20 100644
--- a/sound/soc/codecs/ssm2518.c
+++ b/sound/soc/codecs/ssm2518.c
@@ -309,7 +309,7 @@ static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000 = {
.count = ARRAY_SIZE(ssm2518_rates_12288000),
};
-static unsigned int ssm2518_lookup_mcs(struct ssm2518 *ssm2518,
+static int ssm2518_lookup_mcs(struct ssm2518 *ssm2518,
unsigned int rate)
{
const unsigned int *sysclks = NULL;
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 4cad8929d262..bc3de2e844e6 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -1097,8 +1097,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
{
struct twl6040_data *priv;
struct twl6040 *twl6040 = dev_get_drvdata(codec->dev->parent);
- struct platform_device *pdev = container_of(codec->dev,
- struct platform_device, dev);
+ struct platform_device *pdev = to_platform_device(codec->dev);
int ret = 0;
priv = devm_kzalloc(codec->dev, sizeof(*priv), GFP_KERNEL);
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index c04c0bc6f58a..6088d30962a9 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -360,15 +360,13 @@ static int wm5110_hp_ev(struct snd_soc_dapm_widget *w,
static int wm5110_clear_pga_volume(struct arizona *arizona, int output)
{
- struct reg_sequence clear_pga = {
- ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4, 0x80
- };
+ unsigned int reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4;
int ret;
- ret = regmap_multi_reg_write_bypassed(arizona->regmap, &clear_pga, 1);
+ ret = regmap_write(arizona->regmap, reg, 0x80);
if (ret)
dev_err(arizona->dev, "Failed to clear PGA (0x%x): %d\n",
- clear_pga.reg, ret);
+ reg, ret);
return ret;
}
@@ -439,18 +437,17 @@ static int wm5110_in_pga_get(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
- struct snd_soc_card *card = dapm->card;
int ret;
/*
* PGA Volume is also used as part of the enable sequence, so
* usage of it should be avoided whilst that is running.
*/
- mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ snd_soc_dapm_mutex_lock(dapm);
ret = snd_soc_get_volsw_range(kcontrol, ucontrol);
- mutex_unlock(&card->dapm_mutex);
+ snd_soc_dapm_mutex_unlock(dapm);
return ret;
}
@@ -460,18 +457,17 @@ static int wm5110_in_pga_put(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
- struct snd_soc_card *card = dapm->card;
int ret;
/*
* PGA Volume is also used as part of the enable sequence, so
* usage of it should be avoided whilst that is running.
*/
- mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+ snd_soc_dapm_mutex_lock(dapm);
ret = snd_soc_put_volsw_range(kcontrol, ucontrol);
- mutex_unlock(&card->dapm_mutex);
+ snd_soc_dapm_mutex_unlock(dapm);
return ret;
}
@@ -575,6 +571,33 @@ static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
SOC_SINGLE(name " NG SPKDAT2L Switch", base, 10, 1, 0), \
SOC_SINGLE(name " NG SPKDAT2R Switch", base, 11, 1, 0)
+#define WM5110_RXANC_INPUT_ROUTES(widget, name) \
+ { widget, NULL, name " NG Mux" }, \
+ { name " NG Internal", NULL, "RXANC NG Clock" }, \
+ { name " NG Internal", NULL, name " Channel" }, \
+ { name " NG External", NULL, "RXANC NG External Clock" }, \
+ { name " NG External", NULL, name " Channel" }, \
+ { name " NG Mux", "None", name " Channel" }, \
+ { name " NG Mux", "Internal", name " NG Internal" }, \
+ { name " NG Mux", "External", name " NG External" }, \
+ { name " Channel", "Left", name " Left Input" }, \
+ { name " Channel", "Combine", name " Left Input" }, \
+ { name " Channel", "Right", name " Right Input" }, \
+ { name " Channel", "Combine", name " Right Input" }, \
+ { name " Left Input", "IN1", "IN1L PGA" }, \
+ { name " Right Input", "IN1", "IN1R PGA" }, \
+ { name " Left Input", "IN2", "IN2L PGA" }, \
+ { name " Right Input", "IN2", "IN2R PGA" }, \
+ { name " Left Input", "IN3", "IN3L PGA" }, \
+ { name " Right Input", "IN3", "IN3R PGA" }, \
+ { name " Left Input", "IN4", "IN4L PGA" }, \
+ { name " Right Input", "IN4", "IN4R PGA" }
+
+#define WM5110_RXANC_OUTPUT_ROUTES(widget, name) \
+ { widget, NULL, name " ANC Source" }, \
+ { name " ANC Source", "RXANCL", "RXANCL" }, \
+ { name " ANC Source", "RXANCR", "RXANCR" }
+
static const struct snd_kcontrol_new wm5110_snd_controls[] = {
SOC_ENUM("IN1 OSR", arizona_in_dmic_osr[0]),
SOC_ENUM("IN2 OSR", arizona_in_dmic_osr[1]),
@@ -639,6 +662,15 @@ SOC_SINGLE_TLV("IN4R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4R,
SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+SND_SOC_BYTES("RXANC Coefficients", ARIZONA_ANC_COEFF_START,
+ ARIZONA_ANC_COEFF_END - ARIZONA_ANC_COEFF_START + 1),
+SND_SOC_BYTES("RXANCL Config", ARIZONA_FCL_FILTER_CONTROL, 1),
+SND_SOC_BYTES("RXANCL Coefficients", ARIZONA_FCL_COEFF_START,
+ ARIZONA_FCL_COEFF_END - ARIZONA_FCL_COEFF_START + 1),
+SND_SOC_BYTES("RXANCR Config", ARIZONA_FCR_FILTER_CONTROL, 1),
+SND_SOC_BYTES("RXANCR Coefficients", ARIZONA_FCR_COEFF_START,
+ ARIZONA_FCR_COEFF_END - ARIZONA_FCR_COEFF_START + 1),
+
ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
@@ -995,6 +1027,31 @@ static const struct soc_enum wm5110_aec_loopback =
static const struct snd_kcontrol_new wm5110_aec_loopback_mux =
SOC_DAPM_ENUM("AEC Loopback", wm5110_aec_loopback);
+static const struct snd_kcontrol_new wm5110_anc_input_mux[] = {
+ SOC_DAPM_ENUM("RXANCL Input", arizona_anc_input_src[0]),
+ SOC_DAPM_ENUM("RXANCL Channel", arizona_anc_input_src[1]),
+ SOC_DAPM_ENUM("RXANCR Input", arizona_anc_input_src[2]),
+ SOC_DAPM_ENUM("RXANCR Channel", arizona_anc_input_src[3]),
+};
+
+static const struct snd_kcontrol_new wm5110_anc_ng_mux =
+ SOC_DAPM_ENUM("RXANC NG Source", arizona_anc_ng_enum);
+
+static const struct snd_kcontrol_new wm5110_output_anc_src[] = {
+ SOC_DAPM_ENUM("HPOUT1L ANC Source", arizona_output_anc_src[0]),
+ SOC_DAPM_ENUM("HPOUT1R ANC Source", arizona_output_anc_src[1]),
+ SOC_DAPM_ENUM("HPOUT2L ANC Source", arizona_output_anc_src[2]),
+ SOC_DAPM_ENUM("HPOUT2R ANC Source", arizona_output_anc_src[3]),
+ SOC_DAPM_ENUM("HPOUT3L ANC Source", arizona_output_anc_src[4]),
+ SOC_DAPM_ENUM("HPOUT3R ANC Source", arizona_output_anc_src[5]),
+ SOC_DAPM_ENUM("SPKOUTL ANC Source", arizona_output_anc_src[6]),
+ SOC_DAPM_ENUM("SPKOUTR ANC Source", arizona_output_anc_src[7]),
+ SOC_DAPM_ENUM("SPKDAT1L ANC Source", arizona_output_anc_src[8]),
+ SOC_DAPM_ENUM("SPKDAT1R ANC Source", arizona_output_anc_src[9]),
+ SOC_DAPM_ENUM("SPKDAT2L ANC Source", arizona_output_anc_src[10]),
+ SOC_DAPM_ENUM("SPKDAT2R ANC Source", arizona_output_anc_src[11]),
+};
+
static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
0, wm5110_sysclk_ev, SND_SOC_DAPM_POST_PMU),
@@ -1185,6 +1242,65 @@ SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
&wm5110_aec_loopback_mux),
+SND_SOC_DAPM_SUPPLY("RXANC NG External Clock", SND_SOC_NOPM,
+ ARIZONA_EXT_NG_SEL_SET_SHIFT, 0, arizona_anc_ev,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA("RXANCL NG External", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_PGA("RXANCR NG External", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_SUPPLY("RXANC NG Clock", SND_SOC_NOPM,
+ ARIZONA_CLK_NG_ENA_SET_SHIFT, 0, arizona_anc_ev,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA("RXANCL NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_PGA("RXANCR NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_MUX("RXANCL Left Input", SND_SOC_NOPM, 0, 0,
+ &wm5110_anc_input_mux[0]),
+SND_SOC_DAPM_MUX("RXANCL Right Input", SND_SOC_NOPM, 0, 0,
+ &wm5110_anc_input_mux[0]),
+SND_SOC_DAPM_MUX("RXANCL Channel", SND_SOC_NOPM, 0, 0,
+ &wm5110_anc_input_mux[1]),
+SND_SOC_DAPM_MUX("RXANCL NG Mux", SND_SOC_NOPM, 0, 0, &wm5110_anc_ng_mux),
+SND_SOC_DAPM_MUX("RXANCR Left Input", SND_SOC_NOPM, 0, 0,
+ &wm5110_anc_input_mux[2]),
+SND_SOC_DAPM_MUX("RXANCR Right Input", SND_SOC_NOPM, 0, 0,
+ &wm5110_anc_input_mux[2]),
+SND_SOC_DAPM_MUX("RXANCR Channel", SND_SOC_NOPM, 0, 0,
+ &wm5110_anc_input_mux[3]),
+SND_SOC_DAPM_MUX("RXANCR NG Mux", SND_SOC_NOPM, 0, 0, &wm5110_anc_ng_mux),
+
+SND_SOC_DAPM_PGA_E("RXANCL", SND_SOC_NOPM, ARIZONA_CLK_L_ENA_SET_SHIFT,
+ 0, NULL, 0, arizona_anc_ev,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA_E("RXANCR", SND_SOC_NOPM, ARIZONA_CLK_R_ENA_SET_SHIFT,
+ 0, NULL, 0, arizona_anc_ev,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+SND_SOC_DAPM_MUX("HPOUT1L ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[0]),
+SND_SOC_DAPM_MUX("HPOUT1R ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[1]),
+SND_SOC_DAPM_MUX("HPOUT2L ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[2]),
+SND_SOC_DAPM_MUX("HPOUT2R ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[3]),
+SND_SOC_DAPM_MUX("HPOUT3L ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[4]),
+SND_SOC_DAPM_MUX("HPOUT3R ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[5]),
+SND_SOC_DAPM_MUX("SPKOUTL ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[6]),
+SND_SOC_DAPM_MUX("SPKOUTR ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[7]),
+SND_SOC_DAPM_MUX("SPKDAT1L ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[8]),
+SND_SOC_DAPM_MUX("SPKDAT1R ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[9]),
+SND_SOC_DAPM_MUX("SPKDAT2L ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[10]),
+SND_SOC_DAPM_MUX("SPKDAT2R ANC Source", SND_SOC_NOPM, 0, 0,
+ &wm5110_output_anc_src[11]),
+
SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
@@ -1690,6 +1806,9 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
{ "Slim2 Capture", NULL, "SYSCLK" },
{ "Slim3 Capture", NULL, "SYSCLK" },
+ { "Voice Control DSP", NULL, "DSP3" },
+ { "Voice Control DSP", NULL, "SYSCLK" },
+
{ "IN1L PGA", NULL, "IN1L" },
{ "IN1R PGA", NULL, "IN1R" },
@@ -1838,6 +1957,22 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
{ "SPKDAT2L", NULL, "OUT6L" },
{ "SPKDAT2R", NULL, "OUT6R" },
+ WM5110_RXANC_INPUT_ROUTES("RXANCL", "RXANCL"),
+ WM5110_RXANC_INPUT_ROUTES("RXANCR", "RXANCR"),
+
+ WM5110_RXANC_OUTPUT_ROUTES("OUT1L", "HPOUT1L"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT1R", "HPOUT1R"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT2L", "HPOUT2L"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT2R", "HPOUT2R"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT3L", "HPOUT3L"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT3R", "HPOUT3R"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT4L", "SPKOUTL"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT4R", "SPKOUTR"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT5L", "SPKDAT1L"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT5R", "SPKDAT1R"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT6L", "SPKDAT2L"),
+ WM5110_RXANC_OUTPUT_ROUTES("OUT6R", "SPKDAT2R"),
+
{ "MICSUPP", NULL, "SYSCLK" },
{ "DRC1 Signal Activity", NULL, "DRC1L" },
@@ -1996,12 +2131,65 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
},
.ops = &arizona_simple_dai_ops,
},
+ {
+ .name = "wm5110-cpu-voicectrl",
+ .capture = {
+ .stream_name = "Voice Control CPU",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = WM5110_RATES,
+ .formats = WM5110_FORMATS,
+ },
+ .compress_new = snd_soc_new_compress,
+ },
+ {
+ .name = "wm5110-dsp-voicectrl",
+ .capture = {
+ .stream_name = "Voice Control DSP",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = WM5110_RATES,
+ .formats = WM5110_FORMATS,
+ },
+ },
};
+static int wm5110_open(struct snd_compr_stream *stream)
+{
+ struct snd_soc_pcm_runtime *rtd = stream->private_data;
+ struct wm5110_priv *priv = snd_soc_codec_get_drvdata(rtd->codec);
+ struct arizona *arizona = priv->core.arizona;
+ int n_adsp;
+
+ if (strcmp(rtd->codec_dai->name, "wm5110-dsp-voicectrl") == 0) {
+ n_adsp = 2;
+ } else {
+ dev_err(arizona->dev,
+ "No suitable compressed stream for DAI '%s'\n",
+ rtd->codec_dai->name);
+ return -EINVAL;
+ }
+
+ return wm_adsp_compr_open(&priv->core.adsp[n_adsp], stream);
+}
+
+static irqreturn_t wm5110_adsp2_irq(int irq, void *data)
+{
+ struct wm5110_priv *florida = data;
+ int ret;
+
+ ret = wm_adsp_compr_handle_irq(&florida->core.adsp[2]);
+ if (ret == -ENODEV)
+ return IRQ_NONE;
+
+ return IRQ_HANDLED;
+}
+
static int wm5110_codec_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct arizona *arizona = priv->core.arizona;
int i, ret;
priv->core.arizona->dapm = dapm;
@@ -2010,6 +2198,14 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
arizona_init_gpio(codec);
arizona_init_mono(codec);
+ ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
+ "ADSP2 Compressed IRQ", wm5110_adsp2_irq,
+ priv);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret);
+ return ret;
+ }
+
for (i = 0; i < WM5110_NUM_ADSP; ++i) {
ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec);
if (ret)
@@ -2030,12 +2226,15 @@ err_adsp2_codec_probe:
for (--i; i >= 0; --i)
wm_adsp2_codec_remove(&priv->core.adsp[i], codec);
+ arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
+
return ret;
}
static int wm5110_codec_remove(struct snd_soc_codec *codec)
{
struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct arizona *arizona = priv->core.arizona;
int i;
for (i = 0; i < WM5110_NUM_ADSP; ++i)
@@ -2043,6 +2242,8 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec)
priv->core.arizona->dapm = NULL;
+ arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
+
return 0;
}
@@ -2088,6 +2289,20 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
.num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes),
};
+static struct snd_compr_ops wm5110_compr_ops = {
+ .open = wm5110_open,
+ .free = wm_adsp_compr_free,
+ .set_params = wm_adsp_compr_set_params,
+ .get_caps = wm_adsp_compr_get_caps,
+ .trigger = wm_adsp_compr_trigger,
+ .pointer = wm_adsp_compr_pointer,
+ .copy = wm_adsp_compr_copy,
+};
+
+static struct snd_soc_platform_driver wm5110_compr_platform = {
+ .compr_ops = &wm5110_compr_ops,
+};
+
static int wm5110_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
@@ -2148,8 +2363,21 @@ static int wm5110_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
pm_runtime_idle(&pdev->dev);
- return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110,
+ ret = snd_soc_register_platform(&pdev->dev, &wm5110_compr_platform);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
+ goto error;
+ }
+
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110,
wm5110_dai, ARRAY_SIZE(wm5110_dai));
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
+ snd_soc_unregister_platform(&pdev->dev);
+ }
+
+error:
+ return ret;
}
static int wm5110_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index e4cc41e6c23e..2ed6419c181e 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1804,7 +1804,7 @@ static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset)
regmap_read(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, &reg);
- return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT;
+ return !!((reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT);
}
static int wm8903_gpio_direction_out(struct gpio_chip *chip,
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 2aa23f1b9e3c..8172e499e6ed 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -312,7 +312,7 @@ static bool wm8904_readable_register(struct device *dev, unsigned int reg)
case WM8904_FLL_NCO_TEST_1:
return true;
default:
- return true;
+ return false;
}
}
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 5380798883b5..ff237726775a 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -147,6 +147,13 @@ static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};
static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"};
static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};
static const char *wm8960_alcmode[] = {"ALC", "Limiter"};
+static const char *wm8960_adc_data_output_sel[] = {
+ "Left Data = Left ADC; Right Data = Right ADC",
+ "Left Data = Left ADC; Right Data = Left ADC",
+ "Left Data = Right ADC; Right Data = Right ADC",
+ "Left Data = Right ADC; Right Data = Left ADC",
+};
+static const char *wm8960_dmonomix[] = {"Stereo", "Mono"};
static const struct soc_enum wm8960_enum[] = {
SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
@@ -155,6 +162,8 @@ static const struct soc_enum wm8960_enum[] = {
SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff),
SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc),
SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
+ SOC_ENUM_SINGLE(WM8960_ADDCTL1, 2, 4, wm8960_adc_data_output_sel),
+ SOC_ENUM_SINGLE(WM8960_ADDCTL1, 4, 2, wm8960_dmonomix),
};
static const int deemph_settings[] = { 0, 32000, 44100, 48000 };
@@ -295,6 +304,9 @@ SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume",
WM8960_BYPASS2, 4, 7, 1, bypass_tlv),
SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume",
WM8960_ROUTMIX, 4, 7, 1, bypass_tlv),
+
+SOC_ENUM("ADC Data Output Select", wm8960_enum[6]),
+SOC_ENUM("DAC Mono Mix", wm8960_enum[7]),
};
static const struct snd_kcontrol_new wm8960_lin_boost[] = {
@@ -401,8 +413,8 @@ static const struct snd_soc_dapm_route audio_paths[] = {
{ "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
{ "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" },
- { "Left Input Mixer", "Boost Switch", "Left Boost Mixer", },
- { "Left Input Mixer", NULL, "LINPUT1", }, /* Really Boost Switch */
+ { "Left Input Mixer", "Boost Switch", "Left Boost Mixer" },
+ { "Left Input Mixer", "Boost Switch", "LINPUT1" }, /* Really Boost Switch */
{ "Left Input Mixer", NULL, "LINPUT2" },
{ "Left Input Mixer", NULL, "LINPUT3" },
@@ -410,8 +422,8 @@ static const struct snd_soc_dapm_route audio_paths[] = {
{ "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" },
{ "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" },
- { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", },
- { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */
+ { "Right Input Mixer", "Boost Switch", "Right Boost Mixer" },
+ { "Right Input Mixer", "Boost Switch", "RINPUT1" }, /* Really Boost Switch */
{ "Right Input Mixer", NULL, "RINPUT2" },
{ "Right Input Mixer", NULL, "RINPUT3" },
@@ -419,11 +431,11 @@ static const struct snd_soc_dapm_route audio_paths[] = {
{ "Right ADC", NULL, "Right Input Mixer" },
{ "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" },
- { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer"} ,
+ { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer" },
{ "Left Output Mixer", "PCM Playback Switch", "Left DAC" },
{ "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" },
- { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } ,
+ { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" },
{ "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
{ "LOUT1 PGA", NULL, "Left Output Mixer" },
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index a7e79784fc16..949f632fc3f8 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -131,7 +131,7 @@ static const struct reg_default wm8962_reg[] = {
{ 15, 0x6243 }, /* R15 - Software Reset */
{ 17, 0x007B }, /* R17 - ALC1 */
-
+ { 18, 0x0000 }, /* R18 - ALC2 */
{ 19, 0x1C32 }, /* R19 - ALC3 */
{ 20, 0x3200 }, /* R20 - Noise Gate */
{ 21, 0x00C0 }, /* R21 - Left ADC volume */
@@ -794,7 +794,6 @@ static bool wm8962_volatile_register(struct device *dev, unsigned int reg)
case WM8962_CLOCKING1:
case WM8962_CLOCKING2:
case WM8962_SOFTWARE_RESET:
- case WM8962_ALC2:
case WM8962_THERMAL_SHUTDOWN_STATUS:
case WM8962_ADDITIONAL_CONTROL_4:
case WM8962_DC_SERVO_6:
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 4c29bd2ae75c..c284c7b6db8b 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -632,9 +632,16 @@ static const struct i2c_device_id wm8974_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
+static const struct of_device_id wm8974_of_match[] = {
+ { .compatible = "wlf,wm8974", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8974_of_match);
+
static struct i2c_driver wm8974_i2c_driver = {
.driver = {
.name = "wm8974",
+ .of_match_table = wm8974_of_match,
},
.probe = wm8974_i2c_probe,
.remove = wm8974_i2c_remove,
diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c
index 8782dfb628ab..7719bc509e50 100644
--- a/sound/soc/codecs/wm8998.c
+++ b/sound/soc/codecs/wm8998.c
@@ -199,20 +199,20 @@ static const char * const wm8998_inmux_texts[] = {
"B",
};
-static const SOC_ENUM_SINGLE_DECL(wm8998_in1muxl_enum,
- ARIZONA_ADC_DIGITAL_VOLUME_1L,
- ARIZONA_IN1L_SRC_SHIFT,
- wm8998_inmux_texts);
+static SOC_ENUM_SINGLE_DECL(wm8998_in1muxl_enum,
+ ARIZONA_ADC_DIGITAL_VOLUME_1L,
+ ARIZONA_IN1L_SRC_SHIFT,
+ wm8998_inmux_texts);
-static const SOC_ENUM_SINGLE_DECL(wm8998_in1muxr_enum,
- ARIZONA_ADC_DIGITAL_VOLUME_1R,
- ARIZONA_IN1R_SRC_SHIFT,
- wm8998_inmux_texts);
+static SOC_ENUM_SINGLE_DECL(wm8998_in1muxr_enum,
+ ARIZONA_ADC_DIGITAL_VOLUME_1R,
+ ARIZONA_IN1R_SRC_SHIFT,
+ wm8998_inmux_texts);
-static const SOC_ENUM_SINGLE_DECL(wm8998_in2mux_enum,
- ARIZONA_ADC_DIGITAL_VOLUME_2L,
- ARIZONA_IN2L_SRC_SHIFT,
- wm8998_inmux_texts);
+static SOC_ENUM_SINGLE_DECL(wm8998_in2mux_enum,
+ ARIZONA_ADC_DIGITAL_VOLUME_2L,
+ ARIZONA_IN2L_SRC_SHIFT,
+ wm8998_inmux_texts);
static const struct snd_kcontrol_new wm8998_in1mux[2] = {
SOC_DAPM_ENUM_EXT("IN1L Mux", wm8998_in1muxl_enum,
@@ -522,17 +522,17 @@ static const unsigned int wm8998_aec_loopback_values[] = {
0, 1, 2, 3, 4, 6, 7, 8, 9,
};
-static const SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec1_loopback,
- ARIZONA_DAC_AEC_CONTROL_1,
- ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
- wm8998_aec_loopback_texts,
- wm8998_aec_loopback_values);
-
-static const SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec2_loopback,
- ARIZONA_DAC_AEC_CONTROL_2,
- ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
- wm8998_aec_loopback_texts,
- wm8998_aec_loopback_values);
+static SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec1_loopback,
+ ARIZONA_DAC_AEC_CONTROL_1,
+ ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
+ wm8998_aec_loopback_texts,
+ wm8998_aec_loopback_values);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec2_loopback,
+ ARIZONA_DAC_AEC_CONTROL_2,
+ ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
+ wm8998_aec_loopback_texts,
+ wm8998_aec_loopback_values);
static const struct snd_kcontrol_new wm8998_aec_loopback_mux[] = {
SOC_DAPM_ENUM("AEC1 Loopback", wm8998_aec1_loopback),
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 4083a5130cbd..79e143625ac3 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
@@ -39,34 +40,6 @@ struct wm9713_priv {
struct mutex lock;
};
-static unsigned int ac97_read(struct snd_soc_codec *codec,
- unsigned int reg);
-static int ac97_write(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int val);
-
-/*
- * WM9713 register cache
- * Reg 0x3c bit 15 is used by touch driver.
- */
-static const u16 wm9713_reg[] = {
- 0x6174, 0x8080, 0x8080, 0x8080,
- 0xc880, 0xe808, 0xe808, 0x0808,
- 0x00da, 0x8000, 0xd600, 0xaaa0,
- 0xaaa0, 0xaaa0, 0x0000, 0x0000,
- 0x0f0f, 0x0040, 0x0000, 0x7f00,
- 0x0405, 0x0410, 0xbb80, 0xbb80,
- 0x0000, 0xbb80, 0x0000, 0x4523,
- 0x0000, 0x2000, 0x7eff, 0xffff,
- 0x0000, 0x0000, 0x0080, 0x0000,
- 0x0000, 0x0000, 0xfffe, 0xffff,
- 0x0000, 0x0000, 0x0000, 0xfffe,
- 0x4000, 0x0000, 0x0000, 0x0000,
- 0xb032, 0x3e00, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0006,
- 0x0001, 0x0000, 0x574d, 0x4c13,
-};
-
#define HPL_MIXER 0
#define HPR_MIXER 1
@@ -220,18 +193,15 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
- u16 status, rate;
if (WARN_ON(event != SND_SOC_DAPM_PRE_PMD))
return -EINVAL;
/* Gracefully shut down the voice interface. */
- status = ac97_read(codec, AC97_EXTENDED_MID) | 0x1000;
- rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF;
- ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200);
+ snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0f00, 0x0200);
schedule_timeout_interruptible(msecs_to_jiffies(1));
- ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00);
- ac97_write(codec, AC97_EXTENDED_MID, status);
+ snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0f00, 0x0f00);
+ snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0x1000, 0x1000);
return 0;
}
@@ -674,39 +644,97 @@ static const struct snd_soc_dapm_route wm9713_audio_map[] = {
{"Capture Mono Mux", "Right", "Right Capture Source"},
};
-static unsigned int ac97_read(struct snd_soc_codec *codec,
- unsigned int reg)
+static bool wm9713_readable_reg(struct device *dev, unsigned int reg)
{
- struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
- u16 *cache = codec->reg_cache;
-
- if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
- reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
- reg == AC97_CD)
- return soc_ac97_ops->read(wm9713->ac97, reg);
- else {
- reg = reg >> 1;
-
- if (reg >= (ARRAY_SIZE(wm9713_reg)))
- return -EIO;
-
- return cache[reg];
+ switch (reg) {
+ case AC97_RESET ... AC97_PCM_SURR_DAC_RATE:
+ case AC97_PCM_LR_ADC_RATE:
+ case AC97_CENTER_LFE_MASTER:
+ case AC97_SPDIF ... AC97_LINE1_LEVEL:
+ case AC97_GPIO_CFG ... 0x5c:
+ case AC97_CODEC_CLASS_REV ... AC97_PCI_SID:
+ case 0x74 ... AC97_VENDOR_ID2:
+ return true;
+ default:
+ return false;
}
}
-static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int val)
+static bool wm9713_writeable_reg(struct device *dev, unsigned int reg)
{
- struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
+ switch (reg) {
+ case AC97_VENDOR_ID1:
+ case AC97_VENDOR_ID2:
+ return false;
+ default:
+ return wm9713_readable_reg(dev, reg);
+ }
+}
- u16 *cache = codec->reg_cache;
- soc_ac97_ops->write(wm9713->ac97, reg, val);
- reg = reg >> 1;
- if (reg < (ARRAY_SIZE(wm9713_reg)))
- cache[reg] = val;
+static const struct reg_default wm9713_reg_defaults[] = {
+ { 0x02, 0x8080 }, /* Speaker Output Volume */
+ { 0x04, 0x8080 }, /* Headphone Output Volume */
+ { 0x06, 0x8080 }, /* Out3/OUT4 Volume */
+ { 0x08, 0xc880 }, /* Mono Volume */
+ { 0x0a, 0xe808 }, /* LINEIN Volume */
+ { 0x0c, 0xe808 }, /* DAC PGA Volume */
+ { 0x0e, 0x0808 }, /* MIC PGA Volume */
+ { 0x10, 0x00da }, /* MIC Routing Control */
+ { 0x12, 0x8000 }, /* Record PGA Volume */
+ { 0x14, 0xd600 }, /* Record Routing */
+ { 0x16, 0xaaa0 }, /* PCBEEP Volume */
+ { 0x18, 0xaaa0 }, /* VxDAC Volume */
+ { 0x1a, 0xaaa0 }, /* AUXDAC Volume */
+ { 0x1c, 0x0000 }, /* Output PGA Mux */
+ { 0x1e, 0x0000 }, /* DAC 3D control */
+ { 0x20, 0x0f0f }, /* DAC Tone Control*/
+ { 0x22, 0x0040 }, /* MIC Input Select & Bias */
+ { 0x24, 0x0000 }, /* Output Volume Mapping & Jack */
+ { 0x26, 0x7f00 }, /* Powerdown Ctrl/Stat*/
+ { 0x28, 0x0405 }, /* Extended Audio ID */
+ { 0x2a, 0x0410 }, /* Extended Audio Start/Ctrl */
+ { 0x2c, 0xbb80 }, /* Audio DACs Sample Rate */
+ { 0x2e, 0xbb80 }, /* AUXDAC Sample Rate */
+ { 0x32, 0xbb80 }, /* Audio ADCs Sample Rate */
+ { 0x36, 0x4523 }, /* PCM codec control */
+ { 0x3a, 0x2000 }, /* SPDIF control */
+ { 0x3c, 0xfdff }, /* Powerdown 1 */
+ { 0x3e, 0xffff }, /* Powerdown 2 */
+ { 0x40, 0x0000 }, /* General Purpose */
+ { 0x42, 0x0000 }, /* Fast Power-Up Control */
+ { 0x44, 0x0080 }, /* MCLK/PLL Control */
+ { 0x46, 0x0000 }, /* MCLK/PLL Control */
+ { 0x4c, 0xfffe }, /* GPIO Pin Configuration */
+ { 0x4e, 0xffff }, /* GPIO Pin Polarity / Type */
+ { 0x50, 0x0000 }, /* GPIO Pin Sticky */
+ { 0x52, 0x0000 }, /* GPIO Pin Wake-Up */
+ /* GPIO Pin Status */
+ { 0x56, 0xfffe }, /* GPIO Pin Sharing */
+ { 0x58, 0x4000 }, /* GPIO PullUp/PullDown */
+ { 0x5a, 0x0000 }, /* Additional Functions 1 */
+ { 0x5c, 0x0000 }, /* Additional Functions 2 */
+ { 0x60, 0xb032 }, /* ALC Control */
+ { 0x62, 0x3e00 }, /* ALC / Noise Gate Control */
+ { 0x64, 0x0000 }, /* AUXDAC input control */
+ { 0x74, 0x0000 }, /* Digitiser Reg 1 */
+ { 0x76, 0x0006 }, /* Digitiser Reg 2 */
+ { 0x78, 0x0001 }, /* Digitiser Reg 3 */
+ { 0x7a, 0x0000 }, /* Digitiser Read Back */
+};
- return 0;
-}
+static const struct regmap_config wm9713_regmap_config = {
+ .reg_bits = 16,
+ .reg_stride = 2,
+ .val_bits = 16,
+ .max_register = 0x7e,
+ .cache_type = REGCACHE_RBTREE,
+
+ .reg_defaults = wm9713_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm9713_reg_defaults),
+ .volatile_reg = regmap_ac97_default_volatile,
+ .readable_reg = wm9713_readable_reg,
+ .writeable_reg = wm9713_writeable_reg,
+};
/* PLL divisors */
struct _pll_div {
@@ -793,10 +821,8 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
/* turn PLL off ? */
if (freq_in == 0) {
/* disable PLL power and select ext source */
- reg = ac97_read(codec, AC97_HANDSET_RATE);
- ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080);
- reg = ac97_read(codec, AC97_EXTENDED_MID);
- ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200);
+ snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0080, 0x0080);
+ snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0x0200, 0x0200);
wm9713->pll_in = 0;
return 0;
}
@@ -806,7 +832,7 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
if (pll_div.k == 0) {
reg = (pll_div.n << 12) | (pll_div.lf << 11) |
(pll_div.divsel << 9) | (pll_div.divctl << 8);
- ac97_write(codec, AC97_LINE1_LEVEL, reg);
+ snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
} else {
/* write the fractional k to the reg 0x46 pages */
reg2 = (pll_div.n << 12) | (pll_div.lf << 11) | (1 << 10) |
@@ -814,33 +840,31 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
/* K [21:20] */
reg = reg2 | (0x5 << 4) | (pll_div.k >> 20);
- ac97_write(codec, AC97_LINE1_LEVEL, reg);
+ snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
/* K [19:16] */
reg = reg2 | (0x4 << 4) | ((pll_div.k >> 16) & 0xf);
- ac97_write(codec, AC97_LINE1_LEVEL, reg);
+ snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
/* K [15:12] */
reg = reg2 | (0x3 << 4) | ((pll_div.k >> 12) & 0xf);
- ac97_write(codec, AC97_LINE1_LEVEL, reg);
+ snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
/* K [11:8] */
reg = reg2 | (0x2 << 4) | ((pll_div.k >> 8) & 0xf);
- ac97_write(codec, AC97_LINE1_LEVEL, reg);
+ snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
/* K [7:4] */
reg = reg2 | (0x1 << 4) | ((pll_div.k >> 4) & 0xf);
- ac97_write(codec, AC97_LINE1_LEVEL, reg);
+ snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
reg = reg2 | (0x0 << 4) | (pll_div.k & 0xf); /* K [3:0] */
- ac97_write(codec, AC97_LINE1_LEVEL, reg);
+ snd_soc_write(codec, AC97_LINE1_LEVEL, reg);
}
/* turn PLL on and select as source */
- reg = ac97_read(codec, AC97_EXTENDED_MID);
- ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff);
- reg = ac97_read(codec, AC97_HANDSET_RATE);
- ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f);
+ snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0x0200, 0x0000);
+ snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0080, 0x0000);
wm9713->pll_in = freq_in;
/* wait 10ms AC97 link frames for the link to stabilise */
@@ -863,10 +887,10 @@ static int wm9713_set_dai_tristate(struct snd_soc_dai *codec_dai,
int tristate)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0x9fff;
if (tristate)
- ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
+ snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER,
+ 0x6000, 0x0000);
return 0;
}
@@ -879,36 +903,30 @@ static int wm9713_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
int div_id, int div)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 reg;
switch (div_id) {
case WM9713_PCMCLK_DIV:
- reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xf0ff;
- ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+ snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0f00, div);
break;
case WM9713_CLKA_MULT:
- reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffd;
- ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+ snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0002, div);
break;
case WM9713_CLKB_MULT:
- reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffb;
- ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+ snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x0004, div);
break;
case WM9713_HIFI_DIV:
- reg = ac97_read(codec, AC97_HANDSET_RATE) & 0x8fff;
- ac97_write(codec, AC97_HANDSET_RATE, reg | div);
+ snd_soc_update_bits(codec, AC97_HANDSET_RATE, 0x7000, div);
break;
case WM9713_PCMBCLK_DIV:
- reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xf1ff;
- ac97_write(codec, AC97_CENTER_LFE_MASTER, reg | div);
+ snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER, 0x0e00, div);
break;
case WM9713_PCMCLK_PLL_DIV:
- reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
- ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x60 | div);
+ snd_soc_update_bits(codec, AC97_LINE1_LEVEL,
+ 0x007f, div | 0x60);
break;
case WM9713_HIFI_PLL_DIV:
- reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
- ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x70 | div);
+ snd_soc_update_bits(codec, AC97_LINE1_LEVEL,
+ 0x007f, div | 0x70);
break;
default:
return -EINVAL;
@@ -921,7 +939,7 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 gpio = ac97_read(codec, AC97_GPIO_CFG) & 0xffc5;
+ u16 gpio = snd_soc_read(codec, AC97_GPIO_CFG) & 0xffc5;
u16 reg = 0x8000;
/* clock masters */
@@ -974,8 +992,8 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
break;
}
- ac97_write(codec, AC97_GPIO_CFG, gpio);
- ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
+ snd_soc_write(codec, AC97_GPIO_CFG, gpio);
+ snd_soc_write(codec, AC97_CENTER_LFE_MASTER, reg);
return 0;
}
@@ -984,24 +1002,24 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
+ /* enable PCM interface in master mode */
switch (params_width(params)) {
case 16:
break;
case 20:
- reg |= 0x0004;
+ snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER,
+ 0x000c, 0x0004);
break;
case 24:
- reg |= 0x0008;
+ snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER,
+ 0x000c, 0x0008);
break;
case 32:
- reg |= 0x000c;
+ snd_soc_update_bits(codec, AC97_CENTER_LFE_MASTER,
+ 0x000c, 0x000c);
break;
}
-
- /* enable PCM interface in master mode */
- ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
return 0;
}
@@ -1011,17 +1029,15 @@ static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
struct snd_pcm_runtime *runtime = substream->runtime;
int reg;
- u16 vra;
- vra = ac97_read(codec, AC97_EXTENDED_STATUS);
- ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
+ snd_soc_update_bits(codec, AC97_EXTENDED_STATUS, 0x0001, 0x0001);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
reg = AC97_PCM_FRONT_DAC_RATE;
else
reg = AC97_PCM_LR_ADC_RATE;
- return ac97_write(codec, reg, runtime->rate);
+ return snd_soc_write(codec, reg, runtime->rate);
}
static int ac97_aux_prepare(struct snd_pcm_substream *substream,
@@ -1029,17 +1045,14 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
{
struct snd_soc_codec *codec = dai->codec;
struct snd_pcm_runtime *runtime = substream->runtime;
- u16 vra, xsle;
- vra = ac97_read(codec, AC97_EXTENDED_STATUS);
- ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
- xsle = ac97_read(codec, AC97_PCI_SID);
- ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
+ snd_soc_update_bits(codec, AC97_EXTENDED_STATUS, 0x0001, 0x0001);
+ snd_soc_update_bits(codec, AC97_PCI_SID, 0x8000, 0x8000);
if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
return -ENODEV;
- return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
+ return snd_soc_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
}
#define WM9713_RATES (SNDRV_PCM_RATE_8000 | \
@@ -1128,27 +1141,23 @@ static struct snd_soc_dai_driver wm9713_dai[] = {
static int wm9713_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 reg;
-
switch (level) {
case SND_SOC_BIAS_ON:
/* enable thermal shutdown */
- reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff;
- ac97_write(codec, AC97_EXTENDED_MID, reg);
+ snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0xe400, 0x0000);
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
/* enable master bias and vmid */
- reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff;
- ac97_write(codec, AC97_EXTENDED_MID, reg);
- ac97_write(codec, AC97_POWERDOWN, 0x0000);
+ snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0xc400, 0x0000);
+ snd_soc_write(codec, AC97_POWERDOWN, 0x0000);
break;
case SND_SOC_BIAS_OFF:
/* disable everything including AC link */
- ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
- ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
- ac97_write(codec, AC97_POWERDOWN, 0xffff);
+ snd_soc_write(codec, AC97_EXTENDED_MID, 0xffff);
+ snd_soc_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
+ snd_soc_write(codec, AC97_POWERDOWN, 0xffff);
break;
}
return 0;
@@ -1156,16 +1165,14 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec,
static int wm9713_soc_suspend(struct snd_soc_codec *codec)
{
- u16 reg;
-
/* Disable everything except touchpanel - that will be handled
* by the touch driver and left disabled if touch is not in
* use. */
- reg = ac97_read(codec, AC97_EXTENDED_MID);
- ac97_write(codec, AC97_EXTENDED_MID, reg | 0x7fff);
- ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
- ac97_write(codec, AC97_POWERDOWN, 0x6f00);
- ac97_write(codec, AC97_POWERDOWN, 0xffff);
+ snd_soc_update_bits(codec, AC97_EXTENDED_MID, 0x7fff,
+ 0x7fff);
+ snd_soc_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
+ snd_soc_write(codec, AC97_POWERDOWN, 0x6f00);
+ snd_soc_write(codec, AC97_POWERDOWN, 0xffff);
return 0;
}
@@ -1173,8 +1180,7 @@ static int wm9713_soc_suspend(struct snd_soc_codec *codec)
static int wm9713_soc_resume(struct snd_soc_codec *codec)
{
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
- int i, ret;
- u16 *cache = codec->reg_cache;
+ int ret;
ret = snd_ac97_reset(wm9713->ac97, true, WM9713_VENDOR_ID,
WM9713_VENDOR_ID_MASK);
@@ -1189,12 +1195,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
/* only synchronise the codec if warm reset failed */
if (ret == 0) {
- for (i = 2; i < ARRAY_SIZE(wm9713_reg) << 1; i += 2) {
- if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID ||
- i == AC97_EXTENDED_MSTATUS || i > 0x66)
- continue;
- soc_ac97_ops->write(wm9713->ac97, i, cache[i>>1]);
- }
+ regcache_mark_dirty(codec->component.regmap);
+ snd_soc_cache_sync(codec);
}
return ret;
@@ -1203,16 +1205,23 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
static int wm9713_soc_probe(struct snd_soc_codec *codec)
{
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
- int reg;
+ struct regmap *regmap;
wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID,
WM9713_VENDOR_ID_MASK);
if (IS_ERR(wm9713->ac97))
return PTR_ERR(wm9713->ac97);
+ regmap = devm_regmap_init_ac97(wm9713->ac97, &wm9713_regmap_config);
+ if (IS_ERR(regmap)) {
+ snd_soc_free_ac97_codec(wm9713->ac97);
+ return PTR_ERR(regmap);
+ }
+
+ snd_soc_codec_init_regmap(codec, regmap);
+
/* unmute the adc - move to kcontrol */
- reg = ac97_read(codec, AC97_CD) & 0x7fff;
- ac97_write(codec, AC97_CD, reg);
+ snd_soc_update_bits(codec, AC97_CD, 0x7fff, 0x0000);
return 0;
}
@@ -1221,6 +1230,7 @@ static int wm9713_soc_remove(struct snd_soc_codec *codec)
{
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
+ snd_soc_codec_exit_regmap(codec);
snd_soc_free_ac97_codec(wm9713->ac97);
return 0;
}
@@ -1230,13 +1240,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
.remove = wm9713_soc_remove,
.suspend = wm9713_soc_suspend,
.resume = wm9713_soc_resume,
- .read = ac97_read,
- .write = ac97_write,
.set_bias_level = wm9713_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm9713_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_step = 2,
- .reg_cache_default = wm9713_reg,
.controls = wm9713_snd_ac97_controls,
.num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls),
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 0bb415a28723..33806d487b8a 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -201,27 +201,194 @@ static void wm_adsp_buf_free(struct list_head *list)
}
}
-#define WM_ADSP_NUM_FW 4
-
-#define WM_ADSP_FW_MBC_VSS 0
-#define WM_ADSP_FW_TX 1
-#define WM_ADSP_FW_TX_SPK 2
-#define WM_ADSP_FW_RX_ANC 3
+#define WM_ADSP_FW_MBC_VSS 0
+#define WM_ADSP_FW_HIFI 1
+#define WM_ADSP_FW_TX 2
+#define WM_ADSP_FW_TX_SPK 3
+#define WM_ADSP_FW_RX 4
+#define WM_ADSP_FW_RX_ANC 5
+#define WM_ADSP_FW_CTRL 6
+#define WM_ADSP_FW_ASR 7
+#define WM_ADSP_FW_TRACE 8
+#define WM_ADSP_FW_SPK_PROT 9
+#define WM_ADSP_FW_MISC 10
+
+#define WM_ADSP_NUM_FW 11
static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
- [WM_ADSP_FW_MBC_VSS] = "MBC/VSS",
- [WM_ADSP_FW_TX] = "Tx",
- [WM_ADSP_FW_TX_SPK] = "Tx Speaker",
- [WM_ADSP_FW_RX_ANC] = "Rx ANC",
+ [WM_ADSP_FW_MBC_VSS] = "MBC/VSS",
+ [WM_ADSP_FW_HIFI] = "MasterHiFi",
+ [WM_ADSP_FW_TX] = "Tx",
+ [WM_ADSP_FW_TX_SPK] = "Tx Speaker",
+ [WM_ADSP_FW_RX] = "Rx",
+ [WM_ADSP_FW_RX_ANC] = "Rx ANC",
+ [WM_ADSP_FW_CTRL] = "Voice Ctrl",
+ [WM_ADSP_FW_ASR] = "ASR Assist",
+ [WM_ADSP_FW_TRACE] = "Dbg Trace",
+ [WM_ADSP_FW_SPK_PROT] = "Protection",
+ [WM_ADSP_FW_MISC] = "Misc",
+};
+
+struct wm_adsp_system_config_xm_hdr {
+ __be32 sys_enable;
+ __be32 fw_id;
+ __be32 fw_rev;
+ __be32 boot_status;
+ __be32 watchdog;
+ __be32 dma_buffer_size;
+ __be32 rdma[6];
+ __be32 wdma[8];
+ __be32 build_job_name[3];
+ __be32 build_job_number;
+};
+
+struct wm_adsp_alg_xm_struct {
+ __be32 magic;
+ __be32 smoothing;
+ __be32 threshold;
+ __be32 host_buf_ptr;
+ __be32 start_seq;
+ __be32 high_water_mark;
+ __be32 low_water_mark;
+ __be64 smoothed_power;
+};
+
+struct wm_adsp_buffer {
+ __be32 X_buf_base; /* XM base addr of first X area */
+ __be32 X_buf_size; /* Size of 1st X area in words */
+ __be32 X_buf_base2; /* XM base addr of 2nd X area */
+ __be32 X_buf_brk; /* Total X size in words */
+ __be32 Y_buf_base; /* YM base addr of Y area */
+ __be32 wrap; /* Total size X and Y in words */
+ __be32 high_water_mark; /* Point at which IRQ is asserted */
+ __be32 irq_count; /* bits 1-31 count IRQ assertions */
+ __be32 irq_ack; /* acked IRQ count, bit 0 enables IRQ */
+ __be32 next_write_index; /* word index of next write */
+ __be32 next_read_index; /* word index of next read */
+ __be32 error; /* error if any */
+ __be32 oldest_block_index; /* word index of oldest surviving */
+ __be32 requested_rewind; /* how many blocks rewind was done */
+ __be32 reserved_space; /* internal */
+ __be32 min_free; /* min free space since stream start */
+ __be32 blocks_written[2]; /* total blocks written (64 bit) */
+ __be32 words_written[2]; /* total words written (64 bit) */
+};
+
+struct wm_adsp_compr_buf {
+ struct wm_adsp *dsp;
+
+ struct wm_adsp_buffer_region *regions;
+ u32 host_buf_ptr;
+
+ u32 error;
+ u32 irq_count;
+ int read_index;
+ int avail;
+};
+
+struct wm_adsp_compr {
+ struct wm_adsp *dsp;
+ struct wm_adsp_compr_buf *buf;
+
+ struct snd_compr_stream *stream;
+ struct snd_compressed_buffer size;
+
+ u32 *raw_buf;
+ unsigned int copied_total;
+};
+
+#define WM_ADSP_DATA_WORD_SIZE 3
+
+#define WM_ADSP_MIN_FRAGMENTS 1
+#define WM_ADSP_MAX_FRAGMENTS 256
+#define WM_ADSP_MIN_FRAGMENT_SIZE (64 * WM_ADSP_DATA_WORD_SIZE)
+#define WM_ADSP_MAX_FRAGMENT_SIZE (4096 * WM_ADSP_DATA_WORD_SIZE)
+
+#define WM_ADSP_ALG_XM_STRUCT_MAGIC 0x49aec7
+
+#define HOST_BUFFER_FIELD(field) \
+ (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32))
+
+#define ALG_XM_FIELD(field) \
+ (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
+
+static int wm_adsp_buffer_init(struct wm_adsp *dsp);
+static int wm_adsp_buffer_free(struct wm_adsp *dsp);
+
+struct wm_adsp_buffer_region {
+ unsigned int offset;
+ unsigned int cumulative_size;
+ unsigned int mem_type;
+ unsigned int base_addr;
+};
+
+struct wm_adsp_buffer_region_def {
+ unsigned int mem_type;
+ unsigned int base_offset;
+ unsigned int size_offset;
};
-static struct {
+static struct wm_adsp_buffer_region_def ez2control_regions[] = {
+ {
+ .mem_type = WMFW_ADSP2_XM,
+ .base_offset = HOST_BUFFER_FIELD(X_buf_base),
+ .size_offset = HOST_BUFFER_FIELD(X_buf_size),
+ },
+ {
+ .mem_type = WMFW_ADSP2_XM,
+ .base_offset = HOST_BUFFER_FIELD(X_buf_base2),
+ .size_offset = HOST_BUFFER_FIELD(X_buf_brk),
+ },
+ {
+ .mem_type = WMFW_ADSP2_YM,
+ .base_offset = HOST_BUFFER_FIELD(Y_buf_base),
+ .size_offset = HOST_BUFFER_FIELD(wrap),
+ },
+};
+
+struct wm_adsp_fw_caps {
+ u32 id;
+ struct snd_codec_desc desc;
+ int num_regions;
+ struct wm_adsp_buffer_region_def *region_defs;
+};
+
+static const struct wm_adsp_fw_caps ez2control_caps[] = {
+ {
+ .id = SND_AUDIOCODEC_BESPOKE,
+ .desc = {
+ .max_ch = 1,
+ .sample_rates = { 16000 },
+ .num_sample_rates = 1,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .num_regions = ARRAY_SIZE(ez2control_regions),
+ .region_defs = ez2control_regions,
+ },
+};
+
+static const struct {
const char *file;
+ int compr_direction;
+ int num_caps;
+ const struct wm_adsp_fw_caps *caps;
} wm_adsp_fw[WM_ADSP_NUM_FW] = {
- [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" },
- [WM_ADSP_FW_TX] = { .file = "tx" },
- [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" },
- [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" },
+ [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" },
+ [WM_ADSP_FW_HIFI] = { .file = "hifi" },
+ [WM_ADSP_FW_TX] = { .file = "tx" },
+ [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" },
+ [WM_ADSP_FW_RX] = { .file = "rx" },
+ [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" },
+ [WM_ADSP_FW_CTRL] = {
+ .file = "ctrl",
+ .compr_direction = SND_COMPRESS_CAPTURE,
+ .num_caps = ARRAY_SIZE(ez2control_caps),
+ .caps = ez2control_caps,
+ },
+ [WM_ADSP_FW_ASR] = { .file = "asr" },
+ [WM_ADSP_FW_TRACE] = { .file = "trace" },
+ [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
+ [WM_ADSP_FW_MISC] = { .file = "misc" },
};
struct wm_coeff_ctl_ops {
@@ -254,30 +421,24 @@ static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s)
{
char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
- mutex_lock(&dsp->debugfs_lock);
kfree(dsp->wmfw_file_name);
dsp->wmfw_file_name = tmp;
- mutex_unlock(&dsp->debugfs_lock);
}
static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s)
{
char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
- mutex_lock(&dsp->debugfs_lock);
kfree(dsp->bin_file_name);
dsp->bin_file_name = tmp;
- mutex_unlock(&dsp->debugfs_lock);
}
static void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
{
- mutex_lock(&dsp->debugfs_lock);
kfree(dsp->wmfw_file_name);
kfree(dsp->bin_file_name);
dsp->wmfw_file_name = NULL;
dsp->bin_file_name = NULL;
- mutex_unlock(&dsp->debugfs_lock);
}
static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,
@@ -287,7 +448,7 @@ static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,
struct wm_adsp *dsp = file->private_data;
ssize_t ret;
- mutex_lock(&dsp->debugfs_lock);
+ mutex_lock(&dsp->pwr_lock);
if (!dsp->wmfw_file_name || !dsp->running)
ret = 0;
@@ -296,7 +457,7 @@ static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,
dsp->wmfw_file_name,
strlen(dsp->wmfw_file_name));
- mutex_unlock(&dsp->debugfs_lock);
+ mutex_unlock(&dsp->pwr_lock);
return ret;
}
@@ -307,7 +468,7 @@ static ssize_t wm_adsp_debugfs_bin_read(struct file *file,
struct wm_adsp *dsp = file->private_data;
ssize_t ret;
- mutex_lock(&dsp->debugfs_lock);
+ mutex_lock(&dsp->pwr_lock);
if (!dsp->bin_file_name || !dsp->running)
ret = 0;
@@ -316,7 +477,7 @@ static ssize_t wm_adsp_debugfs_bin_read(struct file *file,
dsp->bin_file_name,
strlen(dsp->bin_file_name));
- mutex_unlock(&dsp->debugfs_lock);
+ mutex_unlock(&dsp->pwr_lock);
return ret;
}
@@ -436,6 +597,7 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
if (ucontrol->value.integer.value[0] == dsp[e->shift_l].fw)
return 0;
@@ -443,12 +605,16 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW)
return -EINVAL;
- if (dsp[e->shift_l].running)
- return -EBUSY;
+ mutex_lock(&dsp[e->shift_l].pwr_lock);
- dsp[e->shift_l].fw = ucontrol->value.integer.value[0];
+ if (dsp[e->shift_l].running || dsp[e->shift_l].compr)
+ ret = -EBUSY;
+ else
+ dsp[e->shift_l].fw = ucontrol->value.integer.value[0];
- return 0;
+ mutex_unlock(&dsp[e->shift_l].pwr_lock);
+
+ return ret;
}
static const struct soc_enum wm_adsp_fw_enum[] = {
@@ -523,10 +689,10 @@ static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
be16_to_cpu(scratch[3]));
}
-static int wm_coeff_info(struct snd_kcontrol *kcontrol,
+static int wm_coeff_info(struct snd_kcontrol *kctl,
struct snd_ctl_elem_info *uinfo)
{
- struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
+ struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value;
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
uinfo->count = ctl->len;
@@ -572,19 +738,24 @@ static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
return 0;
}
-static int wm_coeff_put(struct snd_kcontrol *kcontrol,
+static int wm_coeff_put(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *ucontrol)
{
- struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
+ struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value;
char *p = ucontrol->value.bytes.data;
+ int ret = 0;
+
+ mutex_lock(&ctl->dsp->pwr_lock);
memcpy(ctl->cache, p, ctl->len);
ctl->set = 1;
- if (!ctl->enabled)
- return 0;
+ if (ctl->enabled)
+ ret = wm_coeff_write_control(ctl, p, ctl->len);
+
+ mutex_unlock(&ctl->dsp->pwr_lock);
- return wm_coeff_write_control(ctl, p, ctl->len);
+ return ret;
}
static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
@@ -626,22 +797,30 @@ static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
return 0;
}
-static int wm_coeff_get(struct snd_kcontrol *kcontrol,
+static int wm_coeff_get(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *ucontrol)
{
- struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
+ struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value;
char *p = ucontrol->value.bytes.data;
+ int ret = 0;
+
+ mutex_lock(&ctl->dsp->pwr_lock);
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
if (ctl->enabled)
- return wm_coeff_read_control(ctl, p, ctl->len);
+ ret = wm_coeff_read_control(ctl, p, ctl->len);
else
- return -EPERM;
+ ret = -EPERM;
+ } else {
+ if (!ctl->flags && ctl->enabled)
+ ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
+
+ memcpy(p, ctl->cache, ctl->len);
}
- memcpy(p, ctl->cache, ctl->len);
+ mutex_unlock(&ctl->dsp->pwr_lock);
- return 0;
+ return ret;
}
struct wmfw_ctl_work {
@@ -808,8 +987,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
break;
}
- list_for_each_entry(ctl, &dsp->ctl_list,
- list) {
+ list_for_each_entry(ctl, &dsp->ctl_list, list) {
if (!strcmp(ctl->name, name)) {
if (!ctl->enabled)
ctl->enabled = 1;
@@ -1088,7 +1266,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
goto out_fw;
}
- header = (void*)&firmware->data[0];
+ header = (void *)&firmware->data[0];
if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
adsp_err(dsp, "%s: invalid magic\n", file);
@@ -1168,7 +1346,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
offset = le32_to_cpu(region->offset) & 0xffffff;
type = be32_to_cpu(region->type) & 0xff;
mem = wm_adsp_find_region(dsp, type);
-
+
switch (type) {
case WMFW_NAME_TEXT:
region_name = "Firmware name";
@@ -1333,6 +1511,19 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
return alg;
}
+static struct wm_adsp_alg_region *
+ wm_adsp_find_alg_region(struct wm_adsp *dsp, int type, unsigned int id)
+{
+ struct wm_adsp_alg_region *alg_region;
+
+ list_for_each_entry(alg_region, &dsp->alg_regions, list) {
+ if (id == alg_region->alg && type == alg_region->type)
+ return alg_region;
+ }
+
+ return NULL;
+}
+
static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp,
int type, __be32 id,
__be32 base)
@@ -1625,7 +1816,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
goto out_fw;
}
- hdr = (void*)&firmware->data[0];
+ hdr = (void *)&firmware->data[0];
if (memcmp(hdr->magic, "WMDR", 4) != 0) {
adsp_err(dsp, "%s: invalid magic\n", file);
goto out_fw;
@@ -1651,7 +1842,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
blocks = 0;
while (pos < firmware->size &&
pos - firmware->size > sizeof(*blk)) {
- blk = (void*)(&firmware->data[pos]);
+ blk = (void *)(&firmware->data[pos]);
type = le16_to_cpu(blk->type);
offset = le16_to_cpu(blk->offset);
@@ -1705,22 +1896,16 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
break;
}
- reg = 0;
- list_for_each_entry(alg_region,
- &dsp->alg_regions, list) {
- if (le32_to_cpu(blk->id) == alg_region->alg &&
- type == alg_region->type) {
- reg = alg_region->base;
- reg = wm_adsp_region_to_reg(mem,
- reg);
- reg += offset;
- break;
- }
- }
-
- if (reg == 0)
+ alg_region = wm_adsp_find_alg_region(dsp, type,
+ le32_to_cpu(blk->id));
+ if (alg_region) {
+ reg = alg_region->base;
+ reg = wm_adsp_region_to_reg(mem, reg);
+ reg += offset;
+ } else {
adsp_err(dsp, "No %x for algorithm %x\n",
type, le32_to_cpu(blk->id));
+ }
break;
default:
@@ -1778,9 +1963,8 @@ int wm_adsp1_init(struct wm_adsp *dsp)
{
INIT_LIST_HEAD(&dsp->alg_regions);
-#ifdef CONFIG_DEBUG_FS
- mutex_init(&dsp->debugfs_lock);
-#endif
+ mutex_init(&dsp->pwr_lock);
+
return 0;
}
EXPORT_SYMBOL_GPL(wm_adsp1_init);
@@ -1795,10 +1979,12 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct wm_adsp_alg_region *alg_region;
struct wm_coeff_ctl *ctl;
int ret;
- int val;
+ unsigned int val;
dsp->card = codec->component.card;
+ mutex_lock(&dsp->pwr_lock);
+
switch (event) {
case SND_SOC_DAPM_POST_PMU:
regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
@@ -1808,12 +1994,12 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
* For simplicity set the DSP clock rate to be the
* SYSCLK rate rather than making it configurable.
*/
- if(dsp->sysclk_reg) {
+ if (dsp->sysclk_reg) {
ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
if (ret != 0) {
adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
ret);
- return ret;
+ goto err_mutex;
}
val = (val & dsp->sysclk_mask)
@@ -1825,31 +2011,31 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
if (ret != 0) {
adsp_err(dsp, "Failed to set clock rate: %d\n",
ret);
- return ret;
+ goto err_mutex;
}
}
ret = wm_adsp_load(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
ret = wm_adsp1_setup_algs(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
ret = wm_adsp_load_coeff(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
/* Initialize caches for enabled and unset controls */
ret = wm_coeff_init_control_caches(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
/* Sync set controls */
ret = wm_coeff_sync_controls(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
/* Start the core running */
regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
@@ -1884,11 +2070,16 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
break;
}
+ mutex_unlock(&dsp->pwr_lock);
+
return 0;
-err:
+err_ena:
regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
ADSP1_SYS_ENA, 0);
+err_mutex:
+ mutex_unlock(&dsp->pwr_lock);
+
return ret;
}
EXPORT_SYMBOL_GPL(wm_adsp1_event);
@@ -1934,6 +2125,8 @@ static void wm_adsp2_boot_work(struct work_struct *work)
int ret;
unsigned int val;
+ mutex_lock(&dsp->pwr_lock);
+
/*
* For simplicity set the DSP clock rate to be the
* SYSCLK rate rather than making it configurable.
@@ -1941,7 +2134,7 @@ static void wm_adsp2_boot_work(struct work_struct *work)
ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
if (ret != 0) {
adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
- return;
+ goto err_mutex;
}
val = (val & ARIZONA_SYSCLK_FREQ_MASK)
>> ARIZONA_SYSCLK_FREQ_SHIFT;
@@ -1951,42 +2144,46 @@ static void wm_adsp2_boot_work(struct work_struct *work)
ADSP2_CLK_SEL_MASK, val);
if (ret != 0) {
adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
- return;
+ goto err_mutex;
}
ret = wm_adsp2_ena(dsp);
if (ret != 0)
- return;
+ goto err_mutex;
ret = wm_adsp_load(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
ret = wm_adsp2_setup_algs(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
ret = wm_adsp_load_coeff(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
/* Initialize caches for enabled and unset controls */
ret = wm_coeff_init_control_caches(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
/* Sync set controls */
ret = wm_coeff_sync_controls(dsp);
if (ret != 0)
- goto err;
+ goto err_ena;
dsp->running = true;
+ mutex_unlock(&dsp->pwr_lock);
+
return;
-err:
+err_ena:
regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+err_mutex:
+ mutex_unlock(&dsp->pwr_lock);
}
int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
@@ -2033,12 +2230,18 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
ADSP2_CORE_ENA | ADSP2_START);
if (ret != 0)
goto err;
+
+ if (wm_adsp_fw[dsp->fw].num_caps != 0)
+ ret = wm_adsp_buffer_init(dsp);
+
break;
case SND_SOC_DAPM_PRE_PMD:
/* Log firmware state, it can be useful for analysis */
wm_adsp2_show_fw_status(dsp);
+ mutex_lock(&dsp->pwr_lock);
+
wm_adsp_debugfs_clear(dsp);
dsp->fw_id = 0;
@@ -2065,6 +2268,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
kfree(alg_region);
}
+ if (wm_adsp_fw[dsp->fw].num_caps != 0)
+ wm_adsp_buffer_free(dsp);
+
+ mutex_unlock(&dsp->pwr_lock);
+
adsp_dbg(dsp, "Shutdown complete\n");
break;
@@ -2117,11 +2325,724 @@ int wm_adsp2_init(struct wm_adsp *dsp)
INIT_LIST_HEAD(&dsp->ctl_list);
INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work);
-#ifdef CONFIG_DEBUG_FS
- mutex_init(&dsp->debugfs_lock);
-#endif
+ mutex_init(&dsp->pwr_lock);
+
return 0;
}
EXPORT_SYMBOL_GPL(wm_adsp2_init);
+int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
+{
+ struct wm_adsp_compr *compr;
+ int ret = 0;
+
+ mutex_lock(&dsp->pwr_lock);
+
+ if (wm_adsp_fw[dsp->fw].num_caps == 0) {
+ adsp_err(dsp, "Firmware does not support compressed API\n");
+ ret = -ENXIO;
+ goto out;
+ }
+
+ if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) {
+ adsp_err(dsp, "Firmware does not support stream direction\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (dsp->compr) {
+ /* It is expect this limitation will be removed in future */
+ adsp_err(dsp, "Only a single stream supported per DSP\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ compr = kzalloc(sizeof(*compr), GFP_KERNEL);
+ if (!compr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ compr->dsp = dsp;
+ compr->stream = stream;
+
+ dsp->compr = compr;
+
+ stream->runtime->private_data = compr;
+
+out:
+ mutex_unlock(&dsp->pwr_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp_compr_open);
+
+int wm_adsp_compr_free(struct snd_compr_stream *stream)
+{
+ struct wm_adsp_compr *compr = stream->runtime->private_data;
+ struct wm_adsp *dsp = compr->dsp;
+
+ mutex_lock(&dsp->pwr_lock);
+
+ dsp->compr = NULL;
+
+ kfree(compr->raw_buf);
+ kfree(compr);
+
+ mutex_unlock(&dsp->pwr_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp_compr_free);
+
+static int wm_adsp_compr_check_params(struct snd_compr_stream *stream,
+ struct snd_compr_params *params)
+{
+ struct wm_adsp_compr *compr = stream->runtime->private_data;
+ struct wm_adsp *dsp = compr->dsp;
+ const struct wm_adsp_fw_caps *caps;
+ const struct snd_codec_desc *desc;
+ int i, j;
+
+ if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE ||
+ params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE ||
+ params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS ||
+ params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS ||
+ params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) {
+ adsp_err(dsp, "Invalid buffer fragsize=%d fragments=%d\n",
+ params->buffer.fragment_size,
+ params->buffer.fragments);
+
+ return -EINVAL;
+ }
+
+ for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) {
+ caps = &wm_adsp_fw[dsp->fw].caps[i];
+ desc = &caps->desc;
+
+ if (caps->id != params->codec.id)
+ continue;
+
+ if (stream->direction == SND_COMPRESS_PLAYBACK) {
+ if (desc->max_ch < params->codec.ch_out)
+ continue;
+ } else {
+ if (desc->max_ch < params->codec.ch_in)
+ continue;
+ }
+
+ if (!(desc->formats & (1 << params->codec.format)))
+ continue;
+
+ for (j = 0; j < desc->num_sample_rates; ++j)
+ if (desc->sample_rates[j] == params->codec.sample_rate)
+ return 0;
+ }
+
+ adsp_err(dsp, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
+ params->codec.id, params->codec.ch_in, params->codec.ch_out,
+ params->codec.sample_rate, params->codec.format);
+ return -EINVAL;
+}
+
+static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr)
+{
+ return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE;
+}
+
+int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
+ struct snd_compr_params *params)
+{
+ struct wm_adsp_compr *compr = stream->runtime->private_data;
+ unsigned int size;
+ int ret;
+
+ ret = wm_adsp_compr_check_params(stream, params);
+ if (ret)
+ return ret;
+
+ compr->size = params->buffer;
+
+ adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n",
+ compr->size.fragment_size, compr->size.fragments);
+
+ size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf);
+ compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL);
+ if (!compr->raw_buf)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
+
+int wm_adsp_compr_get_caps(struct snd_compr_stream *stream,
+ struct snd_compr_caps *caps)
+{
+ struct wm_adsp_compr *compr = stream->runtime->private_data;
+ int fw = compr->dsp->fw;
+ int i;
+
+ if (wm_adsp_fw[fw].caps) {
+ for (i = 0; i < wm_adsp_fw[fw].num_caps; i++)
+ caps->codecs[i] = wm_adsp_fw[fw].caps[i].id;
+
+ caps->num_codecs = i;
+ caps->direction = wm_adsp_fw[fw].compr_direction;
+
+ caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE;
+ caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE;
+ caps->min_fragments = WM_ADSP_MIN_FRAGMENTS;
+ caps->max_fragments = WM_ADSP_MAX_FRAGMENTS;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
+
+static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type,
+ unsigned int mem_addr,
+ unsigned int num_words, u32 *data)
+{
+ struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
+ unsigned int i, reg;
+ int ret;
+
+ if (!mem)
+ return -EINVAL;
+
+ reg = wm_adsp_region_to_reg(mem, mem_addr);
+
+ ret = regmap_raw_read(dsp->regmap, reg, data,
+ sizeof(*data) * num_words);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < num_words; ++i)
+ data[i] = be32_to_cpu(data[i]) & 0x00ffffffu;
+
+ return 0;
+}
+
+static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type,
+ unsigned int mem_addr, u32 *data)
+{
+ return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data);
+}
+
+static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
+ unsigned int mem_addr, u32 data)
+{
+ struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
+ unsigned int reg;
+
+ if (!mem)
+ return -EINVAL;
+
+ reg = wm_adsp_region_to_reg(mem, mem_addr);
+
+ data = cpu_to_be32(data & 0x00ffffffu);
+
+ return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data));
+}
+
+static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
+ unsigned int field_offset, u32 *data)
+{
+ return wm_adsp_read_data_word(buf->dsp, WMFW_ADSP2_XM,
+ buf->host_buf_ptr + field_offset, data);
+}
+
+static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
+ unsigned int field_offset, u32 data)
+{
+ return wm_adsp_write_data_word(buf->dsp, WMFW_ADSP2_XM,
+ buf->host_buf_ptr + field_offset, data);
+}
+
+static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
+{
+ struct wm_adsp_alg_region *alg_region;
+ struct wm_adsp *dsp = buf->dsp;
+ u32 xmalg, addr, magic;
+ int i, ret;
+
+ alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
+ xmalg = sizeof(struct wm_adsp_system_config_xm_hdr) / sizeof(__be32);
+
+ addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
+ ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic);
+ if (ret < 0)
+ return ret;
+
+ if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC)
+ return -EINVAL;
+
+ addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr);
+ for (i = 0; i < 5; ++i) {
+ ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr,
+ &buf->host_buf_ptr);
+ if (ret < 0)
+ return ret;
+
+ if (buf->host_buf_ptr)
+ break;
+
+ usleep_range(1000, 2000);
+ }
+
+ if (!buf->host_buf_ptr)
+ return -EIO;
+
+ adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr);
+
+ return 0;
+}
+
+static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
+{
+ const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;
+ struct wm_adsp_buffer_region *region;
+ u32 offset = 0;
+ int i, ret;
+
+ for (i = 0; i < caps->num_regions; ++i) {
+ region = &buf->regions[i];
+
+ region->offset = offset;
+ region->mem_type = caps->region_defs[i].mem_type;
+
+ ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset,
+ &region->base_addr);
+ if (ret < 0)
+ return ret;
+
+ ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset,
+ &offset);
+ if (ret < 0)
+ return ret;
+
+ region->cumulative_size = offset;
+
+ adsp_dbg(buf->dsp,
+ "region=%d type=%d base=%04x off=%04x size=%04x\n",
+ i, region->mem_type, region->base_addr,
+ region->offset, region->cumulative_size);
+ }
+
+ return 0;
+}
+
+static int wm_adsp_buffer_init(struct wm_adsp *dsp)
+{
+ struct wm_adsp_compr_buf *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf->dsp = dsp;
+ buf->read_index = -1;
+ buf->irq_count = 0xFFFFFFFF;
+
+ ret = wm_adsp_buffer_locate(buf);
+ if (ret < 0) {
+ adsp_err(dsp, "Failed to acquire host buffer: %d\n", ret);
+ goto err_buffer;
+ }
+
+ buf->regions = kcalloc(wm_adsp_fw[dsp->fw].caps->num_regions,
+ sizeof(*buf->regions), GFP_KERNEL);
+ if (!buf->regions) {
+ ret = -ENOMEM;
+ goto err_buffer;
+ }
+
+ ret = wm_adsp_buffer_populate(buf);
+ if (ret < 0) {
+ adsp_err(dsp, "Failed to populate host buffer: %d\n", ret);
+ goto err_regions;
+ }
+
+ dsp->buffer = buf;
+
+ return 0;
+
+err_regions:
+ kfree(buf->regions);
+err_buffer:
+ kfree(buf);
+ return ret;
+}
+
+static int wm_adsp_buffer_free(struct wm_adsp *dsp)
+{
+ if (dsp->buffer) {
+ kfree(dsp->buffer->regions);
+ kfree(dsp->buffer);
+
+ dsp->buffer = NULL;
+ }
+
+ return 0;
+}
+
+static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr)
+{
+ return compr->buf != NULL;
+}
+
+static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
+{
+ /*
+ * Note this will be more complex once each DSP can support multiple
+ * streams
+ */
+ if (!compr->dsp->buffer)
+ return -EINVAL;
+
+ compr->buf = compr->dsp->buffer;
+
+ return 0;
+}
+
+int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
+{
+ struct wm_adsp_compr *compr = stream->runtime->private_data;
+ struct wm_adsp *dsp = compr->dsp;
+ int ret = 0;
+
+ adsp_dbg(dsp, "Trigger: %d\n", cmd);
+
+ mutex_lock(&dsp->pwr_lock);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ if (wm_adsp_compr_attached(compr))
+ break;
+
+ ret = wm_adsp_compr_attach(compr);
+ if (ret < 0) {
+ adsp_err(dsp, "Failed to link buffer and stream: %d\n",
+ ret);
+ break;
+ }
+
+ /* Trigger the IRQ at one fragment of data */
+ ret = wm_adsp_buffer_write(compr->buf,
+ HOST_BUFFER_FIELD(high_water_mark),
+ wm_adsp_compr_frag_words(compr));
+ if (ret < 0) {
+ adsp_err(dsp, "Failed to set high water mark: %d\n",
+ ret);
+ break;
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&dsp->pwr_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger);
+
+static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf)
+{
+ int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1;
+
+ return buf->regions[last_region].cumulative_size;
+}
+
+static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf)
+{
+ u32 next_read_index, next_write_index;
+ int write_index, read_index, avail;
+ int ret;
+
+ /* Only sync read index if we haven't already read a valid index */
+ if (buf->read_index < 0) {
+ ret = wm_adsp_buffer_read(buf,
+ HOST_BUFFER_FIELD(next_read_index),
+ &next_read_index);
+ if (ret < 0)
+ return ret;
+
+ read_index = sign_extend32(next_read_index, 23);
+
+ if (read_index < 0) {
+ adsp_dbg(buf->dsp, "Avail check on unstarted stream\n");
+ return 0;
+ }
+
+ buf->read_index = read_index;
+ }
+
+ ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index),
+ &next_write_index);
+ if (ret < 0)
+ return ret;
+
+ write_index = sign_extend32(next_write_index, 23);
+
+ avail = write_index - buf->read_index;
+ if (avail < 0)
+ avail += wm_adsp_buffer_size(buf);
+
+ adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
+ buf->read_index, write_index, avail);
+
+ buf->avail = avail;
+
+ return 0;
+}
+
+int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
+{
+ struct wm_adsp_compr_buf *buf = dsp->buffer;
+ struct wm_adsp_compr *compr = dsp->compr;
+ int ret = 0;
+
+ mutex_lock(&dsp->pwr_lock);
+
+ if (!buf) {
+ adsp_err(dsp, "Spurious buffer IRQ\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ adsp_dbg(dsp, "Handling buffer IRQ\n");
+
+ ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
+ if (ret < 0) {
+ adsp_err(dsp, "Failed to check buffer error: %d\n", ret);
+ goto out;
+ }
+ if (buf->error != 0) {
+ adsp_err(dsp, "Buffer error occurred: %d\n", buf->error);
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
+ &buf->irq_count);
+ if (ret < 0) {
+ adsp_err(dsp, "Failed to get irq_count: %d\n", ret);
+ goto out;
+ }
+
+ ret = wm_adsp_buffer_update_avail(buf);
+ if (ret < 0) {
+ adsp_err(dsp, "Error reading avail: %d\n", ret);
+ goto out;
+ }
+
+ if (compr->stream)
+ snd_compr_fragment_elapsed(compr->stream);
+
+out:
+ mutex_unlock(&dsp->pwr_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq);
+
+static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf)
+{
+ if (buf->irq_count & 0x01)
+ return 0;
+
+ adsp_dbg(buf->dsp, "Enable IRQ(0x%x) for next fragment\n",
+ buf->irq_count);
+
+ buf->irq_count |= 0x01;
+
+ return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack),
+ buf->irq_count);
+}
+
+int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
+ struct snd_compr_tstamp *tstamp)
+{
+ struct wm_adsp_compr *compr = stream->runtime->private_data;
+ struct wm_adsp_compr_buf *buf = compr->buf;
+ struct wm_adsp *dsp = compr->dsp;
+ int ret = 0;
+
+ adsp_dbg(dsp, "Pointer request\n");
+
+ mutex_lock(&dsp->pwr_lock);
+
+ if (!compr->buf) {
+ ret = -ENXIO;
+ goto out;
+ }
+
+ if (compr->buf->error) {
+ ret = -EIO;
+ goto out;
+ }
+
+ if (buf->avail < wm_adsp_compr_frag_words(compr)) {
+ ret = wm_adsp_buffer_update_avail(buf);
+ if (ret < 0) {
+ adsp_err(dsp, "Error reading avail: %d\n", ret);
+ goto out;
+ }
+
+ /*
+ * If we really have less than 1 fragment available tell the
+ * DSP to inform us once a whole fragment is available.
+ */
+ if (buf->avail < wm_adsp_compr_frag_words(compr)) {
+ ret = wm_adsp_buffer_reenable_irq(buf);
+ if (ret < 0) {
+ adsp_err(dsp,
+ "Failed to re-enable buffer IRQ: %d\n",
+ ret);
+ goto out;
+ }
+ }
+ }
+
+ tstamp->copied_total = compr->copied_total;
+ tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE;
+
+out:
+ mutex_unlock(&dsp->pwr_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer);
+
+static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
+{
+ struct wm_adsp_compr_buf *buf = compr->buf;
+ u8 *pack_in = (u8 *)compr->raw_buf;
+ u8 *pack_out = (u8 *)compr->raw_buf;
+ unsigned int adsp_addr;
+ int mem_type, nwords, max_read;
+ int i, j, ret;
+
+ /* Calculate read parameters */
+ for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i)
+ if (buf->read_index < buf->regions[i].cumulative_size)
+ break;
+
+ if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions)
+ return -EINVAL;
+
+ mem_type = buf->regions[i].mem_type;
+ adsp_addr = buf->regions[i].base_addr +
+ (buf->read_index - buf->regions[i].offset);
+
+ max_read = wm_adsp_compr_frag_words(compr);
+ nwords = buf->regions[i].cumulative_size - buf->read_index;
+
+ if (nwords > target)
+ nwords = target;
+ if (nwords > buf->avail)
+ nwords = buf->avail;
+ if (nwords > max_read)
+ nwords = max_read;
+ if (!nwords)
+ return 0;
+
+ /* Read data from DSP */
+ ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr,
+ nwords, compr->raw_buf);
+ if (ret < 0)
+ return ret;
+
+ /* Remove the padding bytes from the data read from the DSP */
+ for (i = 0; i < nwords; i++) {
+ for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++)
+ *pack_out++ = *pack_in++;
+
+ pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE;
+ }
+
+ /* update read index to account for words read */
+ buf->read_index += nwords;
+ if (buf->read_index == wm_adsp_buffer_size(buf))
+ buf->read_index = 0;
+
+ ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index),
+ buf->read_index);
+ if (ret < 0)
+ return ret;
+
+ /* update avail to account for words read */
+ buf->avail -= nwords;
+
+ return nwords;
+}
+
+static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
+ char __user *buf, size_t count)
+{
+ struct wm_adsp *dsp = compr->dsp;
+ int ntotal = 0;
+ int nwords, nbytes;
+
+ adsp_dbg(dsp, "Requested read of %zu bytes\n", count);
+
+ if (!compr->buf)
+ return -ENXIO;
+
+ if (compr->buf->error)
+ return -EIO;
+
+ count /= WM_ADSP_DATA_WORD_SIZE;
+
+ do {
+ nwords = wm_adsp_buffer_capture_block(compr, count);
+ if (nwords < 0) {
+ adsp_err(dsp, "Failed to capture block: %d\n", nwords);
+ return nwords;
+ }
+
+ nbytes = nwords * WM_ADSP_DATA_WORD_SIZE;
+
+ adsp_dbg(dsp, "Read %d bytes\n", nbytes);
+
+ if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) {
+ adsp_err(dsp, "Failed to copy data to user: %d, %d\n",
+ ntotal, nbytes);
+ return -EFAULT;
+ }
+
+ count -= nwords;
+ ntotal += nbytes;
+ } while (nwords > 0 && count > 0);
+
+ compr->copied_total += ntotal;
+
+ return ntotal;
+}
+
+int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf,
+ size_t count)
+{
+ struct wm_adsp_compr *compr = stream->runtime->private_data;
+ struct wm_adsp *dsp = compr->dsp;
+ int ret;
+
+ mutex_lock(&dsp->pwr_lock);
+
+ if (stream->direction == SND_COMPRESS_CAPTURE)
+ ret = wm_adsp_compr_read(compr, buf, count);
+ else
+ ret = -ENOTSUPP;
+
+ mutex_unlock(&dsp->pwr_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp_compr_copy);
+
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index 2d117cf0e953..1a928ec54741 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -15,6 +15,7 @@
#include <sound/soc.h>
#include <sound/soc-dapm.h>
+#include <sound/compress_driver.h>
#include "wmfw.h"
@@ -30,6 +31,9 @@ struct wm_adsp_alg_region {
unsigned int base;
};
+struct wm_adsp_compr;
+struct wm_adsp_compr_buf;
+
struct wm_adsp {
const char *part;
int num;
@@ -45,8 +49,8 @@ struct wm_adsp {
struct list_head alg_regions;
- int fw_id;
- int fw_id_version;
+ unsigned int fw_id;
+ unsigned int fw_id_version;
const struct wm_adsp_region *mem;
int num_mems;
@@ -59,9 +63,13 @@ struct wm_adsp {
struct work_struct boot_work;
+ struct wm_adsp_compr *compr;
+ struct wm_adsp_compr_buf *buffer;
+
+ struct mutex pwr_lock;
+
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_root;
- struct mutex debugfs_lock;
char *wmfw_file_name;
char *bin_file_name;
#endif
@@ -96,4 +104,18 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
int wm_adsp2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
+extern int wm_adsp_compr_open(struct wm_adsp *dsp,
+ struct snd_compr_stream *stream);
+extern int wm_adsp_compr_free(struct snd_compr_stream *stream);
+extern int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
+ struct snd_compr_params *params);
+extern int wm_adsp_compr_get_caps(struct snd_compr_stream *stream,
+ struct snd_compr_caps *caps);
+extern int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd);
+extern int wm_adsp_compr_handle_irq(struct wm_adsp *dsp);
+extern int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
+ struct snd_compr_tstamp *tstamp);
+extern int wm_adsp_compr_copy(struct snd_compr_stream *stream,
+ char __user *buf, size_t count);
+
#endif
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index 6e6a70c5c2bd..ce664c239be3 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
#include <sound/designware_i2s.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -93,7 +94,12 @@ struct dw_i2s_dev {
struct clk *clk;
int active;
unsigned int capability;
+ unsigned int quirks;
+ unsigned int i2s_reg_comp1;
+ unsigned int i2s_reg_comp2;
struct device *dev;
+ u32 ccr;
+ u32 xfer_resolution;
/* data related to DMA transfers b/w i2s and DMAC */
union dw_i2s_snd_dma_data play_dma_data;
@@ -213,31 +219,58 @@ static int dw_i2s_startup(struct snd_pcm_substream *substream,
return 0;
}
+static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
+{
+ u32 ch_reg, irq;
+ struct i2s_clk_config_data *config = &dev->config;
+
+
+ i2s_disable_channels(dev, stream);
+
+ for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) {
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ i2s_write_reg(dev->i2s_base, TCR(ch_reg),
+ dev->xfer_resolution);
+ i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
+ irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
+ i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
+ i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
+ } else {
+ i2s_write_reg(dev->i2s_base, RCR(ch_reg),
+ dev->xfer_resolution);
+ i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
+ irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
+ i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
+ i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
+ }
+
+ }
+}
+
static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
struct i2s_clk_config_data *config = &dev->config;
- u32 ccr, xfer_resolution, ch_reg, irq;
int ret;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
config->data_width = 16;
- ccr = 0x00;
- xfer_resolution = 0x02;
+ dev->ccr = 0x00;
+ dev->xfer_resolution = 0x02;
break;
case SNDRV_PCM_FORMAT_S24_LE:
config->data_width = 24;
- ccr = 0x08;
- xfer_resolution = 0x04;
+ dev->ccr = 0x08;
+ dev->xfer_resolution = 0x04;
break;
case SNDRV_PCM_FORMAT_S32_LE:
config->data_width = 32;
- ccr = 0x10;
- xfer_resolution = 0x05;
+ dev->ccr = 0x10;
+ dev->xfer_resolution = 0x05;
break;
default:
@@ -258,27 +291,9 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- i2s_disable_channels(dev, substream->stream);
-
- for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) {
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- i2s_write_reg(dev->i2s_base, TCR(ch_reg),
- xfer_resolution);
- i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
- irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
- i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
- i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
- } else {
- i2s_write_reg(dev->i2s_base, RCR(ch_reg),
- xfer_resolution);
- i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
- irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
- i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
- i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
- }
- }
+ dw_i2s_config(dev, substream->stream);
- i2s_write_reg(dev->i2s_base, CCR, ccr);
+ i2s_write_reg(dev->i2s_base, CCR, dev->ccr);
config->sample_rate = params_rate(params);
@@ -394,6 +409,23 @@ static const struct snd_soc_component_driver dw_i2s_component = {
};
#ifdef CONFIG_PM
+static int dw_i2s_runtime_suspend(struct device *dev)
+{
+ struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev);
+
+ if (dw_dev->capability & DW_I2S_MASTER)
+ clk_disable(dw_dev->clk);
+ return 0;
+}
+
+static int dw_i2s_runtime_resume(struct device *dev)
+{
+ struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev);
+
+ if (dw_dev->capability & DW_I2S_MASTER)
+ clk_enable(dw_dev->clk);
+ return 0;
+}
static int dw_i2s_suspend(struct snd_soc_dai *dai)
{
@@ -410,6 +442,11 @@ static int dw_i2s_resume(struct snd_soc_dai *dai)
if (dev->capability & DW_I2S_MASTER)
clk_enable(dev->clk);
+
+ if (dai->playback_active)
+ dw_i2s_config(dev, SNDRV_PCM_STREAM_PLAYBACK);
+ if (dai->capture_active)
+ dw_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE);
return 0;
}
@@ -459,10 +496,14 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
* Read component parameter registers to extract
* the I2S block's configuration.
*/
- u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1);
- u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2);
+ u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1);
+ u32 comp2 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp2);
u32 idx;
+ if (dev->capability & DWC_I2S_RECORD &&
+ dev->quirks & DW_I2S_QUIRK_COMP_PARAM1)
+ comp1 = comp1 & ~BIT(5);
+
if (COMP1_TX_ENABLED(comp1)) {
dev_dbg(dev->dev, " designware: play supported\n");
idx = COMP1_TX_WORDSIZE_0(comp1);
@@ -503,7 +544,7 @@ static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev,
struct resource *res,
const struct i2s_platform_data *pdata)
{
- u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1);
+ u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1);
u32 idx = COMP1_APB_DATA_WIDTH(comp1);
int ret;
@@ -607,6 +648,14 @@ static int dw_i2s_probe(struct platform_device *pdev)
if (pdata) {
dev->capability = pdata->cap;
clk_id = NULL;
+ dev->quirks = pdata->quirks;
+ if (dev->quirks & DW_I2S_QUIRK_COMP_REG_OFFSET) {
+ dev->i2s_reg_comp1 = pdata->i2s_reg_comp1;
+ dev->i2s_reg_comp2 = pdata->i2s_reg_comp2;
+ } else {
+ dev->i2s_reg_comp1 = I2S_COMP_PARAM_1;
+ dev->i2s_reg_comp2 = I2S_COMP_PARAM_2;
+ }
ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata);
} else {
clk_id = "i2sclk";
@@ -649,7 +698,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
goto err_clk_disable;
}
}
-
+ pm_runtime_enable(&pdev->dev);
return 0;
err_clk_disable:
@@ -665,6 +714,7 @@ static int dw_i2s_remove(struct platform_device *pdev)
if (dev->capability & DW_I2S_MASTER)
clk_disable_unprepare(dev->clk);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
@@ -677,12 +727,17 @@ static const struct of_device_id dw_i2s_of_match[] = {
MODULE_DEVICE_TABLE(of, dw_i2s_of_match);
#endif
+static const struct dev_pm_ops dwc_pm_ops = {
+ SET_RUNTIME_PM_OPS(dw_i2s_runtime_suspend, dw_i2s_runtime_resume, NULL)
+};
+
static struct platform_driver dw_i2s_driver = {
.probe = dw_i2s_probe,
.remove = dw_i2s_remove,
.driver = {
.name = "designware-i2s",
.of_match_table = of_match_ptr(dw_i2s_of_match),
+ .pm = &dwc_pm_ops,
},
};
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 1b05d1c5d9fd..562b3bd22d9a 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -107,6 +107,13 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"CPU-Capture", NULL, "Capture"},
};
+static const struct snd_soc_dapm_route audio_map_ac97[] = {
+ {"AC97 Playback", NULL, "ASRC-Playback"},
+ {"Playback", NULL, "AC97 Playback"},
+ {"ASRC-Capture", NULL, "AC97 Capture"},
+ {"AC97 Capture", NULL, "Capture"},
+};
+
/* Add all possible widgets into here without being redundant */
static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = {
SND_SOC_DAPM_LINE("Line Out Jack", NULL),
@@ -222,12 +229,15 @@ static int fsl_asoc_card_set_bias_level(struct snd_soc_card *card,
enum snd_soc_bias_level level)
{
struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
struct codec_priv *codec_priv = &priv->codec_priv;
struct device *dev = card->dev;
unsigned int pll_out;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec_dai = rtd->codec_dai;
if (dapm->dev != codec_dai->dev)
return 0;
@@ -414,14 +424,16 @@ static int fsl_asoc_card_audmux_init(struct device_node *np,
static int fsl_asoc_card_late_probe(struct snd_soc_card *card)
{
struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_pcm_runtime *rtd = list_first_entry(
+ &card->rtd_list, struct snd_soc_pcm_runtime, list);
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct codec_priv *codec_priv = &priv->codec_priv;
struct device *dev = card->dev;
int ret;
if (fsl_asoc_card_is_ac97(priv)) {
#if IS_ENABLED(CONFIG_SND_AC97_CODEC)
- struct snd_soc_codec *codec = card->rtd[0].codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
/*
@@ -574,7 +586,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
priv->card.dev = &pdev->dev;
priv->card.name = priv->name;
priv->card.dai_link = priv->dai_link;
- priv->card.dapm_routes = audio_map;
+ priv->card.dapm_routes = fsl_asoc_card_is_ac97(priv) ?
+ audio_map_ac97 : audio_map;
priv->card.late_probe = fsl_asoc_card_late_probe;
priv->card.num_dapm_routes = ARRAY_SIZE(audio_map);
priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets;
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 9f087d4f73ed..c1a0e01cb8e7 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -31,21 +31,21 @@
dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
/* Sample rates are aligned with that defined in pcm.h file */
-static const u8 process_option[][8][2] = {
- /* 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */
- {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */
- {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */
- {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */
- {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */
- {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */
- {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */
- {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */
- {{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */
- {{1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */
- {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */
- {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */
- {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */
- {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */
+static const u8 process_option[][12][2] = {
+ /* 8kHz 11.025kHz 16kHz 22.05kHz 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */
+ {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */
+ {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */
+ {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */
+ {{1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */
+ {{1, 2}, {1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */
+ {{1, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */
+ {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */
+ {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */
+ {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */
+ {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */
+ {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */
+ {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */
+ {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */
};
/* Corresponding to process_option */
@@ -55,7 +55,7 @@ static int supported_input_rate[] = {
};
static int supported_asrc_rate[] = {
- 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
+ 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000,
};
/**
@@ -286,6 +286,13 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
return -EINVAL;
}
+ if ((outrate > 8000 && outrate < 30000) &&
+ (outrate/inrate > 24 || inrate/outrate > 8)) {
+ pair_err("exceed supported ratio range [1/24, 8] for \
+ inrate/outrate: %d/%d\n", inrate, outrate);
+ return -EINVAL;
+ }
+
/* Validate input and output clock sources */
clk_index[IN] = clk_map[IN][config->inclk];
clk_index[OUT] = clk_map[OUT][config->outclk];
@@ -447,7 +454,7 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
- int width = snd_pcm_format_width(params_format(params));
+ int width = params_width(params);
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
unsigned int channels = params_channels(params);
@@ -859,6 +866,10 @@ static int fsl_asrc_probe(struct platform_device *pdev)
return PTR_ERR(asrc_priv->ipg_clk);
}
+ asrc_priv->spba_clk = devm_clk_get(&pdev->dev, "spba");
+ if (IS_ERR(asrc_priv->spba_clk))
+ dev_warn(&pdev->dev, "failed to get spba clock\n");
+
for (i = 0; i < ASRC_CLK_MAX_NUM; i++) {
sprintf(tmp, "asrck_%x", i);
asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp);
@@ -939,6 +950,11 @@ static int fsl_asrc_runtime_resume(struct device *dev)
ret = clk_prepare_enable(asrc_priv->ipg_clk);
if (ret)
goto disable_mem_clk;
+ if (!IS_ERR(asrc_priv->spba_clk)) {
+ ret = clk_prepare_enable(asrc_priv->spba_clk);
+ if (ret)
+ goto disable_ipg_clk;
+ }
for (i = 0; i < ASRC_CLK_MAX_NUM; i++) {
ret = clk_prepare_enable(asrc_priv->asrck_clk[i]);
if (ret)
@@ -950,6 +966,9 @@ static int fsl_asrc_runtime_resume(struct device *dev)
disable_asrck_clk:
for (i--; i >= 0; i--)
clk_disable_unprepare(asrc_priv->asrck_clk[i]);
+ if (!IS_ERR(asrc_priv->spba_clk))
+ clk_disable_unprepare(asrc_priv->spba_clk);
+disable_ipg_clk:
clk_disable_unprepare(asrc_priv->ipg_clk);
disable_mem_clk:
clk_disable_unprepare(asrc_priv->mem_clk);
@@ -963,6 +982,8 @@ static int fsl_asrc_runtime_suspend(struct device *dev)
for (i = 0; i < ASRC_CLK_MAX_NUM; i++)
clk_disable_unprepare(asrc_priv->asrck_clk[i]);
+ if (!IS_ERR(asrc_priv->spba_clk))
+ clk_disable_unprepare(asrc_priv->spba_clk);
clk_disable_unprepare(asrc_priv->ipg_clk);
clk_disable_unprepare(asrc_priv->mem_clk);
@@ -975,6 +996,9 @@ static int fsl_asrc_suspend(struct device *dev)
{
struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
+ regmap_read(asrc_priv->regmap, REG_ASRCFG,
+ &asrc_priv->regcache_cfg);
+
regcache_cache_only(asrc_priv->regmap, true);
regcache_mark_dirty(asrc_priv->regmap);
@@ -995,6 +1019,10 @@ static int fsl_asrc_resume(struct device *dev)
regcache_cache_only(asrc_priv->regmap, false);
regcache_sync(asrc_priv->regmap);
+ regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
+ ASRCFG_NDPRi_ALL_MASK | ASRCFG_POSTMODi_ALL_MASK |
+ ASRCFG_PREMODi_ALL_MASK, asrc_priv->regcache_cfg);
+
/* Restart enabled pairs */
regmap_update_bits(asrc_priv->regmap, REG_ASRCTR,
ASRCTR_ASRCEi_ALL_MASK, asrctr);
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h
index 4aed63c4b431..0f163abe4ba3 100644
--- a/sound/soc/fsl/fsl_asrc.h
+++ b/sound/soc/fsl/fsl_asrc.h
@@ -132,10 +132,13 @@
#define ASRCFG_INIRQi (1 << ASRCFG_INIRQi_SHIFT(i))
#define ASRCFG_NDPRi_SHIFT(i) (18 + i)
#define ASRCFG_NDPRi_MASK(i) (1 << ASRCFG_NDPRi_SHIFT(i))
+#define ASRCFG_NDPRi_ALL_SHIFT 18
+#define ASRCFG_NDPRi_ALL_MASK (7 << ASRCFG_NDPRi_ALL_SHIFT)
#define ASRCFG_NDPRi (1 << ASRCFG_NDPRi_SHIFT(i))
#define ASRCFG_POSTMODi_SHIFT(i) (8 + (i << 2))
#define ASRCFG_POSTMODi_WIDTH 2
#define ASRCFG_POSTMODi_MASK(i) (((1 << ASRCFG_POSTMODi_WIDTH) - 1) << ASRCFG_POSTMODi_SHIFT(i))
+#define ASRCFG_POSTMODi_ALL_MASK (ASRCFG_POSTMODi_MASK(0) | ASRCFG_POSTMODi_MASK(1) | ASRCFG_POSTMODi_MASK(2))
#define ASRCFG_POSTMOD(i, v) ((v) << ASRCFG_POSTMODi_SHIFT(i))
#define ASRCFG_POSTMODi_UP(i) (0 << ASRCFG_POSTMODi_SHIFT(i))
#define ASRCFG_POSTMODi_DCON(i) (1 << ASRCFG_POSTMODi_SHIFT(i))
@@ -143,6 +146,7 @@
#define ASRCFG_PREMODi_SHIFT(i) (6 + (i << 2))
#define ASRCFG_PREMODi_WIDTH 2
#define ASRCFG_PREMODi_MASK(i) (((1 << ASRCFG_PREMODi_WIDTH) - 1) << ASRCFG_PREMODi_SHIFT(i))
+#define ASRCFG_PREMODi_ALL_MASK (ASRCFG_PREMODi_MASK(0) | ASRCFG_PREMODi_MASK(1) | ASRCFG_PREMODi_MASK(2))
#define ASRCFG_PREMOD(i, v) ((v) << ASRCFG_PREMODi_SHIFT(i))
#define ASRCFG_PREMODi_UP(i) (0 << ASRCFG_PREMODi_SHIFT(i))
#define ASRCFG_PREMODi_DCON(i) (1 << ASRCFG_PREMODi_SHIFT(i))
@@ -426,6 +430,7 @@ struct fsl_asrc_pair {
* @paddr: physical address to the base address of registers
* @mem_clk: clock source to access register
* @ipg_clk: clock source to drive peripheral
+ * @spba_clk: SPBA clock (optional, depending on SoC design)
* @asrck_clk: clock sources to driver ASRC internal logic
* @lock: spin lock for resource protection
* @pair: pair pointers
@@ -433,6 +438,7 @@ struct fsl_asrc_pair {
* @channel_avail: non-occupied channel numbers
* @asrc_rate: default sample rate for ASoC Back-Ends
* @asrc_width: default sample width for ASoC Back-Ends
+ * @regcache_cfg: store register value of REG_ASRCFG
*/
struct fsl_asrc {
struct snd_dmaengine_dai_dma_data dma_params_rx;
@@ -442,6 +448,7 @@ struct fsl_asrc {
unsigned long paddr;
struct clk *mem_clk;
struct clk *ipg_clk;
+ struct clk *spba_clk;
struct clk *asrck_clk[ASRC_CLK_MAX_NUM];
spinlock_t lock;
@@ -451,6 +458,8 @@ struct fsl_asrc {
int asrc_rate;
int asrc_width;
+
+ u32 regcache_cfg;
};
extern struct snd_soc_platform_driver fsl_asrc_platform;
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 59f234e51971..26a90e12ede4 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -35,6 +35,7 @@
* @coreclk: clock source to access register
* @extalclk: esai clock source to derive HCK, SCK and FS
* @fsysclk: system clock source to derive HCK, SCK and FS
+ * @spbaclk: SPBA clock (optional, depending on SoC design)
* @fifo_depth: depth of tx/rx FIFO
* @slot_width: width of each DAI slot
* @slots: number of slots
@@ -54,6 +55,7 @@ struct fsl_esai {
struct clk *coreclk;
struct clk *extalclk;
struct clk *fsysclk;
+ struct clk *spbaclk;
u32 fifo_depth;
u32 slot_width;
u32 slots;
@@ -469,6 +471,11 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
ret = clk_prepare_enable(esai_priv->coreclk);
if (ret)
return ret;
+ if (!IS_ERR(esai_priv->spbaclk)) {
+ ret = clk_prepare_enable(esai_priv->spbaclk);
+ if (ret)
+ goto err_spbaclk;
+ }
if (!IS_ERR(esai_priv->extalclk)) {
ret = clk_prepare_enable(esai_priv->extalclk);
if (ret)
@@ -499,6 +506,9 @@ err_fsysclk:
if (!IS_ERR(esai_priv->extalclk))
clk_disable_unprepare(esai_priv->extalclk);
err_extalck:
+ if (!IS_ERR(esai_priv->spbaclk))
+ clk_disable_unprepare(esai_priv->spbaclk);
+err_spbaclk:
clk_disable_unprepare(esai_priv->coreclk);
return ret;
@@ -510,7 +520,7 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
{
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- u32 width = snd_pcm_format_width(params_format(params));
+ u32 width = params_width(params);
u32 channels = params_channels(params);
u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
u32 slot_width = width;
@@ -564,6 +574,8 @@ static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
clk_disable_unprepare(esai_priv->fsysclk);
if (!IS_ERR(esai_priv->extalclk))
clk_disable_unprepare(esai_priv->extalclk);
+ if (!IS_ERR(esai_priv->spbaclk))
+ clk_disable_unprepare(esai_priv->spbaclk);
clk_disable_unprepare(esai_priv->coreclk);
}
@@ -653,21 +665,28 @@ static const struct snd_soc_component_driver fsl_esai_component = {
};
static const struct reg_default fsl_esai_reg_defaults[] = {
- {0x8, 0x00000000},
- {0x10, 0x00000000},
- {0x18, 0x00000000},
- {0x98, 0x00000000},
- {0xd0, 0x00000000},
- {0xd4, 0x00000000},
- {0xd8, 0x00000000},
- {0xdc, 0x00000000},
- {0xe0, 0x00000000},
- {0xe4, 0x0000ffff},
- {0xe8, 0x0000ffff},
- {0xec, 0x0000ffff},
- {0xf0, 0x0000ffff},
- {0xf8, 0x00000000},
- {0xfc, 0x00000000},
+ {REG_ESAI_ETDR, 0x00000000},
+ {REG_ESAI_ECR, 0x00000000},
+ {REG_ESAI_TFCR, 0x00000000},
+ {REG_ESAI_RFCR, 0x00000000},
+ {REG_ESAI_TX0, 0x00000000},
+ {REG_ESAI_TX1, 0x00000000},
+ {REG_ESAI_TX2, 0x00000000},
+ {REG_ESAI_TX3, 0x00000000},
+ {REG_ESAI_TX4, 0x00000000},
+ {REG_ESAI_TX5, 0x00000000},
+ {REG_ESAI_TSR, 0x00000000},
+ {REG_ESAI_SAICR, 0x00000000},
+ {REG_ESAI_TCR, 0x00000000},
+ {REG_ESAI_TCCR, 0x00000000},
+ {REG_ESAI_RCR, 0x00000000},
+ {REG_ESAI_RCCR, 0x00000000},
+ {REG_ESAI_TSMA, 0x0000ffff},
+ {REG_ESAI_TSMB, 0x0000ffff},
+ {REG_ESAI_RSMA, 0x0000ffff},
+ {REG_ESAI_RSMB, 0x0000ffff},
+ {REG_ESAI_PRRC, 0x00000000},
+ {REG_ESAI_PCRC, 0x00000000},
};
static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg)
@@ -705,17 +724,10 @@ static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg)
static bool fsl_esai_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
- case REG_ESAI_ETDR:
case REG_ESAI_ERDR:
case REG_ESAI_ESR:
case REG_ESAI_TFSR:
case REG_ESAI_RFSR:
- case REG_ESAI_TX0:
- case REG_ESAI_TX1:
- case REG_ESAI_TX2:
- case REG_ESAI_TX3:
- case REG_ESAI_TX4:
- case REG_ESAI_TX5:
case REG_ESAI_RX0:
case REG_ESAI_RX1:
case REG_ESAI_RX2:
@@ -819,6 +831,11 @@ static int fsl_esai_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n",
PTR_ERR(esai_priv->fsysclk));
+ esai_priv->spbaclk = devm_clk_get(&pdev->dev, "spba");
+ if (IS_ERR(esai_priv->spbaclk))
+ dev_warn(&pdev->dev, "failed to get spba clock: %ld\n",
+ PTR_ERR(esai_priv->spbaclk));
+
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 08b460ba06ef..fef264d27fd3 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -126,6 +126,17 @@ out:
return IRQ_HANDLED;
}
+static int fsl_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
+ u32 rx_mask, int slots, int slot_width)
+{
+ struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+
+ sai->slots = slots;
+ sai->slot_width = slot_width;
+
+ return 0;
+}
+
static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int fsl_dir)
{
@@ -354,13 +365,25 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
return -EINVAL;
}
- if ((tx && sai->synchronous[TX]) || (!tx && !sai->synchronous[RX])) {
+ /*
+ * 1) For Asynchronous mode, we must set RCR2 register for capture, and
+ * set TCR2 register for playback.
+ * 2) For Tx sync with Rx clock, we must set RCR2 register for playback
+ * and capture.
+ * 3) For Rx sync with Tx clock, we must set TCR2 register for playback
+ * and capture.
+ * 4) For Tx and Rx are both Synchronous with another SAI, we just
+ * ignore it.
+ */
+ if ((sai->synchronous[TX] && !sai->synchronous[RX]) ||
+ (!tx && !sai->synchronous[RX])) {
regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
FSL_SAI_CR2_MSEL_MASK,
FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
FSL_SAI_CR2_DIV_MASK, savediv - 1);
- } else {
+ } else if ((sai->synchronous[RX] && !sai->synchronous[TX]) ||
+ (tx && !sai->synchronous[TX])) {
regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
FSL_SAI_CR2_MSEL_MASK,
FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
@@ -381,13 +404,21 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
unsigned int channels = params_channels(params);
- u32 word_width = snd_pcm_format_width(params_format(params));
+ u32 word_width = params_width(params);
u32 val_cr4 = 0, val_cr5 = 0;
+ u32 slots = (channels == 1) ? 2 : channels;
+ u32 slot_width = word_width;
int ret;
+ if (sai->slots)
+ slots = sai->slots;
+
+ if (sai->slot_width)
+ slot_width = sai->slot_width;
+
if (!sai->is_slave_mode) {
ret = fsl_sai_set_bclk(cpu_dai, tx,
- 2 * word_width * params_rate(params));
+ slots * slot_width * params_rate(params));
if (ret)
return ret;
@@ -399,21 +430,49 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
sai->mclk_streams |= BIT(substream->stream);
}
-
}
if (!sai->is_dsp_mode)
- val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
+ val_cr4 |= FSL_SAI_CR4_SYWD(slot_width);
- val_cr5 |= FSL_SAI_CR5_WNW(word_width);
- val_cr5 |= FSL_SAI_CR5_W0W(word_width);
+ val_cr5 |= FSL_SAI_CR5_WNW(slot_width);
+ val_cr5 |= FSL_SAI_CR5_W0W(slot_width);
if (sai->is_lsb_first)
val_cr5 |= FSL_SAI_CR5_FBT(0);
else
val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
- val_cr4 |= FSL_SAI_CR4_FRSZ(channels);
+ val_cr4 |= FSL_SAI_CR4_FRSZ(slots);
+
+ /*
+ * For SAI master mode, when Tx(Rx) sync with Rx(Tx) clock, Rx(Tx) will
+ * generate bclk and frame clock for Tx(Rx), we should set RCR4(TCR4),
+ * RCR5(TCR5) and RMR(TMR) for playback(capture), or there will be sync
+ * error.
+ */
+
+ if (!sai->is_slave_mode) {
+ if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR4,
+ FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
+ val_cr4);
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR5,
+ FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
+ FSL_SAI_CR5_FBT_MASK, val_cr5);
+ regmap_write(sai->regmap, FSL_SAI_TMR,
+ ~0UL - ((1 << channels) - 1));
+ } else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR4,
+ FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
+ val_cr4);
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR5,
+ FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
+ FSL_SAI_CR5_FBT_MASK, val_cr5);
+ regmap_write(sai->regmap, FSL_SAI_RMR,
+ ~0UL - ((1 << channels) - 1));
+ }
+ }
regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
@@ -569,6 +628,7 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
.set_sysclk = fsl_sai_set_dai_sysclk,
.set_fmt = fsl_sai_set_dai_fmt,
+ .set_tdm_slot = fsl_sai_set_dai_tdm_slot,
.hw_params = fsl_sai_hw_params,
.hw_free = fsl_sai_hw_free,
.trigger = fsl_sai_trigger,
@@ -627,6 +687,22 @@ static const struct snd_soc_component_driver fsl_component = {
.name = "fsl-sai",
};
+static struct reg_default fsl_sai_reg_defaults[] = {
+ {FSL_SAI_TCR1, 0},
+ {FSL_SAI_TCR2, 0},
+ {FSL_SAI_TCR3, 0},
+ {FSL_SAI_TCR4, 0},
+ {FSL_SAI_TCR5, 0},
+ {FSL_SAI_TDR, 0},
+ {FSL_SAI_TMR, 0},
+ {FSL_SAI_RCR1, 0},
+ {FSL_SAI_RCR2, 0},
+ {FSL_SAI_RCR3, 0},
+ {FSL_SAI_RCR4, 0},
+ {FSL_SAI_RCR5, 0},
+ {FSL_SAI_RMR, 0},
+};
+
static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -660,13 +736,11 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
case FSL_SAI_RCSR:
case FSL_SAI_TFR:
case FSL_SAI_RFR:
- case FSL_SAI_TDR:
case FSL_SAI_RDR:
return true;
default:
return false;
}
-
}
static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
@@ -699,6 +773,8 @@ static const struct regmap_config fsl_sai_regmap_config = {
.val_bits = 32,
.max_register = FSL_SAI_RMR,
+ .reg_defaults = fsl_sai_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults),
.readable_reg = fsl_sai_readable_reg,
.volatile_reg = fsl_sai_volatile_reg,
.writeable_reg = fsl_sai_writeable_reg,
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index b95fbc3f68eb..d9ed7be8cb34 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -143,6 +143,9 @@ struct fsl_sai {
unsigned int mclk_id[2];
unsigned int mclk_streams;
+ unsigned int slots;
+ unsigned int slot_width;
+
struct snd_dmaengine_dai_dma_data dma_params_rx;
struct snd_dmaengine_dai_dma_data dma_params_tx;
};
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 3d59bb6719f2..151849f79863 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -88,6 +88,7 @@ struct spdif_mixer_control {
* @rxclk: rx clock sources for capture
* @coreclk: core clock for register access via DMA
* @sysclk: system clock for rx clock rate measurement
+ * @spbaclk: SPBA clock (optional, depending on SoC design)
* @dma_params_tx: DMA parameters for transmit channel
* @dma_params_rx: DMA parameters for receive channel
*/
@@ -106,6 +107,7 @@ struct fsl_spdif_priv {
struct clk *rxclk;
struct clk *coreclk;
struct clk *sysclk;
+ struct clk *spbaclk;
struct snd_dmaengine_dai_dma_data dma_params_tx;
struct snd_dmaengine_dai_dma_data dma_params_rx;
/* regcache for SRPC */
@@ -474,6 +476,14 @@ static int fsl_spdif_startup(struct snd_pcm_substream *substream,
return ret;
}
+ if (!IS_ERR(spdif_priv->spbaclk)) {
+ ret = clk_prepare_enable(spdif_priv->spbaclk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable spba clock\n");
+ goto err_spbaclk;
+ }
+ }
+
ret = spdif_softreset(spdif_priv);
if (ret) {
dev_err(&pdev->dev, "failed to soft reset\n");
@@ -515,6 +525,9 @@ disable_txclk:
for (i--; i >= 0; i--)
clk_disable_unprepare(spdif_priv->txclk[i]);
err:
+ if (!IS_ERR(spdif_priv->spbaclk))
+ clk_disable_unprepare(spdif_priv->spbaclk);
+err_spbaclk:
clk_disable_unprepare(spdif_priv->coreclk);
return ret;
@@ -548,6 +561,8 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream,
spdif_intr_status_clear(spdif_priv);
regmap_update_bits(regmap, REG_SPDIF_SCR,
SCR_LOW_POWER, SCR_LOW_POWER);
+ if (!IS_ERR(spdif_priv->spbaclk))
+ clk_disable_unprepare(spdif_priv->spbaclk);
clk_disable_unprepare(spdif_priv->coreclk);
}
}
@@ -1006,12 +1021,14 @@ static const struct snd_soc_component_driver fsl_spdif_component = {
/* FSL SPDIF REGMAP */
static const struct reg_default fsl_spdif_reg_defaults[] = {
- {0x0, 0x00000400},
- {0x4, 0x00000000},
- {0xc, 0x00000000},
- {0x34, 0x00000000},
- {0x38, 0x00000000},
- {0x50, 0x00020f00},
+ {REG_SPDIF_SCR, 0x00000400},
+ {REG_SPDIF_SRCD, 0x00000000},
+ {REG_SPDIF_SIE, 0x00000000},
+ {REG_SPDIF_STL, 0x00000000},
+ {REG_SPDIF_STR, 0x00000000},
+ {REG_SPDIF_STCSCH, 0x00000000},
+ {REG_SPDIF_STCSCL, 0x00000000},
+ {REG_SPDIF_STC, 0x00020f00},
};
static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
@@ -1049,8 +1066,6 @@ static bool fsl_spdif_volatile_reg(struct device *dev, unsigned int reg)
case REG_SPDIF_SRCSL:
case REG_SPDIF_SRU:
case REG_SPDIF_SRQ:
- case REG_SPDIF_STL:
- case REG_SPDIF_STR:
case REG_SPDIF_SRFM:
return true;
default:
@@ -1261,6 +1276,10 @@ static int fsl_spdif_probe(struct platform_device *pdev)
return PTR_ERR(spdif_priv->coreclk);
}
+ spdif_priv->spbaclk = devm_clk_get(&pdev->dev, "spba");
+ if (IS_ERR(spdif_priv->spbaclk))
+ dev_warn(&pdev->dev, "no spba clock in devicetree\n");
+
/* Select clock source for rx/tx clock */
spdif_priv->rxclk = devm_clk_get(&pdev->dev, "rxtx1");
if (IS_ERR(spdif_priv->rxclk)) {
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 95d2392303eb..40dfd8a36484 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -113,17 +113,17 @@ struct fsl_ssi_rxtx_reg_val {
};
static const struct reg_default fsl_ssi_reg_defaults[] = {
- {0x10, 0x00000000},
- {0x18, 0x00003003},
- {0x1c, 0x00000200},
- {0x20, 0x00000200},
- {0x24, 0x00040000},
- {0x28, 0x00040000},
- {0x38, 0x00000000},
- {0x48, 0x00000000},
- {0x4c, 0x00000000},
- {0x54, 0x00000000},
- {0x58, 0x00000000},
+ {CCSR_SSI_SCR, 0x00000000},
+ {CCSR_SSI_SIER, 0x00003003},
+ {CCSR_SSI_STCR, 0x00000200},
+ {CCSR_SSI_SRCR, 0x00000200},
+ {CCSR_SSI_STCCR, 0x00040000},
+ {CCSR_SSI_SRCCR, 0x00040000},
+ {CCSR_SSI_SACNT, 0x00000000},
+ {CCSR_SSI_STMSK, 0x00000000},
+ {CCSR_SSI_SRMSK, 0x00000000},
+ {CCSR_SSI_SACCEN, 0x00000000},
+ {CCSR_SSI_SACCDIS, 0x00000000},
};
static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg)
@@ -146,6 +146,7 @@ static bool fsl_ssi_volatile_reg(struct device *dev, unsigned int reg)
case CCSR_SSI_SRX1:
case CCSR_SSI_SISR:
case CCSR_SSI_SFCSR:
+ case CCSR_SSI_SACNT:
case CCSR_SSI_SACADD:
case CCSR_SSI_SACDAT:
case CCSR_SSI_SATAG:
@@ -156,6 +157,21 @@ static bool fsl_ssi_volatile_reg(struct device *dev, unsigned int reg)
}
}
+static bool fsl_ssi_precious_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CCSR_SSI_SRX0:
+ case CCSR_SSI_SRX1:
+ case CCSR_SSI_SISR:
+ case CCSR_SSI_SACADD:
+ case CCSR_SSI_SACDAT:
+ case CCSR_SSI_SATAG:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool fsl_ssi_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -178,6 +194,7 @@ static const struct regmap_config fsl_ssi_regconfig = {
.num_reg_defaults = ARRAY_SIZE(fsl_ssi_reg_defaults),
.readable_reg = fsl_ssi_readable_reg,
.volatile_reg = fsl_ssi_volatile_reg,
+ .precious_reg = fsl_ssi_precious_reg,
.writeable_reg = fsl_ssi_writeable_reg,
.cache_type = REGCACHE_RBTREE,
};
@@ -239,8 +256,9 @@ struct fsl_ssi_private {
unsigned int baudclk_streams;
unsigned int bitclk_freq;
- /*regcache for SFCSR*/
+ /* regcache for volatile regs */
u32 regcache_sfcsr;
+ u32 regcache_sacnt;
/* DMA params */
struct snd_dmaengine_dai_dma_data dma_params_tx;
@@ -767,8 +785,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
struct regmap *regs = ssi_private->regs;
unsigned int channels = params_channels(hw_params);
- unsigned int sample_size =
- snd_pcm_format_width(params_format(hw_params));
+ unsigned int sample_size = params_width(hw_params);
u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
int ret;
u32 scr_val;
@@ -1588,6 +1605,8 @@ static int fsl_ssi_suspend(struct device *dev)
regmap_read(regs, CCSR_SSI_SFCSR,
&ssi_private->regcache_sfcsr);
+ regmap_read(regs, CCSR_SSI_SACNT,
+ &ssi_private->regcache_sacnt);
regcache_cache_only(regs, true);
regcache_mark_dirty(regs);
@@ -1606,6 +1625,8 @@ static int fsl_ssi_resume(struct device *dev)
CCSR_SSI_SFCSR_RFWM1_MASK | CCSR_SSI_SFCSR_TFWM1_MASK |
CCSR_SSI_SFCSR_RFWM0_MASK | CCSR_SSI_SFCSR_TFWM0_MASK,
ssi_private->regcache_sfcsr);
+ regmap_write(regs, CCSR_SSI_SACNT,
+ ssi_private->regcache_sacnt);
return regcache_sync(regs);
}
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index 1fc01ed3279d..f3d3d1ffa84e 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -62,6 +62,8 @@ int imx_pcm_dma_init(struct platform_device *pdev, size_t size)
config = devm_kzalloc(&pdev->dev,
sizeof(struct snd_dmaengine_pcm_config), GFP_KERNEL);
+ if (!config)
+ return -ENOMEM;
*config = imx_dmaengine_pcm_config;
if (size)
config->prealloc_buffer_size = size;
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 7abf6a079574..49d7513f429e 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -220,9 +220,9 @@ static int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
- pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
+ pr_debug("%s: ret: %d %p %pad 0x%08x\n", __func__, ret,
runtime->dma_area,
- runtime->dma_addr,
+ &runtime->dma_addr,
runtime->dma_bytes);
return ret;
}
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
index b38b98cae855..201a70d1027a 100644
--- a/sound/soc/fsl/imx-wm8962.c
+++ b/sound/soc/fsl/imx-wm8962.c
@@ -69,13 +69,16 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
struct imx_priv *priv = &card_priv;
struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
struct device *dev = &priv->pdev->dev;
unsigned int pll_out;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec_dai = rtd->codec_dai;
if (dapm->dev != codec_dai->dev)
return 0;
@@ -135,12 +138,15 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
static int imx_wm8962_late_probe(struct snd_soc_card *card)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
struct imx_priv *priv = &card_priv;
struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
struct device *dev = &priv->pdev->dev;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec_dai = rtd->codec_dai;
ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
data->clk_frequency, SND_SOC_CLOCK_IN);
if (ret < 0)
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 6f236f170cf5..ddf49f30b23f 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -189,8 +189,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
{
struct device *dev = pdev->dev.parent;
/* ssi_pdev is the platform device for the SSI node that probed us */
- struct platform_device *ssi_pdev =
- container_of(dev, struct platform_device, dev);
+ struct platform_device *ssi_pdev = to_platform_device(dev);
struct device_node *np = ssi_pdev->dev.of_node;
struct device_node *codec_np = NULL;
struct mpc8610_hpcd_data *machine_data;
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 747aab0602bd..a1f780ecadf5 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -199,8 +199,7 @@ static int p1022_ds_probe(struct platform_device *pdev)
{
struct device *dev = pdev->dev.parent;
/* ssi_pdev is the platform device for the SSI node that probed us */
- struct platform_device *ssi_pdev =
- container_of(dev, struct platform_device, dev);
+ struct platform_device *ssi_pdev = to_platform_device(dev);
struct device_node *np = ssi_pdev->dev.of_node;
struct device_node *codec_np = NULL;
struct machine_data *mdata;
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
index 1dd49e5f9675..d4d88a8cb9c0 100644
--- a/sound/soc/fsl/p1022_rdk.c
+++ b/sound/soc/fsl/p1022_rdk.c
@@ -203,8 +203,7 @@ static int p1022_rdk_probe(struct platform_device *pdev)
{
struct device *dev = pdev->dev.parent;
/* ssi_pdev is the platform device for the SSI node that probed us */
- struct platform_device *ssi_pdev =
- container_of(dev, struct platform_device, dev);
+ struct platform_device *ssi_pdev = to_platform_device(dev);
struct device_node *np = ssi_pdev->dev.of_node;
struct device_node *codec_np = NULL;
struct machine_data *mdata;
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 54c33204541f..1ded8811598e 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -45,7 +45,7 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct simple_dai_props *dai_props =
- &priv->dai_props[rtd - rtd->card->rtd];
+ &priv->dai_props[rtd->num];
int ret;
ret = clk_prepare_enable(dai_props->cpu_dai.clk);
@@ -64,7 +64,7 @@ static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
struct simple_dai_props *dai_props =
- &priv->dai_props[rtd - rtd->card->rtd];
+ &priv->dai_props[rtd->num];
clk_disable_unprepare(dai_props->cpu_dai.clk);
@@ -78,8 +78,7 @@ static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
- struct simple_dai_props *dai_props =
- &priv->dai_props[rtd - rtd->card->rtd];
+ struct simple_dai_props *dai_props = &priv->dai_props[rtd->num];
unsigned int mclk, mclk_fs = 0;
int ret = 0;
@@ -174,10 +173,9 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dai *codec = rtd->codec_dai;
struct snd_soc_dai *cpu = rtd->cpu_dai;
struct simple_dai_props *dai_props;
- int num, ret;
+ int ret;
- num = rtd - rtd->card->rtd;
- dai_props = &priv->dai_props[num];
+ dai_props = &priv->dai_props[rtd->num];
ret = __asoc_simple_card_dai_init(codec, &dai_props->codec_dai);
if (ret < 0)
return ret;
diff --git a/sound/soc/img/Kconfig b/sound/soc/img/Kconfig
new file mode 100644
index 000000000000..857a9510ee1c
--- /dev/null
+++ b/sound/soc/img/Kconfig
@@ -0,0 +1,52 @@
+config SND_SOC_IMG
+ bool "Audio support for Imagination Technologies designs"
+ help
+ Audio support for Imagination Technologies audio hardware
+
+config SND_SOC_IMG_I2S_IN
+ tristate "Imagination I2S Input Device Driver"
+ depends on SND_SOC_IMG
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+ help
+ Say Y or M if you want to add support for I2S in driver for
+ Imagination Technologies I2S in device.
+
+config SND_SOC_IMG_I2S_OUT
+ tristate "Imagination I2S Output Device Driver"
+ depends on SND_SOC_IMG
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+ help
+ Say Y or M if you want to add support for I2S out driver for
+ Imagination Technologies I2S out device.
+
+config SND_SOC_IMG_PARALLEL_OUT
+ tristate "Imagination Parallel Output Device Driver"
+ depends on SND_SOC_IMG
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+ help
+ Say Y or M if you want to add support for parallel out driver for
+ Imagination Technologies parallel out device.
+
+config SND_SOC_IMG_SPDIF_IN
+ tristate "Imagination SPDIF Input Device Driver"
+ depends on SND_SOC_IMG
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+ help
+ Say Y or M if you want to add support for SPDIF input driver for
+ Imagination Technologies SPDIF input device.
+
+config SND_SOC_IMG_SPDIF_OUT
+ tristate "Imagination SPDIF Output Device Driver"
+ depends on SND_SOC_IMG
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+ help
+ Say Y or M if you want to add support for SPDIF out driver for
+ Imagination Technologies SPDIF out device.
+
+
+config SND_SOC_IMG_PISTACHIO_INTERNAL_DAC
+ tristate "Support for Pistachio SoC Internal DAC Driver"
+ depends on SND_SOC_IMG
+ help
+ Say Y or M if you want to add support for Pistachio internal DAC
+ driver for Imagination Technologies Pistachio internal DAC device.
diff --git a/sound/soc/img/Makefile b/sound/soc/img/Makefile
new file mode 100644
index 000000000000..0508c1ced636
--- /dev/null
+++ b/sound/soc/img/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_SND_SOC_IMG_I2S_IN) += img-i2s-in.o
+obj-$(CONFIG_SND_SOC_IMG_I2S_OUT) += img-i2s-out.o
+obj-$(CONFIG_SND_SOC_IMG_PARALLEL_OUT) += img-parallel-out.o
+obj-$(CONFIG_SND_SOC_IMG_SPDIF_IN) += img-spdif-in.o
+obj-$(CONFIG_SND_SOC_IMG_SPDIF_OUT) += img-spdif-out.o
+
+obj-$(CONFIG_SND_SOC_IMG_PISTACHIO_INTERNAL_DAC) += pistachio-internal-dac.o
diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c
new file mode 100644
index 000000000000..0389203f8560
--- /dev/null
+++ b/sound/soc/img/img-i2s-in.c
@@ -0,0 +1,516 @@
+/*
+ * IMG I2S input controller driver
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define IMG_I2S_IN_RX_FIFO 0x0
+
+#define IMG_I2S_IN_CTL 0x4
+#define IMG_I2S_IN_CTL_ACTIVE_CHAN_MASK 0xfffffffc
+#define IMG_I2S_IN_CTL_ACTIVE_CH_SHIFT 2
+#define IMG_I2S_IN_CTL_16PACK_MASK BIT(1)
+#define IMG_I2S_IN_CTL_ME_MASK BIT(0)
+
+#define IMG_I2S_IN_CH_CTL 0x4
+#define IMG_I2S_IN_CH_CTL_CCDEL_MASK 0x38000
+#define IMG_I2S_IN_CH_CTL_CCDEL_SHIFT 15
+#define IMG_I2S_IN_CH_CTL_FEN_MASK BIT(14)
+#define IMG_I2S_IN_CH_CTL_FMODE_MASK BIT(13)
+#define IMG_I2S_IN_CH_CTL_16PACK_MASK BIT(12)
+#define IMG_I2S_IN_CH_CTL_JUST_MASK BIT(10)
+#define IMG_I2S_IN_CH_CTL_PACKH_MASK BIT(9)
+#define IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK BIT(8)
+#define IMG_I2S_IN_CH_CTL_BLKP_MASK BIT(7)
+#define IMG_I2S_IN_CH_CTL_FIFO_FLUSH_MASK BIT(6)
+#define IMG_I2S_IN_CH_CTL_LRD_MASK BIT(3)
+#define IMG_I2S_IN_CH_CTL_FW_MASK BIT(2)
+#define IMG_I2S_IN_CH_CTL_SW_MASK BIT(1)
+#define IMG_I2S_IN_CH_CTL_ME_MASK BIT(0)
+
+#define IMG_I2S_IN_CH_STRIDE 0x20
+
+struct img_i2s_in {
+ void __iomem *base;
+ struct clk *clk_sys;
+ struct snd_dmaengine_dai_dma_data dma_data;
+ struct device *dev;
+ unsigned int max_i2s_chan;
+ void __iomem *channel_base;
+ unsigned int active_channels;
+ struct snd_soc_dai_driver dai_driver;
+};
+
+static inline void img_i2s_in_writel(struct img_i2s_in *i2s, u32 val, u32 reg)
+{
+ writel(val, i2s->base + reg);
+}
+
+static inline u32 img_i2s_in_readl(struct img_i2s_in *i2s, u32 reg)
+{
+ return readl(i2s->base + reg);
+}
+
+static inline void img_i2s_in_ch_writel(struct img_i2s_in *i2s, u32 chan,
+ u32 val, u32 reg)
+{
+ writel(val, i2s->channel_base + (chan * IMG_I2S_IN_CH_STRIDE) + reg);
+}
+
+static inline u32 img_i2s_in_ch_readl(struct img_i2s_in *i2s, u32 chan,
+ u32 reg)
+{
+ return readl(i2s->channel_base + (chan * IMG_I2S_IN_CH_STRIDE) + reg);
+}
+
+static inline void img_i2s_in_ch_disable(struct img_i2s_in *i2s, u32 chan)
+{
+ u32 reg;
+
+ reg = img_i2s_in_ch_readl(i2s, chan, IMG_I2S_IN_CH_CTL);
+ reg &= ~IMG_I2S_IN_CH_CTL_ME_MASK;
+ img_i2s_in_ch_writel(i2s, chan, reg, IMG_I2S_IN_CH_CTL);
+}
+
+static inline void img_i2s_in_ch_enable(struct img_i2s_in *i2s, u32 chan)
+{
+ u32 reg;
+
+ reg = img_i2s_in_ch_readl(i2s, chan, IMG_I2S_IN_CH_CTL);
+ reg |= IMG_I2S_IN_CH_CTL_ME_MASK;
+ img_i2s_in_ch_writel(i2s, chan, reg, IMG_I2S_IN_CH_CTL);
+}
+
+static inline void img_i2s_in_disable(struct img_i2s_in *i2s)
+{
+ u32 reg;
+
+ reg = img_i2s_in_readl(i2s, IMG_I2S_IN_CTL);
+ reg &= ~IMG_I2S_IN_CTL_ME_MASK;
+ img_i2s_in_writel(i2s, reg, IMG_I2S_IN_CTL);
+}
+
+static inline void img_i2s_in_enable(struct img_i2s_in *i2s)
+{
+ u32 reg;
+
+ reg = img_i2s_in_readl(i2s, IMG_I2S_IN_CTL);
+ reg |= IMG_I2S_IN_CTL_ME_MASK;
+ img_i2s_in_writel(i2s, reg, IMG_I2S_IN_CTL);
+}
+
+static inline void img_i2s_in_flush(struct img_i2s_in *i2s)
+{
+ int i;
+ u32 reg;
+
+ for (i = 0; i < i2s->active_channels; i++) {
+ reg = img_i2s_in_ch_readl(i2s, i, IMG_I2S_IN_CH_CTL);
+ reg |= IMG_I2S_IN_CH_CTL_FIFO_FLUSH_MASK;
+ img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
+ reg &= ~IMG_I2S_IN_CH_CTL_FIFO_FLUSH_MASK;
+ img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
+ }
+}
+
+static int img_i2s_in_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct img_i2s_in *i2s = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ img_i2s_in_enable(i2s);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ img_i2s_in_disable(i2s);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int img_i2s_in_check_rate(struct img_i2s_in *i2s,
+ unsigned int sample_rate, unsigned int frame_size,
+ unsigned int *bclk_filter_enable,
+ unsigned int *bclk_filter_value)
+{
+ unsigned int bclk_freq, cur_freq;
+
+ bclk_freq = sample_rate * frame_size;
+
+ cur_freq = clk_get_rate(i2s->clk_sys);
+
+ if (cur_freq >= bclk_freq * 8) {
+ *bclk_filter_enable = 1;
+ *bclk_filter_value = 0;
+ } else if (cur_freq >= bclk_freq * 7) {
+ *bclk_filter_enable = 1;
+ *bclk_filter_value = 1;
+ } else if (cur_freq >= bclk_freq * 6) {
+ *bclk_filter_enable = 0;
+ *bclk_filter_value = 0;
+ } else {
+ dev_err(i2s->dev,
+ "Sys clock rate %u insufficient for sample rate %u\n",
+ cur_freq, sample_rate);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int img_i2s_in_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct img_i2s_in *i2s = snd_soc_dai_get_drvdata(dai);
+ unsigned int rate, channels, i2s_channels, frame_size;
+ unsigned int bclk_filter_enable, bclk_filter_value;
+ int i, ret = 0;
+ u32 reg, control_mask, chan_control_mask;
+ u32 control_set = 0, chan_control_set = 0;
+ snd_pcm_format_t format;
+
+ rate = params_rate(params);
+ format = params_format(params);
+ channels = params_channels(params);
+ i2s_channels = channels / 2;
+
+ switch (format) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ frame_size = 64;
+ chan_control_set |= IMG_I2S_IN_CH_CTL_SW_MASK;
+ chan_control_set |= IMG_I2S_IN_CH_CTL_FW_MASK;
+ chan_control_set |= IMG_I2S_IN_CH_CTL_PACKH_MASK;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ frame_size = 64;
+ chan_control_set |= IMG_I2S_IN_CH_CTL_SW_MASK;
+ chan_control_set |= IMG_I2S_IN_CH_CTL_FW_MASK;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ frame_size = 32;
+ control_set |= IMG_I2S_IN_CTL_16PACK_MASK;
+ chan_control_set |= IMG_I2S_IN_CH_CTL_16PACK_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((channels < 2) ||
+ (channels > (i2s->max_i2s_chan * 2)) ||
+ (channels % 2))
+ return -EINVAL;
+
+ control_set |= ((i2s_channels - 1) << IMG_I2S_IN_CTL_ACTIVE_CH_SHIFT);
+
+ ret = img_i2s_in_check_rate(i2s, rate, frame_size,
+ &bclk_filter_enable, &bclk_filter_value);
+ if (ret < 0)
+ return ret;
+
+ if (bclk_filter_enable)
+ chan_control_set |= IMG_I2S_IN_CH_CTL_FEN_MASK;
+
+ if (bclk_filter_value)
+ chan_control_set |= IMG_I2S_IN_CH_CTL_FMODE_MASK;
+
+ control_mask = IMG_I2S_IN_CTL_16PACK_MASK |
+ IMG_I2S_IN_CTL_ACTIVE_CHAN_MASK;
+
+ chan_control_mask = IMG_I2S_IN_CH_CTL_16PACK_MASK |
+ IMG_I2S_IN_CH_CTL_FEN_MASK |
+ IMG_I2S_IN_CH_CTL_FMODE_MASK |
+ IMG_I2S_IN_CH_CTL_SW_MASK |
+ IMG_I2S_IN_CH_CTL_FW_MASK |
+ IMG_I2S_IN_CH_CTL_PACKH_MASK;
+
+ reg = img_i2s_in_readl(i2s, IMG_I2S_IN_CTL);
+ reg = (reg & ~control_mask) | control_set;
+ img_i2s_in_writel(i2s, reg, IMG_I2S_IN_CTL);
+
+ for (i = 0; i < i2s->active_channels; i++)
+ img_i2s_in_ch_disable(i2s, i);
+
+ for (i = 0; i < i2s->max_i2s_chan; i++) {
+ reg = img_i2s_in_ch_readl(i2s, i, IMG_I2S_IN_CH_CTL);
+ reg = (reg & ~chan_control_mask) | chan_control_set;
+ img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
+ }
+
+ i2s->active_channels = i2s_channels;
+
+ img_i2s_in_flush(i2s);
+
+ for (i = 0; i < i2s->active_channels; i++)
+ img_i2s_in_ch_enable(i2s, i);
+
+ return 0;
+}
+
+static int img_i2s_in_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct img_i2s_in *i2s = snd_soc_dai_get_drvdata(dai);
+ int i;
+ u32 chan_control_mask, lrd_set = 0, blkp_set = 0, chan_control_set = 0;
+ u32 reg;
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ lrd_set |= IMG_I2S_IN_CH_CTL_LRD_MASK;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ lrd_set |= IMG_I2S_IN_CH_CTL_LRD_MASK;
+ blkp_set |= IMG_I2S_IN_CH_CTL_BLKP_MASK;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ blkp_set |= IMG_I2S_IN_CH_CTL_BLKP_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ chan_control_set |= IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ chan_control_mask = IMG_I2S_IN_CH_CTL_CLK_TRANS_MASK;
+
+ for (i = 0; i < i2s->active_channels; i++)
+ img_i2s_in_ch_disable(i2s, i);
+
+ /*
+ * BLKP and LRD must be set during separate register writes
+ */
+ for (i = 0; i < i2s->max_i2s_chan; i++) {
+ reg = img_i2s_in_ch_readl(i2s, i, IMG_I2S_IN_CH_CTL);
+ reg = (reg & ~chan_control_mask) | chan_control_set;
+ img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
+ reg = (reg & ~IMG_I2S_IN_CH_CTL_BLKP_MASK) | blkp_set;
+ img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
+ reg = (reg & ~IMG_I2S_IN_CH_CTL_LRD_MASK) | lrd_set;
+ img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
+ }
+
+ for (i = 0; i < i2s->active_channels; i++)
+ img_i2s_in_ch_enable(i2s, i);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops img_i2s_in_dai_ops = {
+ .trigger = img_i2s_in_trigger,
+ .hw_params = img_i2s_in_hw_params,
+ .set_fmt = img_i2s_in_set_fmt
+};
+
+static int img_i2s_in_dai_probe(struct snd_soc_dai *dai)
+{
+ struct img_i2s_in *i2s = snd_soc_dai_get_drvdata(dai);
+
+ snd_soc_dai_init_dma_data(dai, NULL, &i2s->dma_data);
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver img_i2s_in_component = {
+ .name = "img-i2s-in"
+};
+
+static int img_i2s_in_dma_prepare_slave_config(struct snd_pcm_substream *st,
+ struct snd_pcm_hw_params *params, struct dma_slave_config *sc)
+{
+ unsigned int i2s_channels = params_channels(params) / 2;
+ struct snd_soc_pcm_runtime *rtd = st->private_data;
+ struct snd_dmaengine_dai_dma_data *dma_data;
+ int ret;
+
+ dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, st);
+
+ ret = snd_hwparams_to_dma_slave_config(st, params, sc);
+ if (ret)
+ return ret;
+
+ sc->src_addr = dma_data->addr;
+ sc->src_addr_width = dma_data->addr_width;
+ sc->src_maxburst = 4 * i2s_channels;
+
+ return 0;
+}
+
+static const struct snd_dmaengine_pcm_config img_i2s_in_dma_config = {
+ .prepare_slave_config = img_i2s_in_dma_prepare_slave_config
+};
+
+static int img_i2s_in_probe(struct platform_device *pdev)
+{
+ struct img_i2s_in *i2s;
+ struct resource *res;
+ void __iomem *base;
+ int ret, i;
+ struct reset_control *rst;
+ unsigned int max_i2s_chan_pow_2;
+ struct device *dev = &pdev->dev;
+
+ i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL);
+ if (!i2s)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, i2s);
+
+ i2s->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ i2s->base = base;
+
+ if (of_property_read_u32(pdev->dev.of_node, "img,i2s-channels",
+ &i2s->max_i2s_chan)) {
+ dev_err(dev, "No img,i2s-channels property\n");
+ return -EINVAL;
+ }
+
+ max_i2s_chan_pow_2 = 1 << get_count_order(i2s->max_i2s_chan);
+
+ i2s->channel_base = base + (max_i2s_chan_pow_2 * 0x20);
+
+ i2s->clk_sys = devm_clk_get(dev, "sys");
+ if (IS_ERR(i2s->clk_sys)) {
+ if (PTR_ERR(i2s->clk_sys) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to acquire clock 'sys'\n");
+ return PTR_ERR(i2s->clk_sys);
+ }
+
+ ret = clk_prepare_enable(i2s->clk_sys);
+ if (ret)
+ return ret;
+
+ i2s->active_channels = 1;
+ i2s->dma_data.addr = res->start + IMG_I2S_IN_RX_FIFO;
+ i2s->dma_data.addr_width = 4;
+
+ i2s->dai_driver.probe = img_i2s_in_dai_probe;
+ i2s->dai_driver.capture.channels_min = 2;
+ i2s->dai_driver.capture.channels_max = i2s->max_i2s_chan * 2;
+ i2s->dai_driver.capture.rates = SNDRV_PCM_RATE_8000_192000;
+ i2s->dai_driver.capture.formats = SNDRV_PCM_FMTBIT_S32_LE |
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE;
+ i2s->dai_driver.ops = &img_i2s_in_dai_ops;
+
+ rst = devm_reset_control_get(dev, "rst");
+ if (IS_ERR(rst)) {
+ if (PTR_ERR(rst) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_clk_disable;
+ }
+
+ dev_dbg(dev, "No top level reset found\n");
+
+ img_i2s_in_disable(i2s);
+
+ for (i = 0; i < i2s->max_i2s_chan; i++)
+ img_i2s_in_ch_disable(i2s, i);
+ } else {
+ reset_control_assert(rst);
+ reset_control_deassert(rst);
+ }
+
+ img_i2s_in_writel(i2s, 0, IMG_I2S_IN_CTL);
+
+ for (i = 0; i < i2s->max_i2s_chan; i++)
+ img_i2s_in_ch_writel(i2s, i,
+ (4 << IMG_I2S_IN_CH_CTL_CCDEL_SHIFT) |
+ IMG_I2S_IN_CH_CTL_JUST_MASK |
+ IMG_I2S_IN_CH_CTL_FW_MASK, IMG_I2S_IN_CH_CTL);
+
+ ret = devm_snd_soc_register_component(dev, &img_i2s_in_component,
+ &i2s->dai_driver, 1);
+ if (ret)
+ goto err_clk_disable;
+
+ ret = devm_snd_dmaengine_pcm_register(dev, &img_i2s_in_dma_config, 0);
+ if (ret)
+ goto err_clk_disable;
+
+ return 0;
+
+err_clk_disable:
+ clk_disable_unprepare(i2s->clk_sys);
+
+ return ret;
+}
+
+static int img_i2s_in_dev_remove(struct platform_device *pdev)
+{
+ struct img_i2s_in *i2s = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(i2s->clk_sys);
+
+ return 0;
+}
+
+static const struct of_device_id img_i2s_in_of_match[] = {
+ { .compatible = "img,i2s-in" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, img_i2s_in_of_match);
+
+static struct platform_driver img_i2s_in_driver = {
+ .driver = {
+ .name = "img-i2s-in",
+ .of_match_table = img_i2s_in_of_match
+ },
+ .probe = img_i2s_in_probe,
+ .remove = img_i2s_in_dev_remove
+};
+module_platform_driver(img_i2s_in_driver);
+
+MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
+MODULE_DESCRIPTION("IMG I2S Input Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c
new file mode 100644
index 000000000000..5f997135a8ae
--- /dev/null
+++ b/sound/soc/img/img-i2s-out.c
@@ -0,0 +1,565 @@
+/*
+ * IMG I2S output controller driver
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define IMG_I2S_OUT_TX_FIFO 0x0
+
+#define IMG_I2S_OUT_CTL 0x4
+#define IMG_I2S_OUT_CTL_DATA_EN_MASK BIT(24)
+#define IMG_I2S_OUT_CTL_ACTIVE_CHAN_MASK 0xffe000
+#define IMG_I2S_OUT_CTL_ACTIVE_CHAN_SHIFT 13
+#define IMG_I2S_OUT_CTL_FRM_SIZE_MASK BIT(8)
+#define IMG_I2S_OUT_CTL_MASTER_MASK BIT(6)
+#define IMG_I2S_OUT_CTL_CLK_MASK BIT(5)
+#define IMG_I2S_OUT_CTL_CLK_EN_MASK BIT(4)
+#define IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK BIT(3)
+#define IMG_I2S_OUT_CTL_BCLK_POL_MASK BIT(2)
+#define IMG_I2S_OUT_CTL_ME_MASK BIT(0)
+
+#define IMG_I2S_OUT_CH_CTL 0x4
+#define IMG_I2S_OUT_CHAN_CTL_CH_MASK BIT(11)
+#define IMG_I2S_OUT_CHAN_CTL_LT_MASK BIT(10)
+#define IMG_I2S_OUT_CHAN_CTL_FMT_MASK 0xf0
+#define IMG_I2S_OUT_CHAN_CTL_FMT_SHIFT 4
+#define IMG_I2S_OUT_CHAN_CTL_JUST_MASK BIT(3)
+#define IMG_I2S_OUT_CHAN_CTL_CLKT_MASK BIT(1)
+#define IMG_I2S_OUT_CHAN_CTL_ME_MASK BIT(0)
+
+#define IMG_I2S_OUT_CH_STRIDE 0x20
+
+struct img_i2s_out {
+ void __iomem *base;
+ struct clk *clk_sys;
+ struct clk *clk_ref;
+ struct snd_dmaengine_dai_dma_data dma_data;
+ struct device *dev;
+ unsigned int max_i2s_chan;
+ void __iomem *channel_base;
+ bool force_clk_active;
+ unsigned int active_channels;
+ struct reset_control *rst;
+ struct snd_soc_dai_driver dai_driver;
+};
+
+static int img_i2s_out_suspend(struct device *dev)
+{
+ struct img_i2s_out *i2s = dev_get_drvdata(dev);
+
+ if (!i2s->force_clk_active)
+ clk_disable_unprepare(i2s->clk_ref);
+
+ return 0;
+}
+
+static int img_i2s_out_resume(struct device *dev)
+{
+ struct img_i2s_out *i2s = dev_get_drvdata(dev);
+ int ret;
+
+ if (!i2s->force_clk_active) {
+ ret = clk_prepare_enable(i2s->clk_ref);
+ if (ret) {
+ dev_err(dev, "clk_enable failed: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static inline void img_i2s_out_writel(struct img_i2s_out *i2s, u32 val,
+ u32 reg)
+{
+ writel(val, i2s->base + reg);
+}
+
+static inline u32 img_i2s_out_readl(struct img_i2s_out *i2s, u32 reg)
+{
+ return readl(i2s->base + reg);
+}
+
+static inline void img_i2s_out_ch_writel(struct img_i2s_out *i2s,
+ u32 chan, u32 val, u32 reg)
+{
+ writel(val, i2s->channel_base + (chan * IMG_I2S_OUT_CH_STRIDE) + reg);
+}
+
+static inline u32 img_i2s_out_ch_readl(struct img_i2s_out *i2s, u32 chan,
+ u32 reg)
+{
+ return readl(i2s->channel_base + (chan * IMG_I2S_OUT_CH_STRIDE) + reg);
+}
+
+static inline void img_i2s_out_ch_disable(struct img_i2s_out *i2s, u32 chan)
+{
+ u32 reg;
+
+ reg = img_i2s_out_ch_readl(i2s, chan, IMG_I2S_OUT_CH_CTL);
+ reg &= ~IMG_I2S_OUT_CHAN_CTL_ME_MASK;
+ img_i2s_out_ch_writel(i2s, chan, reg, IMG_I2S_OUT_CH_CTL);
+}
+
+static inline void img_i2s_out_ch_enable(struct img_i2s_out *i2s, u32 chan)
+{
+ u32 reg;
+
+ reg = img_i2s_out_ch_readl(i2s, chan, IMG_I2S_OUT_CH_CTL);
+ reg |= IMG_I2S_OUT_CHAN_CTL_ME_MASK;
+ img_i2s_out_ch_writel(i2s, chan, reg, IMG_I2S_OUT_CH_CTL);
+}
+
+static inline void img_i2s_out_disable(struct img_i2s_out *i2s)
+{
+ u32 reg;
+
+ reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
+ reg &= ~IMG_I2S_OUT_CTL_ME_MASK;
+ img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
+}
+
+static inline void img_i2s_out_enable(struct img_i2s_out *i2s)
+{
+ u32 reg;
+
+ reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
+ reg |= IMG_I2S_OUT_CTL_ME_MASK;
+ img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
+}
+
+static void img_i2s_out_reset(struct img_i2s_out *i2s)
+{
+ int i;
+ u32 core_ctl, chan_ctl;
+
+ core_ctl = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL) &
+ ~IMG_I2S_OUT_CTL_ME_MASK &
+ ~IMG_I2S_OUT_CTL_DATA_EN_MASK;
+
+ if (!i2s->force_clk_active)
+ core_ctl &= ~IMG_I2S_OUT_CTL_CLK_EN_MASK;
+
+ chan_ctl = img_i2s_out_ch_readl(i2s, 0, IMG_I2S_OUT_CH_CTL) &
+ ~IMG_I2S_OUT_CHAN_CTL_ME_MASK;
+
+ reset_control_assert(i2s->rst);
+ reset_control_deassert(i2s->rst);
+
+ for (i = 0; i < i2s->max_i2s_chan; i++)
+ img_i2s_out_ch_writel(i2s, i, chan_ctl, IMG_I2S_OUT_CH_CTL);
+
+ for (i = 0; i < i2s->active_channels; i++)
+ img_i2s_out_ch_enable(i2s, i);
+
+ img_i2s_out_writel(i2s, core_ctl, IMG_I2S_OUT_CTL);
+ img_i2s_out_enable(i2s);
+}
+
+static int img_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct img_i2s_out *i2s = snd_soc_dai_get_drvdata(dai);
+ u32 reg;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
+ if (!i2s->force_clk_active)
+ reg |= IMG_I2S_OUT_CTL_CLK_EN_MASK;
+ reg |= IMG_I2S_OUT_CTL_DATA_EN_MASK;
+ img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ img_i2s_out_reset(i2s);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int img_i2s_out_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct img_i2s_out *i2s = snd_soc_dai_get_drvdata(dai);
+ unsigned int channels, i2s_channels;
+ long pre_div_a, pre_div_b, diff_a, diff_b, rate, clk_rate;
+ int i;
+ u32 reg, control_mask, control_set = 0;
+ snd_pcm_format_t format;
+
+ rate = params_rate(params);
+ format = params_format(params);
+ channels = params_channels(params);
+ i2s_channels = channels / 2;
+
+ if (format != SNDRV_PCM_FORMAT_S32_LE)
+ return -EINVAL;
+
+ if ((channels < 2) ||
+ (channels > (i2s->max_i2s_chan * 2)) ||
+ (channels % 2))
+ return -EINVAL;
+
+ pre_div_a = clk_round_rate(i2s->clk_ref, rate * 256);
+ if (pre_div_a < 0)
+ return pre_div_a;
+ pre_div_b = clk_round_rate(i2s->clk_ref, rate * 384);
+ if (pre_div_b < 0)
+ return pre_div_b;
+
+ diff_a = abs((pre_div_a / 256) - rate);
+ diff_b = abs((pre_div_b / 384) - rate);
+
+ /* If diffs are equal, use lower clock rate */
+ if (diff_a > diff_b)
+ clk_set_rate(i2s->clk_ref, pre_div_b);
+ else
+ clk_set_rate(i2s->clk_ref, pre_div_a);
+
+ /*
+ * Another driver (eg alsa machine driver) may have rejected the above
+ * change. Get the current rate and set the register bit according to
+ * the new minimum diff
+ */
+ clk_rate = clk_get_rate(i2s->clk_ref);
+
+ diff_a = abs((clk_rate / 256) - rate);
+ diff_b = abs((clk_rate / 384) - rate);
+
+ if (diff_a > diff_b)
+ control_set |= IMG_I2S_OUT_CTL_CLK_MASK;
+
+ control_set |= ((i2s_channels - 1) <<
+ IMG_I2S_OUT_CTL_ACTIVE_CHAN_SHIFT) &
+ IMG_I2S_OUT_CTL_ACTIVE_CHAN_MASK;
+
+ control_mask = IMG_I2S_OUT_CTL_CLK_MASK |
+ IMG_I2S_OUT_CTL_ACTIVE_CHAN_MASK;
+
+ img_i2s_out_disable(i2s);
+
+ reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
+ reg = (reg & ~control_mask) | control_set;
+ img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
+
+ for (i = 0; i < i2s_channels; i++)
+ img_i2s_out_ch_enable(i2s, i);
+
+ for (; i < i2s->max_i2s_chan; i++)
+ img_i2s_out_ch_disable(i2s, i);
+
+ img_i2s_out_enable(i2s);
+
+ i2s->active_channels = i2s_channels;
+
+ return 0;
+}
+
+static int img_i2s_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct img_i2s_out *i2s = snd_soc_dai_get_drvdata(dai);
+ int i;
+ bool force_clk_active;
+ u32 chan_control_mask, control_mask, chan_control_set = 0;
+ u32 reg, control_set = 0;
+
+ force_clk_active = ((fmt & SND_SOC_DAIFMT_CLOCK_MASK) ==
+ SND_SOC_DAIFMT_CONT);
+
+ if (force_clk_active)
+ control_set |= IMG_I2S_OUT_CTL_CLK_EN_MASK;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ control_set |= IMG_I2S_OUT_CTL_MASTER_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ control_set |= IMG_I2S_OUT_CTL_BCLK_POL_MASK;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ control_set |= IMG_I2S_OUT_CTL_BCLK_POL_MASK;
+ control_set |= IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ control_set |= IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ chan_control_set |= IMG_I2S_OUT_CHAN_CTL_CLKT_MASK;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ control_mask = IMG_I2S_OUT_CTL_CLK_EN_MASK |
+ IMG_I2S_OUT_CTL_MASTER_MASK |
+ IMG_I2S_OUT_CTL_BCLK_POL_MASK |
+ IMG_I2S_OUT_CTL_FRM_CLK_POL_MASK;
+
+ chan_control_mask = IMG_I2S_OUT_CHAN_CTL_CLKT_MASK;
+
+ img_i2s_out_disable(i2s);
+
+ reg = img_i2s_out_readl(i2s, IMG_I2S_OUT_CTL);
+ reg = (reg & ~control_mask) | control_set;
+ img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
+
+ for (i = 0; i < i2s->active_channels; i++)
+ img_i2s_out_ch_disable(i2s, i);
+
+ for (i = 0; i < i2s->max_i2s_chan; i++) {
+ reg = img_i2s_out_ch_readl(i2s, i, IMG_I2S_OUT_CH_CTL);
+ reg = (reg & ~chan_control_mask) | chan_control_set;
+ img_i2s_out_ch_writel(i2s, i, reg, IMG_I2S_OUT_CH_CTL);
+ }
+
+ for (i = 0; i < i2s->active_channels; i++)
+ img_i2s_out_ch_enable(i2s, i);
+
+ img_i2s_out_enable(i2s);
+
+ i2s->force_clk_active = force_clk_active;
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops img_i2s_out_dai_ops = {
+ .trigger = img_i2s_out_trigger,
+ .hw_params = img_i2s_out_hw_params,
+ .set_fmt = img_i2s_out_set_fmt
+};
+
+static int img_i2s_out_dai_probe(struct snd_soc_dai *dai)
+{
+ struct img_i2s_out *i2s = snd_soc_dai_get_drvdata(dai);
+
+ snd_soc_dai_init_dma_data(dai, &i2s->dma_data, NULL);
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver img_i2s_out_component = {
+ .name = "img-i2s-out"
+};
+
+static int img_i2s_out_dma_prepare_slave_config(struct snd_pcm_substream *st,
+ struct snd_pcm_hw_params *params, struct dma_slave_config *sc)
+{
+ unsigned int i2s_channels = params_channels(params) / 2;
+ struct snd_soc_pcm_runtime *rtd = st->private_data;
+ struct snd_dmaengine_dai_dma_data *dma_data;
+ int ret;
+
+ dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, st);
+
+ ret = snd_hwparams_to_dma_slave_config(st, params, sc);
+ if (ret)
+ return ret;
+
+ sc->dst_addr = dma_data->addr;
+ sc->dst_addr_width = dma_data->addr_width;
+ sc->dst_maxburst = 4 * i2s_channels;
+
+ return 0;
+}
+
+static const struct snd_dmaengine_pcm_config img_i2s_out_dma_config = {
+ .prepare_slave_config = img_i2s_out_dma_prepare_slave_config
+};
+
+static int img_i2s_out_probe(struct platform_device *pdev)
+{
+ struct img_i2s_out *i2s;
+ struct resource *res;
+ void __iomem *base;
+ int i, ret;
+ unsigned int max_i2s_chan_pow_2;
+ u32 reg;
+ struct device *dev = &pdev->dev;
+
+ i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
+ if (!i2s)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, i2s);
+
+ i2s->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ i2s->base = base;
+
+ if (of_property_read_u32(pdev->dev.of_node, "img,i2s-channels",
+ &i2s->max_i2s_chan)) {
+ dev_err(&pdev->dev, "No img,i2s-channels property\n");
+ return -EINVAL;
+ }
+
+ max_i2s_chan_pow_2 = 1 << get_count_order(i2s->max_i2s_chan);
+
+ i2s->channel_base = base + (max_i2s_chan_pow_2 * 0x20);
+
+ i2s->rst = devm_reset_control_get(&pdev->dev, "rst");
+ if (IS_ERR(i2s->rst)) {
+ if (PTR_ERR(i2s->rst) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "No top level reset found\n");
+ return PTR_ERR(i2s->rst);
+ }
+
+ i2s->clk_sys = devm_clk_get(&pdev->dev, "sys");
+ if (IS_ERR(i2s->clk_sys)) {
+ if (PTR_ERR(i2s->clk_sys) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to acquire clock 'sys'\n");
+ return PTR_ERR(i2s->clk_sys);
+ }
+
+ i2s->clk_ref = devm_clk_get(&pdev->dev, "ref");
+ if (IS_ERR(i2s->clk_ref)) {
+ if (PTR_ERR(i2s->clk_ref) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to acquire clock 'ref'\n");
+ return PTR_ERR(i2s->clk_ref);
+ }
+
+ ret = clk_prepare_enable(i2s->clk_sys);
+ if (ret)
+ return ret;
+
+ reg = IMG_I2S_OUT_CTL_FRM_SIZE_MASK;
+ img_i2s_out_writel(i2s, reg, IMG_I2S_OUT_CTL);
+
+ reg = IMG_I2S_OUT_CHAN_CTL_JUST_MASK |
+ IMG_I2S_OUT_CHAN_CTL_LT_MASK |
+ IMG_I2S_OUT_CHAN_CTL_CH_MASK |
+ (8 << IMG_I2S_OUT_CHAN_CTL_FMT_SHIFT);
+
+ for (i = 0; i < i2s->max_i2s_chan; i++)
+ img_i2s_out_ch_writel(i2s, i, reg, IMG_I2S_OUT_CH_CTL);
+
+ img_i2s_out_reset(i2s);
+
+ pm_runtime_enable(&pdev->dev);
+ if (!pm_runtime_enabled(&pdev->dev)) {
+ ret = img_i2s_out_resume(&pdev->dev);
+ if (ret)
+ goto err_pm_disable;
+ }
+
+ i2s->active_channels = 1;
+ i2s->dma_data.addr = res->start + IMG_I2S_OUT_TX_FIFO;
+ i2s->dma_data.addr_width = 4;
+ i2s->dma_data.maxburst = 4;
+
+ i2s->dai_driver.probe = img_i2s_out_dai_probe;
+ i2s->dai_driver.playback.channels_min = 2;
+ i2s->dai_driver.playback.channels_max = i2s->max_i2s_chan * 2;
+ i2s->dai_driver.playback.rates = SNDRV_PCM_RATE_8000_192000;
+ i2s->dai_driver.playback.formats = SNDRV_PCM_FMTBIT_S32_LE;
+ i2s->dai_driver.ops = &img_i2s_out_dai_ops;
+
+ ret = devm_snd_soc_register_component(&pdev->dev,
+ &img_i2s_out_component, &i2s->dai_driver, 1);
+ if (ret)
+ goto err_suspend;
+
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
+ &img_i2s_out_dma_config, 0);
+ if (ret)
+ goto err_suspend;
+
+ return 0;
+
+err_suspend:
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ img_i2s_out_suspend(&pdev->dev);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ clk_disable_unprepare(i2s->clk_sys);
+
+ return ret;
+}
+
+static int img_i2s_out_dev_remove(struct platform_device *pdev)
+{
+ struct img_i2s_out *i2s = platform_get_drvdata(pdev);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ img_i2s_out_suspend(&pdev->dev);
+
+ clk_disable_unprepare(i2s->clk_sys);
+
+ return 0;
+}
+
+static const struct of_device_id img_i2s_out_of_match[] = {
+ { .compatible = "img,i2s-out" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, img_i2s_out_of_match);
+
+static const struct dev_pm_ops img_i2s_out_pm_ops = {
+ SET_RUNTIME_PM_OPS(img_i2s_out_suspend,
+ img_i2s_out_resume, NULL)
+};
+
+static struct platform_driver img_i2s_out_driver = {
+ .driver = {
+ .name = "img-i2s-out",
+ .of_match_table = img_i2s_out_of_match,
+ .pm = &img_i2s_out_pm_ops
+ },
+ .probe = img_i2s_out_probe,
+ .remove = img_i2s_out_dev_remove
+};
+module_platform_driver(img_i2s_out_driver);
+
+MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
+MODULE_DESCRIPTION("IMG I2S Output Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/img/img-parallel-out.c b/sound/soc/img/img-parallel-out.c
new file mode 100644
index 000000000000..c1610a054d65
--- /dev/null
+++ b/sound/soc/img/img-parallel-out.c
@@ -0,0 +1,327 @@
+/*
+ * IMG parallel output controller driver
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define IMG_PRL_OUT_TX_FIFO 0
+
+#define IMG_PRL_OUT_CTL 0x4
+#define IMG_PRL_OUT_CTL_CH_MASK BIT(4)
+#define IMG_PRL_OUT_CTL_PACKH_MASK BIT(3)
+#define IMG_PRL_OUT_CTL_EDGE_MASK BIT(2)
+#define IMG_PRL_OUT_CTL_ME_MASK BIT(1)
+#define IMG_PRL_OUT_CTL_SRST_MASK BIT(0)
+
+struct img_prl_out {
+ void __iomem *base;
+ struct clk *clk_sys;
+ struct clk *clk_ref;
+ struct snd_dmaengine_dai_dma_data dma_data;
+ struct device *dev;
+ struct reset_control *rst;
+};
+
+static int img_prl_out_suspend(struct device *dev)
+{
+ struct img_prl_out *prl = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(prl->clk_ref);
+
+ return 0;
+}
+
+static int img_prl_out_resume(struct device *dev)
+{
+ struct img_prl_out *prl = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(prl->clk_ref);
+ if (ret) {
+ dev_err(dev, "clk_enable failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline void img_prl_out_writel(struct img_prl_out *prl,
+ u32 val, u32 reg)
+{
+ writel(val, prl->base + reg);
+}
+
+static inline u32 img_prl_out_readl(struct img_prl_out *prl, u32 reg)
+{
+ return readl(prl->base + reg);
+}
+
+static void img_prl_out_reset(struct img_prl_out *prl)
+{
+ u32 ctl;
+
+ ctl = img_prl_out_readl(prl, IMG_PRL_OUT_CTL) &
+ ~IMG_PRL_OUT_CTL_ME_MASK;
+
+ reset_control_assert(prl->rst);
+ reset_control_deassert(prl->rst);
+
+ img_prl_out_writel(prl, ctl, IMG_PRL_OUT_CTL);
+}
+
+static int img_prl_out_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai);
+ u32 reg;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ reg = img_prl_out_readl(prl, IMG_PRL_OUT_CTL);
+ reg |= IMG_PRL_OUT_CTL_ME_MASK;
+ img_prl_out_writel(prl, reg, IMG_PRL_OUT_CTL);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ img_prl_out_reset(prl);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int img_prl_out_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai);
+ unsigned int rate, channels;
+ u32 reg, control_set = 0;
+ snd_pcm_format_t format;
+
+ rate = params_rate(params);
+ format = params_format(params);
+ channels = params_channels(params);
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ control_set |= IMG_PRL_OUT_CTL_PACKH_MASK;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (channels != 2)
+ return -EINVAL;
+
+ clk_set_rate(prl->clk_ref, rate * 256);
+
+ reg = img_prl_out_readl(prl, IMG_PRL_OUT_CTL);
+ reg = (reg & ~IMG_PRL_OUT_CTL_PACKH_MASK) | control_set;
+ img_prl_out_writel(prl, reg, IMG_PRL_OUT_CTL);
+
+ return 0;
+}
+
+static int img_prl_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai);
+ u32 reg, control_set = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ control_set |= IMG_PRL_OUT_CTL_EDGE_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ reg = img_prl_out_readl(prl, IMG_PRL_OUT_CTL);
+ reg = (reg & ~IMG_PRL_OUT_CTL_EDGE_MASK) | control_set;
+ img_prl_out_writel(prl, reg, IMG_PRL_OUT_CTL);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops img_prl_out_dai_ops = {
+ .trigger = img_prl_out_trigger,
+ .hw_params = img_prl_out_hw_params,
+ .set_fmt = img_prl_out_set_fmt
+};
+
+static int img_prl_out_dai_probe(struct snd_soc_dai *dai)
+{
+ struct img_prl_out *prl = snd_soc_dai_get_drvdata(dai);
+
+ snd_soc_dai_init_dma_data(dai, &prl->dma_data, NULL);
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver img_prl_out_dai = {
+ .probe = img_prl_out_dai_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE
+ },
+ .ops = &img_prl_out_dai_ops
+};
+
+static const struct snd_soc_component_driver img_prl_out_component = {
+ .name = "img-prl-out"
+};
+
+static int img_prl_out_probe(struct platform_device *pdev)
+{
+ struct img_prl_out *prl;
+ struct resource *res;
+ void __iomem *base;
+ int ret;
+ struct device *dev = &pdev->dev;
+
+ prl = devm_kzalloc(&pdev->dev, sizeof(*prl), GFP_KERNEL);
+ if (!prl)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, prl);
+
+ prl->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ prl->base = base;
+
+ prl->rst = devm_reset_control_get(&pdev->dev, "rst");
+ if (IS_ERR(prl->rst)) {
+ if (PTR_ERR(prl->rst) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "No top level reset found\n");
+ return PTR_ERR(prl->rst);
+ }
+
+ prl->clk_sys = devm_clk_get(&pdev->dev, "sys");
+ if (IS_ERR(prl->clk_sys)) {
+ if (PTR_ERR(prl->clk_sys) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to acquire clock 'sys'\n");
+ return PTR_ERR(prl->clk_sys);
+ }
+
+ prl->clk_ref = devm_clk_get(&pdev->dev, "ref");
+ if (IS_ERR(prl->clk_ref)) {
+ if (PTR_ERR(prl->clk_ref) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to acquire clock 'ref'\n");
+ return PTR_ERR(prl->clk_ref);
+ }
+
+ ret = clk_prepare_enable(prl->clk_sys);
+ if (ret)
+ return ret;
+
+ img_prl_out_writel(prl, IMG_PRL_OUT_CTL_EDGE_MASK, IMG_PRL_OUT_CTL);
+ img_prl_out_reset(prl);
+
+ pm_runtime_enable(&pdev->dev);
+ if (!pm_runtime_enabled(&pdev->dev)) {
+ ret = img_prl_out_resume(&pdev->dev);
+ if (ret)
+ goto err_pm_disable;
+ }
+
+ prl->dma_data.addr = res->start + IMG_PRL_OUT_TX_FIFO;
+ prl->dma_data.addr_width = 4;
+ prl->dma_data.maxburst = 4;
+
+ ret = devm_snd_soc_register_component(&pdev->dev,
+ &img_prl_out_component,
+ &img_prl_out_dai, 1);
+ if (ret)
+ goto err_suspend;
+
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+ if (ret)
+ goto err_suspend;
+
+ return 0;
+
+err_suspend:
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ img_prl_out_suspend(&pdev->dev);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ clk_disable_unprepare(prl->clk_sys);
+
+ return ret;
+}
+
+static int img_prl_out_dev_remove(struct platform_device *pdev)
+{
+ struct img_prl_out *prl = platform_get_drvdata(pdev);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ img_prl_out_suspend(&pdev->dev);
+
+ clk_disable_unprepare(prl->clk_sys);
+
+ return 0;
+}
+
+static const struct of_device_id img_prl_out_of_match[] = {
+ { .compatible = "img,parallel-out" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, img_prl_out_of_match);
+
+static const struct dev_pm_ops img_prl_out_pm_ops = {
+ SET_RUNTIME_PM_OPS(img_prl_out_suspend,
+ img_prl_out_resume, NULL)
+};
+
+static struct platform_driver img_prl_out_driver = {
+ .driver = {
+ .name = "img-parallel-out",
+ .of_match_table = img_prl_out_of_match,
+ .pm = &img_prl_out_pm_ops
+ },
+ .probe = img_prl_out_probe,
+ .remove = img_prl_out_dev_remove
+};
+module_platform_driver(img_prl_out_driver);
+
+MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
+MODULE_DESCRIPTION("IMG Parallel Output Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/img/img-spdif-in.c b/sound/soc/img/img-spdif-in.c
new file mode 100644
index 000000000000..4d9953d318af
--- /dev/null
+++ b/sound/soc/img/img-spdif-in.c
@@ -0,0 +1,806 @@
+/*
+ * IMG SPDIF input controller driver
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define IMG_SPDIF_IN_RX_FIFO_OFFSET 0
+
+#define IMG_SPDIF_IN_CTL 0x4
+#define IMG_SPDIF_IN_CTL_LOCKLO_MASK 0xff
+#define IMG_SPDIF_IN_CTL_LOCKLO_SHIFT 0
+#define IMG_SPDIF_IN_CTL_LOCKHI_MASK 0xff00
+#define IMG_SPDIF_IN_CTL_LOCKHI_SHIFT 8
+#define IMG_SPDIF_IN_CTL_TRK_MASK 0xff0000
+#define IMG_SPDIF_IN_CTL_TRK_SHIFT 16
+#define IMG_SPDIF_IN_CTL_SRD_MASK 0x70000000
+#define IMG_SPDIF_IN_CTL_SRD_SHIFT 28
+#define IMG_SPDIF_IN_CTL_SRT_MASK BIT(31)
+
+#define IMG_SPDIF_IN_STATUS 0x8
+#define IMG_SPDIF_IN_STATUS_SAM_MASK 0x7000
+#define IMG_SPDIF_IN_STATUS_SAM_SHIFT 12
+#define IMG_SPDIF_IN_STATUS_LOCK_MASK BIT(15)
+#define IMG_SPDIF_IN_STATUS_LOCK_SHIFT 15
+
+#define IMG_SPDIF_IN_CLKGEN 0x1c
+#define IMG_SPDIF_IN_CLKGEN_NOM_MASK 0x3ff
+#define IMG_SPDIF_IN_CLKGEN_NOM_SHIFT 0
+#define IMG_SPDIF_IN_CLKGEN_HLD_MASK 0x3ff0000
+#define IMG_SPDIF_IN_CLKGEN_HLD_SHIFT 16
+
+#define IMG_SPDIF_IN_CSL 0x20
+
+#define IMG_SPDIF_IN_CSH 0x24
+#define IMG_SPDIF_IN_CSH_MASK 0xff
+#define IMG_SPDIF_IN_CSH_SHIFT 0
+
+#define IMG_SPDIF_IN_SOFT_RESET 0x28
+#define IMG_SPDIF_IN_SOFT_RESET_MASK BIT(0)
+
+#define IMG_SPDIF_IN_ACLKGEN_START 0x2c
+#define IMG_SPDIF_IN_ACLKGEN_NOM_MASK 0x3ff
+#define IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT 0
+#define IMG_SPDIF_IN_ACLKGEN_HLD_MASK 0xffc00
+#define IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT 10
+#define IMG_SPDIF_IN_ACLKGEN_TRK_MASK 0xff00000
+#define IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT 20
+
+#define IMG_SPDIF_IN_NUM_ACLKGEN 4
+
+struct img_spdif_in {
+ spinlock_t lock;
+ void __iomem *base;
+ struct clk *clk_sys;
+ struct snd_dmaengine_dai_dma_data dma_data;
+ struct device *dev;
+ unsigned int trk;
+ bool multi_freq;
+ int lock_acquire;
+ int lock_release;
+ unsigned int single_freq;
+ unsigned int multi_freqs[IMG_SPDIF_IN_NUM_ACLKGEN];
+ bool active;
+
+ /* Write-only registers */
+ unsigned int aclkgen_regs[IMG_SPDIF_IN_NUM_ACLKGEN];
+};
+
+static inline void img_spdif_in_writel(struct img_spdif_in *spdif,
+ u32 val, u32 reg)
+{
+ writel(val, spdif->base + reg);
+}
+
+static inline u32 img_spdif_in_readl(struct img_spdif_in *spdif, u32 reg)
+{
+ return readl(spdif->base + reg);
+}
+
+static inline void img_spdif_in_aclkgen_writel(struct img_spdif_in *spdif,
+ u32 index)
+{
+ img_spdif_in_writel(spdif, spdif->aclkgen_regs[index],
+ IMG_SPDIF_IN_ACLKGEN_START + (index * 0x4));
+}
+
+static int img_spdif_in_check_max_rate(struct img_spdif_in *spdif,
+ unsigned int sample_rate, unsigned long *actual_freq)
+{
+ unsigned long min_freq, freq_t;
+
+ /* Clock rate must be at least 24x the bit rate */
+ min_freq = sample_rate * 2 * 32 * 24;
+
+ freq_t = clk_get_rate(spdif->clk_sys);
+
+ if (freq_t < min_freq)
+ return -EINVAL;
+
+ *actual_freq = freq_t;
+
+ return 0;
+}
+
+static int img_spdif_in_do_clkgen_calc(unsigned int rate, unsigned int *pnom,
+ unsigned int *phld, unsigned long clk_rate)
+{
+ unsigned int ori, nom, hld;
+
+ /*
+ * Calculate oversampling ratio, nominal phase increment and hold
+ * increment for the given rate / frequency
+ */
+
+ if (!rate)
+ return -EINVAL;
+
+ ori = clk_rate / (rate * 64);
+
+ if (!ori)
+ return -EINVAL;
+
+ nom = (4096 / ori) + 1;
+ do
+ hld = 4096 - (--nom * (ori - 1));
+ while (hld < 120);
+
+ *pnom = nom;
+ *phld = hld;
+
+ return 0;
+}
+
+static int img_spdif_in_do_clkgen_single(struct img_spdif_in *spdif,
+ unsigned int rate)
+{
+ unsigned int nom, hld;
+ unsigned long flags, clk_rate;
+ int ret = 0;
+ u32 reg;
+
+ ret = img_spdif_in_check_max_rate(spdif, rate, &clk_rate);
+ if (ret)
+ return ret;
+
+ ret = img_spdif_in_do_clkgen_calc(rate, &nom, &hld, clk_rate);
+ if (ret)
+ return ret;
+
+ reg = (nom << IMG_SPDIF_IN_CLKGEN_NOM_SHIFT) &
+ IMG_SPDIF_IN_CLKGEN_NOM_MASK;
+ reg |= (hld << IMG_SPDIF_IN_CLKGEN_HLD_SHIFT) &
+ IMG_SPDIF_IN_CLKGEN_HLD_MASK;
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ if (spdif->active) {
+ spin_unlock_irqrestore(&spdif->lock, flags);
+ return -EBUSY;
+ }
+
+ img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CLKGEN);
+
+ spdif->single_freq = rate;
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static int img_spdif_in_do_clkgen_multi(struct img_spdif_in *spdif,
+ unsigned int multi_freqs[])
+{
+ unsigned int nom, hld, rate, max_rate = 0;
+ unsigned long flags, clk_rate;
+ int i, ret = 0;
+ u32 reg, trk_reg, temp_regs[IMG_SPDIF_IN_NUM_ACLKGEN];
+
+ for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++)
+ if (multi_freqs[i] > max_rate)
+ max_rate = multi_freqs[i];
+
+ ret = img_spdif_in_check_max_rate(spdif, max_rate, &clk_rate);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) {
+ rate = multi_freqs[i];
+
+ ret = img_spdif_in_do_clkgen_calc(rate, &nom, &hld, clk_rate);
+ if (ret)
+ return ret;
+
+ reg = (nom << IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT) &
+ IMG_SPDIF_IN_ACLKGEN_NOM_MASK;
+ reg |= (hld << IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT) &
+ IMG_SPDIF_IN_ACLKGEN_HLD_MASK;
+ temp_regs[i] = reg;
+ }
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ if (spdif->active) {
+ spin_unlock_irqrestore(&spdif->lock, flags);
+ return -EBUSY;
+ }
+
+ trk_reg = spdif->trk << IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT;
+
+ for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) {
+ spdif->aclkgen_regs[i] = temp_regs[i] | trk_reg;
+ img_spdif_in_aclkgen_writel(spdif, i);
+ }
+
+ spdif->multi_freq = true;
+ spdif->multi_freqs[0] = multi_freqs[0];
+ spdif->multi_freqs[1] = multi_freqs[1];
+ spdif->multi_freqs[2] = multi_freqs[2];
+ spdif->multi_freqs[3] = multi_freqs[3];
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static int img_spdif_in_iec958_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+
+ return 0;
+}
+
+static int img_spdif_in_get_status_mask(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.iec958.status[0] = 0xff;
+ ucontrol->value.iec958.status[1] = 0xff;
+ ucontrol->value.iec958.status[2] = 0xff;
+ ucontrol->value.iec958.status[3] = 0xff;
+ ucontrol->value.iec958.status[4] = 0xff;
+
+ return 0;
+}
+
+static int img_spdif_in_get_status(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ u32 reg;
+
+ reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CSL);
+ ucontrol->value.iec958.status[0] = reg & 0xff;
+ ucontrol->value.iec958.status[1] = (reg >> 8) & 0xff;
+ ucontrol->value.iec958.status[2] = (reg >> 16) & 0xff;
+ ucontrol->value.iec958.status[3] = (reg >> 24) & 0xff;
+ reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CSH);
+ ucontrol->value.iec958.status[4] = (reg & IMG_SPDIF_IN_CSH_MASK)
+ >> IMG_SPDIF_IN_CSH_SHIFT;
+
+ return 0;
+}
+
+static int img_spdif_in_info_multi_freq(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = IMG_SPDIF_IN_NUM_ACLKGEN;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = LONG_MAX;
+
+ return 0;
+}
+
+static int img_spdif_in_get_multi_freq(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned long flags;
+
+ spin_lock_irqsave(&spdif->lock, flags);
+ if (spdif->multi_freq) {
+ ucontrol->value.integer.value[0] = spdif->multi_freqs[0];
+ ucontrol->value.integer.value[1] = spdif->multi_freqs[1];
+ ucontrol->value.integer.value[2] = spdif->multi_freqs[2];
+ ucontrol->value.integer.value[3] = spdif->multi_freqs[3];
+ } else {
+ ucontrol->value.integer.value[0] = 0;
+ ucontrol->value.integer.value[1] = 0;
+ ucontrol->value.integer.value[2] = 0;
+ ucontrol->value.integer.value[3] = 0;
+ }
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static int img_spdif_in_set_multi_freq(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned int multi_freqs[IMG_SPDIF_IN_NUM_ACLKGEN];
+ bool multi_freq;
+ unsigned long flags;
+
+ if ((ucontrol->value.integer.value[0] == 0) &&
+ (ucontrol->value.integer.value[1] == 0) &&
+ (ucontrol->value.integer.value[2] == 0) &&
+ (ucontrol->value.integer.value[3] == 0)) {
+ multi_freq = false;
+ } else {
+ multi_freqs[0] = ucontrol->value.integer.value[0];
+ multi_freqs[1] = ucontrol->value.integer.value[1];
+ multi_freqs[2] = ucontrol->value.integer.value[2];
+ multi_freqs[3] = ucontrol->value.integer.value[3];
+ multi_freq = true;
+ }
+
+ if (multi_freq)
+ return img_spdif_in_do_clkgen_multi(spdif, multi_freqs);
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ if (spdif->active) {
+ spin_unlock_irqrestore(&spdif->lock, flags);
+ return -EBUSY;
+ }
+
+ spdif->multi_freq = false;
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static int img_spdif_in_info_lock_freq(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = LONG_MAX;
+
+ return 0;
+}
+
+static int img_spdif_in_get_lock_freq(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uc)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ u32 reg;
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_STATUS);
+ if (reg & IMG_SPDIF_IN_STATUS_LOCK_MASK) {
+ if (spdif->multi_freq) {
+ i = ((reg & IMG_SPDIF_IN_STATUS_SAM_MASK) >>
+ IMG_SPDIF_IN_STATUS_SAM_SHIFT) - 1;
+ uc->value.integer.value[0] = spdif->multi_freqs[i];
+ } else {
+ uc->value.integer.value[0] = spdif->single_freq;
+ }
+ } else {
+ uc->value.integer.value[0] = 0;
+ }
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static int img_spdif_in_info_trk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 255;
+
+ return 0;
+}
+
+static int img_spdif_in_get_trk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+
+ ucontrol->value.integer.value[0] = spdif->trk;
+
+ return 0;
+}
+
+static int img_spdif_in_set_trk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned long flags;
+ int i;
+ u32 reg;
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ if (spdif->active) {
+ spin_unlock_irqrestore(&spdif->lock, flags);
+ return -EBUSY;
+ }
+
+ spdif->trk = ucontrol->value.integer.value[0];
+
+ reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
+ reg &= ~IMG_SPDIF_IN_CTL_TRK_MASK;
+ reg |= spdif->trk << IMG_SPDIF_IN_CTL_TRK_SHIFT;
+ img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
+
+ for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) {
+ spdif->aclkgen_regs[i] = (spdif->aclkgen_regs[i] &
+ ~IMG_SPDIF_IN_ACLKGEN_TRK_MASK) |
+ (spdif->trk << IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT);
+
+ img_spdif_in_aclkgen_writel(spdif, i);
+ }
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static int img_spdif_in_info_lock(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = -128;
+ uinfo->value.integer.max = 127;
+
+ return 0;
+}
+
+static int img_spdif_in_get_lock_acquire(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+
+ ucontrol->value.integer.value[0] = spdif->lock_acquire;
+
+ return 0;
+}
+
+static int img_spdif_in_set_lock_acquire(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ if (spdif->active) {
+ spin_unlock_irqrestore(&spdif->lock, flags);
+ return -EBUSY;
+ }
+
+ spdif->lock_acquire = ucontrol->value.integer.value[0];
+
+ reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
+ reg &= ~IMG_SPDIF_IN_CTL_LOCKHI_MASK;
+ reg |= (spdif->lock_acquire << IMG_SPDIF_IN_CTL_LOCKHI_SHIFT) &
+ IMG_SPDIF_IN_CTL_LOCKHI_MASK;
+ img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static int img_spdif_in_get_lock_release(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+
+ ucontrol->value.integer.value[0] = spdif->lock_release;
+
+ return 0;
+}
+
+static int img_spdif_in_set_lock_release(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ if (spdif->active) {
+ spin_unlock_irqrestore(&spdif->lock, flags);
+ return -EBUSY;
+ }
+
+ spdif->lock_release = ucontrol->value.integer.value[0];
+
+ reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
+ reg &= ~IMG_SPDIF_IN_CTL_LOCKLO_MASK;
+ reg |= (spdif->lock_release << IMG_SPDIF_IN_CTL_LOCKLO_SHIFT) &
+ IMG_SPDIF_IN_CTL_LOCKLO_MASK;
+ img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static struct snd_kcontrol_new img_spdif_in_controls[] = {
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
+ .info = img_spdif_in_iec958_info,
+ .get = img_spdif_in_get_status_mask
+ },
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
+ .info = img_spdif_in_iec958_info,
+ .get = img_spdif_in_get_status
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SPDIF In Multi Frequency Acquire",
+ .info = img_spdif_in_info_multi_freq,
+ .get = img_spdif_in_get_multi_freq,
+ .put = img_spdif_in_set_multi_freq
+ },
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SPDIF In Lock Frequency",
+ .info = img_spdif_in_info_lock_freq,
+ .get = img_spdif_in_get_lock_freq
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SPDIF In Lock TRK",
+ .info = img_spdif_in_info_trk,
+ .get = img_spdif_in_get_trk,
+ .put = img_spdif_in_set_trk
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SPDIF In Lock Acquire Threshold",
+ .info = img_spdif_in_info_lock,
+ .get = img_spdif_in_get_lock_acquire,
+ .put = img_spdif_in_set_lock_acquire
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SPDIF In Lock Release Threshold",
+ .info = img_spdif_in_info_lock,
+ .get = img_spdif_in_get_lock_release,
+ .put = img_spdif_in_set_lock_release
+ }
+};
+
+static int img_spdif_in_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ unsigned long flags;
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
+ int ret = 0;
+ u32 reg;
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
+ if (spdif->multi_freq)
+ reg &= ~IMG_SPDIF_IN_CTL_SRD_MASK;
+ else
+ reg |= (1UL << IMG_SPDIF_IN_CTL_SRD_SHIFT);
+ reg |= IMG_SPDIF_IN_CTL_SRT_MASK;
+ img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
+ spdif->active = true;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
+ reg &= ~IMG_SPDIF_IN_CTL_SRT_MASK;
+ img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
+ spdif->active = false;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return ret;
+}
+
+static int img_spdif_in_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
+ unsigned int rate, channels;
+ snd_pcm_format_t format;
+
+ rate = params_rate(params);
+ channels = params_channels(params);
+ format = params_format(params);
+
+ if (format != SNDRV_PCM_FORMAT_S32_LE)
+ return -EINVAL;
+
+ if (channels != 2)
+ return -EINVAL;
+
+ return img_spdif_in_do_clkgen_single(spdif, rate);
+}
+
+static const struct snd_soc_dai_ops img_spdif_in_dai_ops = {
+ .trigger = img_spdif_in_trigger,
+ .hw_params = img_spdif_in_hw_params
+};
+
+static int img_spdif_in_dai_probe(struct snd_soc_dai *dai)
+{
+ struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
+
+ snd_soc_dai_init_dma_data(dai, NULL, &spdif->dma_data);
+
+ snd_soc_add_dai_controls(dai, img_spdif_in_controls,
+ ARRAY_SIZE(img_spdif_in_controls));
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver img_spdif_in_dai = {
+ .probe = img_spdif_in_dai_probe,
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE
+ },
+ .ops = &img_spdif_in_dai_ops
+};
+
+static const struct snd_soc_component_driver img_spdif_in_component = {
+ .name = "img-spdif-in"
+};
+
+static int img_spdif_in_probe(struct platform_device *pdev)
+{
+ struct img_spdif_in *spdif;
+ struct resource *res;
+ void __iomem *base;
+ int ret;
+ struct reset_control *rst;
+ u32 reg;
+ struct device *dev = &pdev->dev;
+
+ spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL);
+ if (!spdif)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, spdif);
+
+ spdif->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ spdif->base = base;
+
+ spdif->clk_sys = devm_clk_get(dev, "sys");
+ if (IS_ERR(spdif->clk_sys)) {
+ if (PTR_ERR(spdif->clk_sys) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to acquire clock 'sys'\n");
+ return PTR_ERR(spdif->clk_sys);
+ }
+
+ ret = clk_prepare_enable(spdif->clk_sys);
+ if (ret)
+ return ret;
+
+ rst = devm_reset_control_get(&pdev->dev, "rst");
+ if (IS_ERR(rst)) {
+ if (PTR_ERR(rst) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_clk_disable;
+ }
+ dev_dbg(dev, "No top level reset found\n");
+ img_spdif_in_writel(spdif, IMG_SPDIF_IN_SOFT_RESET_MASK,
+ IMG_SPDIF_IN_SOFT_RESET);
+ img_spdif_in_writel(spdif, 0, IMG_SPDIF_IN_SOFT_RESET);
+ } else {
+ reset_control_assert(rst);
+ reset_control_deassert(rst);
+ }
+
+ spin_lock_init(&spdif->lock);
+
+ spdif->dma_data.addr = res->start + IMG_SPDIF_IN_RX_FIFO_OFFSET;
+ spdif->dma_data.addr_width = 4;
+ spdif->dma_data.maxburst = 4;
+ spdif->trk = 0x80;
+ spdif->lock_acquire = 4;
+ spdif->lock_release = -128;
+
+ reg = (spdif->lock_acquire << IMG_SPDIF_IN_CTL_LOCKHI_SHIFT) &
+ IMG_SPDIF_IN_CTL_LOCKHI_MASK;
+ reg |= (spdif->lock_release << IMG_SPDIF_IN_CTL_LOCKLO_SHIFT) &
+ IMG_SPDIF_IN_CTL_LOCKLO_MASK;
+ reg |= (spdif->trk << IMG_SPDIF_IN_CTL_TRK_SHIFT) &
+ IMG_SPDIF_IN_CTL_TRK_MASK;
+ img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
+
+ ret = devm_snd_soc_register_component(&pdev->dev,
+ &img_spdif_in_component, &img_spdif_in_dai, 1);
+ if (ret)
+ goto err_clk_disable;
+
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+ if (ret)
+ goto err_clk_disable;
+
+ return 0;
+
+err_clk_disable:
+ clk_disable_unprepare(spdif->clk_sys);
+
+ return ret;
+}
+
+static int img_spdif_in_dev_remove(struct platform_device *pdev)
+{
+ struct img_spdif_in *spdif = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(spdif->clk_sys);
+
+ return 0;
+}
+
+static const struct of_device_id img_spdif_in_of_match[] = {
+ { .compatible = "img,spdif-in" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, img_spdif_in_of_match);
+
+static struct platform_driver img_spdif_in_driver = {
+ .driver = {
+ .name = "img-spdif-in",
+ .of_match_table = img_spdif_in_of_match
+ },
+ .probe = img_spdif_in_probe,
+ .remove = img_spdif_in_dev_remove
+};
+module_platform_driver(img_spdif_in_driver);
+
+MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
+MODULE_DESCRIPTION("IMG SPDIF Input driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/img/img-spdif-out.c b/sound/soc/img/img-spdif-out.c
new file mode 100644
index 000000000000..08f93a5dadfe
--- /dev/null
+++ b/sound/soc/img/img-spdif-out.c
@@ -0,0 +1,441 @@
+/*
+ * IMG SPDIF output controller driver
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define IMG_SPDIF_OUT_TX_FIFO 0x0
+
+#define IMG_SPDIF_OUT_CTL 0x4
+#define IMG_SPDIF_OUT_CTL_FS_MASK BIT(4)
+#define IMG_SPDIF_OUT_CTL_CLK_MASK BIT(2)
+#define IMG_SPDIF_OUT_CTL_SRT_MASK BIT(0)
+
+#define IMG_SPDIF_OUT_CSL 0x14
+
+#define IMG_SPDIF_OUT_CSH_UV 0x18
+#define IMG_SPDIF_OUT_CSH_UV_CSH_SHIFT 0
+#define IMG_SPDIF_OUT_CSH_UV_CSH_MASK 0xff
+
+struct img_spdif_out {
+ spinlock_t lock;
+ void __iomem *base;
+ struct clk *clk_sys;
+ struct clk *clk_ref;
+ struct snd_dmaengine_dai_dma_data dma_data;
+ struct device *dev;
+ struct reset_control *rst;
+};
+
+static int img_spdif_out_suspend(struct device *dev)
+{
+ struct img_spdif_out *spdif = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(spdif->clk_ref);
+
+ return 0;
+}
+
+static int img_spdif_out_resume(struct device *dev)
+{
+ struct img_spdif_out *spdif = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(spdif->clk_ref);
+ if (ret) {
+ dev_err(dev, "clk_enable failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline void img_spdif_out_writel(struct img_spdif_out *spdif, u32 val,
+ u32 reg)
+{
+ writel(val, spdif->base + reg);
+}
+
+static inline u32 img_spdif_out_readl(struct img_spdif_out *spdif, u32 reg)
+{
+ return readl(spdif->base + reg);
+}
+
+static void img_spdif_out_reset(struct img_spdif_out *spdif)
+{
+ u32 ctl, status_low, status_high;
+
+ ctl = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CTL) &
+ ~IMG_SPDIF_OUT_CTL_SRT_MASK;
+ status_low = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CSL);
+ status_high = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CSH_UV);
+
+ reset_control_assert(spdif->rst);
+ reset_control_deassert(spdif->rst);
+
+ img_spdif_out_writel(spdif, ctl, IMG_SPDIF_OUT_CTL);
+ img_spdif_out_writel(spdif, status_low, IMG_SPDIF_OUT_CSL);
+ img_spdif_out_writel(spdif, status_high, IMG_SPDIF_OUT_CSH_UV);
+}
+
+static int img_spdif_out_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+
+ return 0;
+}
+
+static int img_spdif_out_get_status_mask(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.iec958.status[0] = 0xff;
+ ucontrol->value.iec958.status[1] = 0xff;
+ ucontrol->value.iec958.status[2] = 0xff;
+ ucontrol->value.iec958.status[3] = 0xff;
+ ucontrol->value.iec958.status[4] = 0xff;
+
+ return 0;
+}
+
+static int img_spdif_out_get_status(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ u32 reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ reg = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CSL);
+ ucontrol->value.iec958.status[0] = reg & 0xff;
+ ucontrol->value.iec958.status[1] = (reg >> 8) & 0xff;
+ ucontrol->value.iec958.status[2] = (reg >> 16) & 0xff;
+ ucontrol->value.iec958.status[3] = (reg >> 24) & 0xff;
+
+ reg = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CSH_UV);
+ ucontrol->value.iec958.status[4] =
+ (reg & IMG_SPDIF_OUT_CSH_UV_CSH_MASK) >>
+ IMG_SPDIF_OUT_CSH_UV_CSH_SHIFT;
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static int img_spdif_out_set_status(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(cpu_dai);
+ u32 reg;
+ unsigned long flags;
+
+ reg = ((u32)ucontrol->value.iec958.status[3] << 24);
+ reg |= ((u32)ucontrol->value.iec958.status[2] << 16);
+ reg |= ((u32)ucontrol->value.iec958.status[1] << 8);
+ reg |= (u32)ucontrol->value.iec958.status[0];
+
+ spin_lock_irqsave(&spdif->lock, flags);
+
+ img_spdif_out_writel(spdif, reg, IMG_SPDIF_OUT_CSL);
+
+ reg = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CSH_UV);
+ reg &= ~IMG_SPDIF_OUT_CSH_UV_CSH_MASK;
+ reg |= (u32)ucontrol->value.iec958.status[4] <<
+ IMG_SPDIF_OUT_CSH_UV_CSH_SHIFT;
+ img_spdif_out_writel(spdif, reg, IMG_SPDIF_OUT_CSH_UV);
+
+ spin_unlock_irqrestore(&spdif->lock, flags);
+
+ return 0;
+}
+
+static struct snd_kcontrol_new img_spdif_out_controls[] = {
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
+ .info = img_spdif_out_info,
+ .get = img_spdif_out_get_status_mask
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
+ .info = img_spdif_out_info,
+ .get = img_spdif_out_get_status,
+ .put = img_spdif_out_set_status
+ }
+};
+
+static int img_spdif_out_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(dai);
+ u32 reg;
+ unsigned long flags;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ reg = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CTL);
+ reg |= IMG_SPDIF_OUT_CTL_SRT_MASK;
+ img_spdif_out_writel(spdif, reg, IMG_SPDIF_OUT_CTL);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ spin_lock_irqsave(&spdif->lock, flags);
+ img_spdif_out_reset(spdif);
+ spin_unlock_irqrestore(&spdif->lock, flags);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int img_spdif_out_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(dai);
+ unsigned int channels;
+ long pre_div_a, pre_div_b, diff_a, diff_b, rate, clk_rate;
+ u32 reg;
+ snd_pcm_format_t format;
+
+ rate = params_rate(params);
+ format = params_format(params);
+ channels = params_channels(params);
+
+ dev_dbg(spdif->dev, "hw_params rate %ld channels %u format %u\n",
+ rate, channels, format);
+
+ if (format != SNDRV_PCM_FORMAT_S32_LE)
+ return -EINVAL;
+
+ if (channels != 2)
+ return -EINVAL;
+
+ pre_div_a = clk_round_rate(spdif->clk_ref, rate * 256);
+ if (pre_div_a < 0)
+ return pre_div_a;
+ pre_div_b = clk_round_rate(spdif->clk_ref, rate * 384);
+ if (pre_div_b < 0)
+ return pre_div_b;
+
+ diff_a = abs((pre_div_a / 256) - rate);
+ diff_b = abs((pre_div_b / 384) - rate);
+
+ /* If diffs are equal, use lower clock rate */
+ if (diff_a > diff_b)
+ clk_set_rate(spdif->clk_ref, pre_div_b);
+ else
+ clk_set_rate(spdif->clk_ref, pre_div_a);
+
+ /*
+ * Another driver (eg machine driver) may have rejected the above
+ * change. Get the current rate and set the register bit according to
+ * the new min diff
+ */
+ clk_rate = clk_get_rate(spdif->clk_ref);
+
+ diff_a = abs((clk_rate / 256) - rate);
+ diff_b = abs((clk_rate / 384) - rate);
+
+ reg = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CTL);
+ if (diff_a <= diff_b)
+ reg &= ~IMG_SPDIF_OUT_CTL_CLK_MASK;
+ else
+ reg |= IMG_SPDIF_OUT_CTL_CLK_MASK;
+ img_spdif_out_writel(spdif, reg, IMG_SPDIF_OUT_CTL);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops img_spdif_out_dai_ops = {
+ .trigger = img_spdif_out_trigger,
+ .hw_params = img_spdif_out_hw_params
+};
+
+static int img_spdif_out_dai_probe(struct snd_soc_dai *dai)
+{
+ struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(dai);
+
+ snd_soc_dai_init_dma_data(dai, &spdif->dma_data, NULL);
+
+ snd_soc_add_dai_controls(dai, img_spdif_out_controls,
+ ARRAY_SIZE(img_spdif_out_controls));
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver img_spdif_out_dai = {
+ .probe = img_spdif_out_dai_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE
+ },
+ .ops = &img_spdif_out_dai_ops
+};
+
+static const struct snd_soc_component_driver img_spdif_out_component = {
+ .name = "img-spdif-out"
+};
+
+static int img_spdif_out_probe(struct platform_device *pdev)
+{
+ struct img_spdif_out *spdif;
+ struct resource *res;
+ void __iomem *base;
+ int ret;
+ struct device *dev = &pdev->dev;
+
+ spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL);
+ if (!spdif)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, spdif);
+
+ spdif->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ spdif->base = base;
+
+ spdif->rst = devm_reset_control_get(&pdev->dev, "rst");
+ if (IS_ERR(spdif->rst)) {
+ if (PTR_ERR(spdif->rst) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "No top level reset found\n");
+ return PTR_ERR(spdif->rst);
+ }
+
+ spdif->clk_sys = devm_clk_get(&pdev->dev, "sys");
+ if (IS_ERR(spdif->clk_sys)) {
+ if (PTR_ERR(spdif->clk_sys) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to acquire clock 'sys'\n");
+ return PTR_ERR(spdif->clk_sys);
+ }
+
+ spdif->clk_ref = devm_clk_get(&pdev->dev, "ref");
+ if (IS_ERR(spdif->clk_ref)) {
+ if (PTR_ERR(spdif->clk_ref) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to acquire clock 'ref'\n");
+ return PTR_ERR(spdif->clk_ref);
+ }
+
+ ret = clk_prepare_enable(spdif->clk_sys);
+ if (ret)
+ return ret;
+
+ img_spdif_out_writel(spdif, IMG_SPDIF_OUT_CTL_FS_MASK,
+ IMG_SPDIF_OUT_CTL);
+
+ img_spdif_out_reset(spdif);
+
+ pm_runtime_enable(&pdev->dev);
+ if (!pm_runtime_enabled(&pdev->dev)) {
+ ret = img_spdif_out_resume(&pdev->dev);
+ if (ret)
+ goto err_pm_disable;
+ }
+
+ spin_lock_init(&spdif->lock);
+
+ spdif->dma_data.addr = res->start + IMG_SPDIF_OUT_TX_FIFO;
+ spdif->dma_data.addr_width = 4;
+ spdif->dma_data.maxburst = 4;
+
+ ret = devm_snd_soc_register_component(&pdev->dev,
+ &img_spdif_out_component,
+ &img_spdif_out_dai, 1);
+ if (ret)
+ goto err_suspend;
+
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+ if (ret)
+ goto err_suspend;
+
+ dev_dbg(&pdev->dev, "Probe successful\n");
+
+ return 0;
+
+err_suspend:
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ img_spdif_out_suspend(&pdev->dev);
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ clk_disable_unprepare(spdif->clk_sys);
+
+ return ret;
+}
+
+static int img_spdif_out_dev_remove(struct platform_device *pdev)
+{
+ struct img_spdif_out *spdif = platform_get_drvdata(pdev);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ img_spdif_out_suspend(&pdev->dev);
+
+ clk_disable_unprepare(spdif->clk_sys);
+
+ return 0;
+}
+
+static const struct of_device_id img_spdif_out_of_match[] = {
+ { .compatible = "img,spdif-out" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, img_spdif_out_of_match);
+
+static const struct dev_pm_ops img_spdif_out_pm_ops = {
+ SET_RUNTIME_PM_OPS(img_spdif_out_suspend,
+ img_spdif_out_resume, NULL)
+};
+
+static struct platform_driver img_spdif_out_driver = {
+ .driver = {
+ .name = "img-spdif-out",
+ .of_match_table = img_spdif_out_of_match,
+ .pm = &img_spdif_out_pm_ops
+ },
+ .probe = img_spdif_out_probe,
+ .remove = img_spdif_out_dev_remove
+};
+module_platform_driver(img_spdif_out_driver);
+
+MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
+MODULE_DESCRIPTION("IMG SPDIF Output driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/img/pistachio-internal-dac.c b/sound/soc/img/pistachio-internal-dac.c
new file mode 100644
index 000000000000..162a0fd68c7b
--- /dev/null
+++ b/sound/soc/img/pistachio-internal-dac.c
@@ -0,0 +1,287 @@
+/*
+ * Pistachio internal dac driver
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ *
+ * Author: Damien Horsley <Damien.Horsley@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define PISTACHIO_INTERNAL_DAC_CTRL 0x40
+#define PISTACHIO_INTERNAL_DAC_CTRL_PWR_SEL_MASK 0x2
+#define PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK 0x1
+
+#define PISTACHIO_INTERNAL_DAC_SRST 0x44
+#define PISTACHIO_INTERNAL_DAC_SRST_MASK 0x1
+
+#define PISTACHIO_INTERNAL_DAC_GTI_CTRL 0x48
+#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_SHIFT 0
+#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_MASK 0xFFF
+#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK 0x1000
+#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_SHIFT 13
+#define PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_MASK 0x1FE000
+
+#define PISTACHIO_INTERNAL_DAC_PWR 0x1
+#define PISTACHIO_INTERNAL_DAC_PWR_MASK 0x1
+
+#define PISTACHIO_INTERNAL_DAC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+/* codec private data */
+struct pistachio_internal_dac {
+ struct regmap *regmap;
+ struct regulator *supply;
+ bool mute;
+};
+
+static const struct snd_kcontrol_new pistachio_internal_dac_snd_controls[] = {
+ SOC_SINGLE("Playback Switch", PISTACHIO_INTERNAL_DAC_CTRL, 2, 1, 1)
+};
+
+static const struct snd_soc_dapm_widget pistachio_internal_dac_widgets[] = {
+ SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_OUTPUT("AOUTL"),
+ SND_SOC_DAPM_OUTPUT("AOUTR"),
+};
+
+static const struct snd_soc_dapm_route pistachio_internal_dac_routes[] = {
+ { "AOUTL", NULL, "DAC" },
+ { "AOUTR", NULL, "DAC" },
+};
+
+static void pistachio_internal_dac_reg_writel(struct regmap *top_regs,
+ u32 val, u32 reg)
+{
+ regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
+ PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_MASK,
+ reg << PISTACHIO_INTERNAL_DAC_GTI_CTRL_ADDR_SHIFT);
+
+ regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
+ PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_MASK,
+ val << PISTACHIO_INTERNAL_DAC_GTI_CTRL_WDATA_SHIFT);
+
+ regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
+ PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK,
+ PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK);
+
+ regmap_update_bits(top_regs, PISTACHIO_INTERNAL_DAC_GTI_CTRL,
+ PISTACHIO_INTERNAL_DAC_GTI_CTRL_WE_MASK, 0);
+}
+
+static void pistachio_internal_dac_pwr_off(struct pistachio_internal_dac *dac)
+{
+ regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_CTRL,
+ PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK,
+ PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK);
+
+ pistachio_internal_dac_reg_writel(dac->regmap, 0,
+ PISTACHIO_INTERNAL_DAC_PWR);
+}
+
+static void pistachio_internal_dac_pwr_on(struct pistachio_internal_dac *dac)
+{
+ regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_SRST,
+ PISTACHIO_INTERNAL_DAC_SRST_MASK,
+ PISTACHIO_INTERNAL_DAC_SRST_MASK);
+
+ regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_SRST,
+ PISTACHIO_INTERNAL_DAC_SRST_MASK, 0);
+
+ pistachio_internal_dac_reg_writel(dac->regmap,
+ PISTACHIO_INTERNAL_DAC_PWR_MASK,
+ PISTACHIO_INTERNAL_DAC_PWR);
+
+ regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_CTRL,
+ PISTACHIO_INTERNAL_DAC_CTRL_PWRDN_MASK, 0);
+}
+
+static struct snd_soc_dai_driver pistachio_internal_dac_dais[] = {
+ {
+ .name = "pistachio_internal_dac",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = PISTACHIO_INTERNAL_DAC_FORMATS,
+ }
+ },
+};
+
+static int pistachio_internal_dac_codec_probe(struct snd_soc_codec *codec)
+{
+ struct pistachio_internal_dac *dac = snd_soc_codec_get_drvdata(codec);
+
+ snd_soc_codec_init_regmap(codec, dac->regmap);
+
+ return 0;
+}
+
+static const struct snd_soc_codec_driver pistachio_internal_dac_driver = {
+ .probe = pistachio_internal_dac_codec_probe,
+ .idle_bias_off = true,
+ .controls = pistachio_internal_dac_snd_controls,
+ .num_controls = ARRAY_SIZE(pistachio_internal_dac_snd_controls),
+ .dapm_widgets = pistachio_internal_dac_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(pistachio_internal_dac_widgets),
+ .dapm_routes = pistachio_internal_dac_routes,
+ .num_dapm_routes = ARRAY_SIZE(pistachio_internal_dac_routes),
+};
+
+static int pistachio_internal_dac_probe(struct platform_device *pdev)
+{
+ struct pistachio_internal_dac *dac;
+ int ret, voltage;
+ struct device *dev = &pdev->dev;
+ u32 reg;
+
+ dac = devm_kzalloc(dev, sizeof(*dac), GFP_KERNEL);
+
+ if (!dac)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, dac);
+
+ dac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "img,cr-top");
+ if (IS_ERR(dac->regmap))
+ return PTR_ERR(dac->regmap);
+
+ dac->supply = devm_regulator_get(dev, "VDD");
+ if (IS_ERR(dac->supply)) {
+ ret = PTR_ERR(dac->supply);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to acquire supply 'VDD-supply': %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_enable(dac->supply);
+ if (ret) {
+ dev_err(dev, "failed to enable supply: %d\n", ret);
+ return ret;
+ }
+
+ voltage = regulator_get_voltage(dac->supply);
+
+ switch (voltage) {
+ case 1800000:
+ reg = 0;
+ break;
+ case 3300000:
+ reg = PISTACHIO_INTERNAL_DAC_CTRL_PWR_SEL_MASK;
+ break;
+ default:
+ dev_err(dev, "invalid voltage: %d\n", voltage);
+ ret = -EINVAL;
+ goto err_regulator;
+ }
+
+ regmap_update_bits(dac->regmap, PISTACHIO_INTERNAL_DAC_CTRL,
+ PISTACHIO_INTERNAL_DAC_CTRL_PWR_SEL_MASK, reg);
+
+ pistachio_internal_dac_pwr_off(dac);
+ pistachio_internal_dac_pwr_on(dac);
+
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_idle(dev);
+
+ ret = snd_soc_register_codec(dev, &pistachio_internal_dac_driver,
+ pistachio_internal_dac_dais,
+ ARRAY_SIZE(pistachio_internal_dac_dais));
+ if (ret) {
+ dev_err(dev, "failed to register codec: %d\n", ret);
+ goto err_pwr;
+ }
+
+ return 0;
+
+err_pwr:
+ pm_runtime_disable(&pdev->dev);
+ pistachio_internal_dac_pwr_off(dac);
+err_regulator:
+ regulator_disable(dac->supply);
+
+ return ret;
+}
+
+static int pistachio_internal_dac_remove(struct platform_device *pdev)
+{
+ struct pistachio_internal_dac *dac = dev_get_drvdata(&pdev->dev);
+
+ snd_soc_unregister_codec(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pistachio_internal_dac_pwr_off(dac);
+ regulator_disable(dac->supply);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int pistachio_internal_dac_rt_resume(struct device *dev)
+{
+ struct pistachio_internal_dac *dac = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_enable(dac->supply);
+ if (ret) {
+ dev_err(dev, "failed to enable supply: %d\n", ret);
+ return ret;
+ }
+
+ pistachio_internal_dac_pwr_on(dac);
+
+ return 0;
+}
+
+static int pistachio_internal_dac_rt_suspend(struct device *dev)
+{
+ struct pistachio_internal_dac *dac = dev_get_drvdata(dev);
+
+ pistachio_internal_dac_pwr_off(dac);
+
+ regulator_disable(dac->supply);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops pistachio_internal_dac_pm_ops = {
+ SET_RUNTIME_PM_OPS(pistachio_internal_dac_rt_suspend,
+ pistachio_internal_dac_rt_resume, NULL)
+};
+
+static const struct of_device_id pistachio_internal_dac_of_match[] = {
+ { .compatible = "img,pistachio-internal-dac" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pistachio_internal_dac_of_match);
+
+static struct platform_driver pistachio_internal_dac_plat_driver = {
+ .driver = {
+ .name = "img-pistachio-internal-dac",
+ .of_match_table = pistachio_internal_dac_of_match,
+ .pm = &pistachio_internal_dac_pm_ops
+ },
+ .probe = pistachio_internal_dac_probe,
+ .remove = pistachio_internal_dac_remove
+};
+module_platform_driver(pistachio_internal_dac_plat_driver);
+
+MODULE_DESCRIPTION("Pistachio Internal DAC driver");
+MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index d430ef5a4f38..803f95e40679 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -24,6 +24,7 @@ config SND_SST_IPC_PCI
config SND_SST_IPC_ACPI
tristate
select SND_SST_IPC
+ select SND_SOC_INTEL_SST
depends on ACPI
config SND_SOC_INTEL_SST
@@ -43,7 +44,7 @@ config SND_SOC_INTEL_BAYTRAIL
config SND_SOC_INTEL_HASWELL_MACH
tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
- depends on DW_DMAC_CORE
+ depends on DW_DMAC_CORE=y
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT5640
@@ -56,18 +57,19 @@ config SND_SOC_INTEL_HASWELL_MACH
config SND_SOC_INTEL_BYT_RT5640_MACH
tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec"
depends on X86_INTEL_LPSS && I2C
- depends on DW_DMAC_CORE
+ depends on DW_DMAC_CORE=y && (SND_SOC_INTEL_BYTCR_RT5640_MACH = n)
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_RT5640
help
This adds audio driver for Intel Baytrail platform based boards
- with the RT5640 audio codec.
+ with the RT5640 audio codec. This driver is deprecated, use
+ SND_SOC_INTEL_BYTCR_RT5640_MACH instead for better functionality
config SND_SOC_INTEL_BYT_MAX98090_MACH
tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec"
depends on X86_INTEL_LPSS && I2C
- depends on DW_DMAC_CORE
+ depends on DW_DMAC_CORE=y
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_MAX98090
@@ -79,7 +81,7 @@ config SND_SOC_INTEL_BROADWELL_MACH
tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
depends on X86_INTEL_LPSS && I2C && DW_DMAC && \
I2C_DESIGNWARE_PLATFORM
- depends on DW_DMAC_CORE
+ depends on DW_DMAC_CORE=y
select SND_SOC_INTEL_SST
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT286
@@ -90,14 +92,26 @@ config SND_SOC_INTEL_BROADWELL_MACH
If unsure select "N".
config SND_SOC_INTEL_BYTCR_RT5640_MACH
- tristate "ASoC Audio DSP Support for MID BYT Platform"
+ tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec"
depends on X86 && I2C
select SND_SOC_RT5640
select SND_SST_MFLD_PLATFORM
select SND_SST_IPC_ACPI
help
- This adds support for ASoC machine driver for Intel(R) MID Baytrail platform
- used as alsa device in audio substem in Intel(R) MID devices
+ This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
+ platforms with RT5640 audio codec.
+ Say Y if you have such a device
+ If unsure select "N".
+
+config SND_SOC_INTEL_BYTCR_RT5651_MACH
+ tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5651 codec"
+ depends on X86 && I2C
+ select SND_SOC_RT5651
+ select SND_SST_MFLD_PLATFORM
+ select SND_SST_IPC_ACPI
+ help
+ This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
+ platforms with RT5651 audio codec.
Say Y if you have such a device
If unsure select "N".
@@ -154,3 +168,31 @@ config SND_SOC_INTEL_SKL_RT286_MACH
with RT286 I2S audio codec.
Say Y if you have such a device
If unsure select "N".
+
+config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
+ tristate "ASoC Audio driver for SKL with NAU88L25 and SSM4567 in I2S Mode"
+ depends on X86_INTEL_LPSS && I2C
+ select SND_SOC_INTEL_SST
+ select SND_SOC_INTEL_SKYLAKE
+ select SND_SOC_NAU8825
+ select SND_SOC_SSM4567
+ select SND_SOC_DMIC
+ help
+ This adds support for ASoC Onboard Codec I2S machine driver. This will
+ create an alsa sound card for NAU88L25 + SSM4567.
+ Say Y if you have such a device
+ If unsure select "N".
+
+config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
+ tristate "ASoC Audio driver for SKL with NAU88L25 and MAX98357A in I2S Mode"
+ depends on X86_INTEL_LPSS && I2C
+ select SND_SOC_INTEL_SST
+ select SND_SOC_INTEL_SKYLAKE
+ select SND_SOC_NAU8825
+ select SND_SOC_MAX98357A
+ select SND_SOC_DMIC
+ help
+ This adds support for ASoC Onboard Codec I2S machine driver. This will
+ create an alsa sound card for NAU88L25 + MAX98357A.
+ Say Y if you have such a device
+ If unsure select "N".
diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c
index d55388e082e1..b97e6adcf1b2 100644
--- a/sound/soc/intel/atom/sst-atom-controls.c
+++ b/sound/soc/intel/atom/sst-atom-controls.c
@@ -443,7 +443,7 @@ static int sst_gain_get(struct snd_kcontrol *kcontrol,
break;
case SST_GAIN_MUTE:
- ucontrol->value.integer.value[0] = gv->mute ? 1 : 0;
+ ucontrol->value.integer.value[0] = gv->mute ? 0 : 1;
break;
case SST_GAIN_RAMP_DURATION:
@@ -479,7 +479,7 @@ static int sst_gain_put(struct snd_kcontrol *kcontrol,
break;
case SST_GAIN_MUTE:
- gv->mute = !!ucontrol->value.integer.value[0];
+ gv->mute = !ucontrol->value.integer.value[0];
dev_dbg(cmpnt->dev, "%s: Mute %d\n", mc->pname, gv->mute);
break;
@@ -1109,6 +1109,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"media0_in", NULL, "Compress Playback"},
{"media1_in", NULL, "Headset Playback"},
{"media2_in", NULL, "pcm0_out"},
+ {"media3_in", NULL, "Deepbuffer Playback"},
{"media0_out mix 0", "media0_in Switch", "media0_in"},
{"media0_out mix 0", "media1_in Switch", "media1_in"},
diff --git a/sound/soc/intel/atom/sst-atom-controls.h b/sound/soc/intel/atom/sst-atom-controls.h
index 93de8045d4e1..e0113112f668 100644
--- a/sound/soc/intel/atom/sst-atom-controls.h
+++ b/sound/soc/intel/atom/sst-atom-controls.h
@@ -28,6 +28,7 @@
enum {
MERR_DPCM_AUDIO = 0,
+ MERR_DPCM_DEEP_BUFFER,
MERR_DPCM_COMPR,
};
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 0487cfaac538..55c33dc76ce4 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -98,6 +98,7 @@ static struct sst_dev_stream_map dpcm_strm_map[] = {
{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
{MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
+ {MERR_DPCM_DEEP_BUFFER, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA3_IN, SST_TASK_ID_MEDIA, 0},
};
static int sst_media_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
@@ -500,14 +501,25 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
.channels_min = SST_STEREO,
.channels_max = SST_STEREO,
.rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
.capture = {
.stream_name = "Headset Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+ },
+},
+{
+ .name = "deepbuffer-cpu-dai",
+ .ops = &sst_media_dai_ops,
+ .playback = {
+ .stream_name = "Deepbuffer Playback",
+ .channels_min = SST_STEREO,
+ .channels_max = SST_STEREO,
+ .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
},
{
@@ -516,10 +528,6 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
.ops = &sst_compr_dai_ops,
.playback = {
.stream_name = "Compress Playback",
- .channels_min = SST_STEREO,
- .channels_max = SST_STEREO,
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
},
},
/* BE CPU Dais */
@@ -760,15 +768,15 @@ static int sst_platform_remove(struct platform_device *pdev)
static int sst_soc_prepare(struct device *dev)
{
struct sst_data *drv = dev_get_drvdata(dev);
- int i;
+ struct snd_soc_pcm_runtime *rtd;
/* suspend all pcms first */
snd_soc_suspend(drv->soc_card->dev);
snd_soc_poweroff(drv->soc_card->dev);
/* set the SSPs to idle */
- for (i = 0; i < drv->soc_card->num_rtd; i++) {
- struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
+ list_for_each_entry(rtd, &drv->soc_card->rtd_list, list) {
+ struct snd_soc_dai *dai = rtd->cpu_dai;
if (dai->active) {
send_ssp_cmd(dai, dai->name, 0);
@@ -782,11 +790,11 @@ static int sst_soc_prepare(struct device *dev)
static void sst_soc_complete(struct device *dev)
{
struct sst_data *drv = dev_get_drvdata(dev);
- int i;
+ struct snd_soc_pcm_runtime *rtd;
/* restart SSPs */
- for (i = 0; i < drv->soc_card->num_rtd; i++) {
- struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
+ list_for_each_entry(rtd, &drv->soc_card->rtd_list, list) {
+ struct snd_soc_dai *dai = rtd->cpu_dai;
if (dai->active) {
sst_handle_vb_timer(dai, true);
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
index bb19b5801466..4fce03fc1870 100644
--- a/sound/soc/intel/atom/sst/sst_acpi.c
+++ b/sound/soc/intel/atom/sst/sst_acpi.c
@@ -40,18 +40,9 @@
#include <acpi/acpi_bus.h>
#include "../sst-mfld-platform.h"
#include "../../common/sst-dsp.h"
+#include "../../common/sst-acpi.h"
#include "sst.h"
-struct sst_machines {
- char *codec_id;
- char board[32];
- char machine[32];
- void (*machine_quirk)(void);
- char firmware[FW_NAME_SIZE];
- struct sst_platform_info *pdata;
-
-};
-
/* LPE viewpoint addresses */
#define SST_BYT_IRAM_PHY_START 0xff2c0000
#define SST_BYT_IRAM_PHY_END 0xff2d4000
@@ -223,37 +214,16 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx)
return 0;
}
-static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
- void *context, void **ret)
-{
- *(bool *)context = true;
- return AE_OK;
-}
-
-static struct sst_machines *sst_acpi_find_machine(
- struct sst_machines *machines)
-{
- struct sst_machines *mach;
- bool found = false;
-
- for (mach = machines; mach->codec_id; mach++)
- if (ACPI_SUCCESS(acpi_get_devices(mach->codec_id,
- sst_acpi_mach_match,
- &found, NULL)) && found)
- return mach;
-
- return NULL;
-}
-
static int sst_acpi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret = 0;
struct intel_sst_drv *ctx;
const struct acpi_device_id *id;
- struct sst_machines *mach;
+ struct sst_acpi_mach *mach;
struct platform_device *mdev;
struct platform_device *plat_dev;
+ struct sst_platform_info *pdata;
unsigned int dev_id;
id = acpi_match_device(dev->driver->acpi_match_table, dev);
@@ -261,12 +231,13 @@ static int sst_acpi_probe(struct platform_device *pdev)
return -ENODEV;
dev_dbg(dev, "for %s", id->id);
- mach = (struct sst_machines *)id->driver_data;
+ mach = (struct sst_acpi_mach *)id->driver_data;
mach = sst_acpi_find_machine(mach);
if (mach == NULL) {
dev_err(dev, "No matching machine driver found\n");
return -ENODEV;
}
+ pdata = mach->pdata;
ret = kstrtouint(id->id, 16, &dev_id);
if (ret < 0) {
@@ -276,16 +247,23 @@ static int sst_acpi_probe(struct platform_device *pdev)
dev_dbg(dev, "ACPI device id: %x\n", dev_id);
- plat_dev = platform_device_register_data(dev, mach->pdata->platform, -1, NULL, 0);
+ plat_dev = platform_device_register_data(dev, pdata->platform, -1,
+ NULL, 0);
if (IS_ERR(plat_dev)) {
- dev_err(dev, "Failed to create machine device: %s\n", mach->pdata->platform);
+ dev_err(dev, "Failed to create machine device: %s\n",
+ pdata->platform);
return PTR_ERR(plat_dev);
}
- /* Create platform device for sst machine driver */
- mdev = platform_device_register_data(dev, mach->machine, -1, NULL, 0);
+ /*
+ * Create platform device for sst machine driver,
+ * pass machine info as pdata
+ */
+ mdev = platform_device_register_data(dev, mach->drv_name, -1,
+ (const void *)mach, sizeof(*mach));
if (IS_ERR(mdev)) {
- dev_err(dev, "Failed to create machine device: %s\n", mach->machine);
+ dev_err(dev, "Failed to create machine device: %s\n",
+ mach->drv_name);
return PTR_ERR(mdev);
}
@@ -294,8 +272,8 @@ static int sst_acpi_probe(struct platform_device *pdev)
return ret;
/* Fill sst platform data */
- ctx->pdata = mach->pdata;
- strcpy(ctx->firmware_name, mach->firmware);
+ ctx->pdata = pdata;
+ strcpy(ctx->firmware_name, mach->fw_filename);
ret = sst_platform_get_resources(ctx);
if (ret)
@@ -342,22 +320,28 @@ static int sst_acpi_remove(struct platform_device *pdev)
return 0;
}
-static struct sst_machines sst_acpi_bytcr[] = {
- {"10EC5640", "T100", "bytt100_rt5640", NULL, "intel/fw_sst_0f28.bin",
+static struct sst_acpi_mach sst_acpi_bytcr[] = {
+ {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
+ &byt_rvp_platform_data },
+ {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
+ &byt_rvp_platform_data },
+ {"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
+ &byt_rvp_platform_data },
+ {"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL,
&byt_rvp_platform_data },
{},
};
/* Cherryview-based platforms: CherryTrail and Braswell */
-static struct sst_machines sst_acpi_chv[] = {
- {"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "intel/fw_sst_22a8.bin",
+static struct sst_acpi_mach sst_acpi_chv[] = {
+ {"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
+ &chv_platform_data },
+ {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
&chv_platform_data },
- {"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin",
+ {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
&chv_platform_data },
- {"10EC5650", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin",
+ {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
&chv_platform_data },
- {"193C9890", "cht-bsw", "cht-bsw-max98090", NULL,
- "intel/fw_sst_22a8.bin", &chv_platform_data },
{},
};
diff --git a/sound/soc/intel/atom/sst/sst_stream.c b/sound/soc/intel/atom/sst/sst_stream.c
index a74c64c7053c..4ccc80e5e8cc 100644
--- a/sound/soc/intel/atom/sst/sst_stream.c
+++ b/sound/soc/intel/atom/sst/sst_stream.c
@@ -108,7 +108,7 @@ int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
str_id, pipe_id);
ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD,
IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param),
- &alloc_param, data, true, true, false, true);
+ &alloc_param, &data, true, true, false, true);
if (ret < 0) {
dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
diff --git a/sound/soc/intel/baytrail/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c
index 79547bec558b..4765ad474544 100644
--- a/sound/soc/intel/baytrail/sst-baytrail-pcm.c
+++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c
@@ -377,6 +377,8 @@ static int sst_byt_pcm_probe(struct snd_soc_platform *platform)
priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data),
GFP_KERNEL);
+ if (!priv_data)
+ return -ENOMEM;
priv_data->byt = plat_data->dsp;
snd_soc_platform_set_drvdata(platform, priv_data);
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index 371c4565cad8..3310c0f9c356 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -3,17 +3,23 @@ snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
snd-soc-sst-broadwell-objs := broadwell.o
snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
+snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
snd-soc-skl_rt286-objs := skl_rt286.o
+snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o
+snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o
obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
+obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o
+obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o
+obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 7a5c9a36c1db..9a1752df45a9 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -20,51 +20,76 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/acpi.h>
#include <linux/device.h>
+#include <linux/dmi.h>
#include <linux/slab.h>
-#include <linux/input.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/jack.h>
#include "../../codecs/rt5640.h"
#include "../atom/sst-atom-controls.h"
+#include "../common/sst-acpi.h"
-static const struct snd_soc_dapm_widget byt_dapm_widgets[] = {
+static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
- SND_SOC_DAPM_MIC("Int Mic", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
+ SND_SOC_DAPM_MIC("Internal Mic", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
};
-static const struct snd_soc_dapm_route byt_audio_map[] = {
- {"IN2P", NULL, "Headset Mic"},
- {"IN2N", NULL, "Headset Mic"},
- {"Headset Mic", NULL, "MICBIAS1"},
- {"IN1P", NULL, "MICBIAS1"},
- {"LDO2", NULL, "Int Mic"},
- {"Headphone", NULL, "HPOL"},
- {"Headphone", NULL, "HPOR"},
- {"Ext Spk", NULL, "SPOLP"},
- {"Ext Spk", NULL, "SPOLN"},
- {"Ext Spk", NULL, "SPORP"},
- {"Ext Spk", NULL, "SPORN"},
-
+static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
{"AIF1 Playback", NULL, "ssp2 Tx"},
{"ssp2 Tx", NULL, "codec_out0"},
{"ssp2 Tx", NULL, "codec_out1"},
{"codec_in0", NULL, "ssp2 Rx"},
{"codec_in1", NULL, "ssp2 Rx"},
{"ssp2 Rx", NULL, "AIF1 Capture"},
+
+ {"Headset Mic", NULL, "MICBIAS1"},
+ {"IN2P", NULL, "Headset Mic"},
+ {"Headphone", NULL, "HPOL"},
+ {"Headphone", NULL, "HPOR"},
+ {"Speaker", NULL, "SPOLP"},
+ {"Speaker", NULL, "SPOLN"},
+ {"Speaker", NULL, "SPORP"},
+ {"Speaker", NULL, "SPORN"},
+};
+
+static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {
+ {"DMIC1", NULL, "Internal Mic"},
+};
+
+static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {
+ {"DMIC2", NULL, "Internal Mic"},
+};
+
+static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
+ {"Internal Mic", NULL, "MICBIAS1"},
+ {"IN1P", NULL, "Internal Mic"},
+};
+
+enum {
+ BYT_RT5640_DMIC1_MAP,
+ BYT_RT5640_DMIC2_MAP,
+ BYT_RT5640_IN1_MAP,
};
-static const struct snd_kcontrol_new byt_mc_controls[] = {
+#define BYT_RT5640_MAP(quirk) ((quirk) & 0xff)
+#define BYT_RT5640_DMIC_EN BIT(16)
+
+static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP |
+ BYT_RT5640_DMIC_EN;
+
+static const struct snd_kcontrol_new byt_rt5640_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
- SOC_DAPM_PIN_SWITCH("Int Mic"),
- SOC_DAPM_PIN_SWITCH("Ext Spk"),
+ SOC_DAPM_PIN_SWITCH("Internal Mic"),
+ SOC_DAPM_PIN_SWITCH("Speaker"),
};
-static int byt_aif1_hw_params(struct snd_pcm_substream *substream,
+static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -92,7 +117,95 @@ static int byt_aif1_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static const struct snd_soc_pcm_stream byt_dai_params = {
+static int byt_rt5640_quirk_cb(const struct dmi_system_id *id)
+{
+ byt_rt5640_quirk = (unsigned long)id->driver_data;
+ return 1;
+}
+
+static const struct dmi_system_id byt_rt5640_quirk_table[] = {
+ {
+ .callback = byt_rt5640_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),
+ },
+ .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP,
+ },
+ {
+ .callback = byt_rt5640_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "DellInc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"),
+ },
+ .driver_data = (unsigned long *)(BYT_RT5640_DMIC2_MAP |
+ BYT_RT5640_DMIC_EN),
+ },
+ {
+ .callback = byt_rt5640_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
+ },
+ .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP,
+ },
+ {}
+};
+
+static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
+{
+ int ret;
+ struct snd_soc_codec *codec = runtime->codec;
+ struct snd_soc_card *card = runtime->card;
+ const struct snd_soc_dapm_route *custom_map;
+ int num_routes;
+
+ card->dapm.idle_bias_off = true;
+
+ rt5640_sel_asrc_clk_src(codec,
+ RT5640_DA_STEREO_FILTER |
+ RT5640_AD_STEREO_FILTER,
+ RT5640_CLK_SEL_ASRC);
+
+ ret = snd_soc_add_card_controls(card, byt_rt5640_controls,
+ ARRAY_SIZE(byt_rt5640_controls));
+ if (ret) {
+ dev_err(card->dev, "unable to add card controls\n");
+ return ret;
+ }
+
+ dmi_check_system(byt_rt5640_quirk_table);
+ switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
+ case BYT_RT5640_IN1_MAP:
+ custom_map = byt_rt5640_intmic_in1_map;
+ num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);
+ break;
+ case BYT_RT5640_DMIC2_MAP:
+ custom_map = byt_rt5640_intmic_dmic2_map;
+ num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);
+ break;
+ default:
+ custom_map = byt_rt5640_intmic_dmic1_map;
+ num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
+ }
+
+ ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
+ if (ret)
+ return ret;
+
+ if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) {
+ ret = rt5640_dmic_enable(codec, 0, 0);
+ if (ret)
+ return ret;
+ }
+
+ snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
+ snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
+
+ return ret;
+}
+
+static const struct snd_soc_pcm_stream byt_rt5640_dai_params = {
.formats = SNDRV_PCM_FMTBIT_S24_LE,
.rate_min = 48000,
.rate_max = 48000,
@@ -100,13 +213,14 @@ static const struct snd_soc_pcm_stream byt_dai_params = {
.channels_max = 2,
};
-static int byt_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
+ int ret;
/* The DSP will covert the FE rate to 48k, stereo, 24bits */
rate->min = rate->max = 48000;
@@ -114,24 +228,46 @@ static int byt_codec_fixup(struct snd_soc_pcm_runtime *rtd,
/* set SSP2 to 24-bit */
params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+ /*
+ * Default mode for SSP configuration is TDM 4 slot, override config
+ * with explicit setting to I2S 2ch 24-bit. The word length is set with
+ * dai_set_tdm_slot() since there is no other API exposed
+ */
+ ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBS_CFS
+ );
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
+ return ret;
+ }
+
return 0;
}
-static int byt_aif1_startup(struct snd_pcm_substream *substream)
+static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream)
{
return snd_pcm_hw_constraint_single(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE, 48000);
}
-static struct snd_soc_ops byt_aif1_ops = {
- .startup = byt_aif1_startup,
+static struct snd_soc_ops byt_rt5640_aif1_ops = {
+ .startup = byt_rt5640_aif1_startup,
};
-static struct snd_soc_ops byt_be_ssp2_ops = {
- .hw_params = byt_aif1_hw_params,
+static struct snd_soc_ops byt_rt5640_be_ssp2_ops = {
+ .hw_params = byt_rt5640_aif1_hw_params,
};
-static struct snd_soc_dai_link byt_dailink[] = {
+static struct snd_soc_dai_link byt_rt5640_dais[] = {
[MERR_DPCM_AUDIO] = {
.name = "Baytrail Audio Port",
.stream_name = "Baytrail Audio",
@@ -143,7 +279,20 @@ static struct snd_soc_dai_link byt_dailink[] = {
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
- .ops = &byt_aif1_ops,
+ .ops = &byt_rt5640_aif1_ops,
+ },
+ [MERR_DPCM_DEEP_BUFFER] = {
+ .name = "Deep-Buffer Audio Port",
+ .stream_name = "Deep-Buffer Audio",
+ .cpu_dai_name = "deepbuffer-cpu-dai",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .platform_name = "sst-mfld-platform",
+ .ignore_suspend = 1,
+ .nonatomic = true,
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &byt_rt5640_aif1_ops,
},
[MERR_DPCM_COMPR] = {
.name = "Baytrail Compressed Port",
@@ -161,58 +310,69 @@ static struct snd_soc_dai_link byt_dailink[] = {
.platform_name = "sst-mfld-platform",
.no_pcm = 1,
.codec_dai_name = "rt5640-aif1",
- .codec_name = "i2c-10EC5640:00",
+ .codec_name = "i2c-10EC5640:00", /* overwritten with HID */
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBS_CFS,
- .be_hw_params_fixup = byt_codec_fixup,
+ .be_hw_params_fixup = byt_rt5640_codec_fixup,
.ignore_suspend = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
- .ops = &byt_be_ssp2_ops,
+ .init = byt_rt5640_init,
+ .ops = &byt_rt5640_be_ssp2_ops,
},
};
/* SoC card */
-static struct snd_soc_card snd_soc_card_byt = {
- .name = "baytrailcraudio",
+static struct snd_soc_card byt_rt5640_card = {
+ .name = "bytcr-rt5640",
.owner = THIS_MODULE,
- .dai_link = byt_dailink,
- .num_links = ARRAY_SIZE(byt_dailink),
- .dapm_widgets = byt_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(byt_dapm_widgets),
- .dapm_routes = byt_audio_map,
- .num_dapm_routes = ARRAY_SIZE(byt_audio_map),
- .controls = byt_mc_controls,
- .num_controls = ARRAY_SIZE(byt_mc_controls),
+ .dai_link = byt_rt5640_dais,
+ .num_links = ARRAY_SIZE(byt_rt5640_dais),
+ .dapm_widgets = byt_rt5640_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),
+ .dapm_routes = byt_rt5640_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),
+ .fully_routed = true,
};
-static int snd_byt_mc_probe(struct platform_device *pdev)
+static char byt_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
+
+static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
{
int ret_val = 0;
+ struct sst_acpi_mach *mach;
/* register the soc card */
- snd_soc_card_byt.dev = &pdev->dev;
+ byt_rt5640_card.dev = &pdev->dev;
+ mach = byt_rt5640_card.dev->platform_data;
+
+ /* fixup codec name based on HID */
+ snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
+ "%s%s%s", "i2c-", mach->id, ":00");
+ byt_rt5640_dais[MERR_DPCM_COMPR+1].codec_name = byt_rt5640_codec_name;
+
+ ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
- ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_byt);
if (ret_val) {
- dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n", ret_val);
+ dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
+ ret_val);
return ret_val;
}
- platform_set_drvdata(pdev, &snd_soc_card_byt);
+ platform_set_drvdata(pdev, &byt_rt5640_card);
return ret_val;
}
-static struct platform_driver snd_byt_mc_driver = {
+static struct platform_driver snd_byt_rt5640_mc_driver = {
.driver = {
- .name = "bytt100_rt5640",
+ .name = "bytcr_rt5640",
.pm = &snd_soc_pm_ops,
},
- .probe = snd_byt_mc_probe,
+ .probe = snd_byt_rt5640_mc_probe,
};
-module_platform_driver(snd_byt_mc_driver);
+module_platform_driver(snd_byt_rt5640_mc_driver);
MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");
MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:bytt100_rt5640");
+MODULE_ALIAS("platform:bytcr_rt5640");
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
new file mode 100644
index 000000000000..1c95ccc886c4
--- /dev/null
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -0,0 +1,332 @@
+/*
+ * bytcr_rt5651.c - ASoc Machine driver for Intel Byt CR platform
+ * (derived from bytcr_rt5640.c)
+ *
+ * Copyright (C) 2015 Intel Corp
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/dmi.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include "../../codecs/rt5651.h"
+#include "../atom/sst-atom-controls.h"
+
+static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Internal Mic", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
+ {"AIF1 Playback", NULL, "ssp2 Tx"},
+ {"ssp2 Tx", NULL, "codec_out0"},
+ {"ssp2 Tx", NULL, "codec_out1"},
+ {"codec_in0", NULL, "ssp2 Rx"},
+ {"codec_in1", NULL, "ssp2 Rx"},
+ {"ssp2 Rx", NULL, "AIF1 Capture"},
+
+ {"Headset Mic", NULL, "micbias1"}, /* lowercase for rt5651 */
+ {"IN2P", NULL, "Headset Mic"},
+ {"Headphone", NULL, "HPOL"},
+ {"Headphone", NULL, "HPOR"},
+ {"Speaker", NULL, "LOUTL"},
+ {"Speaker", NULL, "LOUTR"},
+};
+
+static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic1_map[] = {
+ {"DMIC1", NULL, "Internal Mic"},
+};
+
+static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic2_map[] = {
+ {"DMIC2", NULL, "Internal Mic"},
+};
+
+static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
+ {"Internal Mic", NULL, "micbias1"},
+ {"IN1P", NULL, "Internal Mic"},
+};
+
+enum {
+ BYT_RT5651_DMIC1_MAP,
+ BYT_RT5651_DMIC2_MAP,
+ BYT_RT5651_IN1_MAP,
+};
+
+#define BYT_RT5651_MAP(quirk) ((quirk) & 0xff)
+#define BYT_RT5651_DMIC_EN BIT(16)
+
+static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC1_MAP |
+ BYT_RT5651_DMIC_EN;
+
+static const struct snd_kcontrol_new byt_rt5651_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphone"),
+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_DAPM_PIN_SWITCH("Internal Mic"),
+ SOC_DAPM_PIN_SWITCH("Speaker"),
+};
+
+static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+
+ snd_soc_dai_set_bclk_ratio(codec_dai, 50);
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
+ params_rate(params) * 512,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set codec clock %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_pll(codec_dai, 0, RT5651_PLL1_S_BCLK1,
+ params_rate(params) * 50,
+ params_rate(params) * 512);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dmi_system_id byt_rt5651_quirk_table[] = {
+ {}
+};
+
+static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
+{
+ int ret;
+ struct snd_soc_card *card = runtime->card;
+ const struct snd_soc_dapm_route *custom_map;
+ int num_routes;
+
+ card->dapm.idle_bias_off = true;
+
+ dmi_check_system(byt_rt5651_quirk_table);
+ switch (BYT_RT5651_MAP(byt_rt5651_quirk)) {
+ case BYT_RT5651_IN1_MAP:
+ custom_map = byt_rt5651_intmic_in1_map;
+ num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map);
+ break;
+ case BYT_RT5651_DMIC2_MAP:
+ custom_map = byt_rt5651_intmic_dmic2_map;
+ num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic2_map);
+ break;
+ default:
+ custom_map = byt_rt5651_intmic_dmic1_map;
+ num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic1_map);
+ }
+
+ ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
+ ARRAY_SIZE(byt_rt5651_controls));
+ if (ret) {
+ dev_err(card->dev, "unable to add card controls\n");
+ return ret;
+ }
+ snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
+ snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
+
+ return ret;
+}
+
+static const struct snd_soc_pcm_stream byt_rt5651_dai_params = {
+ .formats = SNDRV_PCM_FMTBIT_S24_LE,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+};
+
+static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ int ret;
+
+ /* The DSP will covert the FE rate to 48k, stereo, 24bits */
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = 2;
+
+ /* set SSP2 to 24-bit */
+ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+ /*
+ * Default mode for SSP configuration is TDM 4 slot, override config
+ * with explicit setting to I2S 2ch 24-bit. The word length is set with
+ * dai_set_tdm_slot() since there is no other API exposed
+ */
+ ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBS_CFS
+ );
+
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static unsigned int rates_48000[] = {
+ 48000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_48000 = {
+ .count = ARRAY_SIZE(rates_48000),
+ .list = rates_48000,
+};
+
+static int byt_rt5651_aif1_startup(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_48000);
+}
+
+static struct snd_soc_ops byt_rt5651_aif1_ops = {
+ .startup = byt_rt5651_aif1_startup,
+};
+
+static struct snd_soc_ops byt_rt5651_be_ssp2_ops = {
+ .hw_params = byt_rt5651_aif1_hw_params,
+};
+
+static struct snd_soc_dai_link byt_rt5651_dais[] = {
+ [MERR_DPCM_AUDIO] = {
+ .name = "Audio Port",
+ .stream_name = "Audio",
+ .cpu_dai_name = "media-cpu-dai",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .platform_name = "sst-mfld-platform",
+ .ignore_suspend = 1,
+ .nonatomic = true,
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .ops = &byt_rt5651_aif1_ops,
+ },
+ [MERR_DPCM_DEEP_BUFFER] = {
+ .name = "Deep-Buffer Audio Port",
+ .stream_name = "Deep-Buffer Audio",
+ .cpu_dai_name = "deepbuffer-cpu-dai",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .platform_name = "sst-mfld-platform",
+ .ignore_suspend = 1,
+ .nonatomic = true,
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &byt_rt5651_aif1_ops,
+ },
+ [MERR_DPCM_COMPR] = {
+ .name = "Compressed Port",
+ .stream_name = "Compress",
+ .cpu_dai_name = "compress-cpu-dai",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .platform_name = "sst-mfld-platform",
+ },
+ /* CODEC<->CODEC link */
+ /* back ends */
+ {
+ .name = "SSP2-Codec",
+ .be_id = 1,
+ .cpu_dai_name = "ssp2-port",
+ .platform_name = "sst-mfld-platform",
+ .no_pcm = 1,
+ .codec_dai_name = "rt5651-aif1",
+ .codec_name = "i2c-10EC5651:00",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBS_CFS,
+ .be_hw_params_fixup = byt_rt5651_codec_fixup,
+ .ignore_suspend = 1,
+ .nonatomic = true,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .init = byt_rt5651_init,
+ .ops = &byt_rt5651_be_ssp2_ops,
+ },
+};
+
+/* SoC card */
+static struct snd_soc_card byt_rt5651_card = {
+ .name = "bytcr-rt5651",
+ .owner = THIS_MODULE,
+ .dai_link = byt_rt5651_dais,
+ .num_links = ARRAY_SIZE(byt_rt5651_dais),
+ .dapm_widgets = byt_rt5651_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(byt_rt5651_widgets),
+ .dapm_routes = byt_rt5651_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(byt_rt5651_audio_map),
+ .fully_routed = true,
+};
+
+static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
+{
+ int ret_val = 0;
+
+ /* register the soc card */
+ byt_rt5651_card.dev = &pdev->dev;
+
+ ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);
+
+ if (ret_val) {
+ dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
+ ret_val);
+ return ret_val;
+ }
+ platform_set_drvdata(pdev, &byt_rt5651_card);
+ return ret_val;
+}
+
+static struct platform_driver snd_byt_rt5651_mc_driver = {
+ .driver = {
+ .name = "bytcr_rt5651",
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = snd_byt_rt5651_mc_probe,
+};
+
+module_platform_driver(snd_byt_rt5651_mc_driver);
+
+MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver for RT5651");
+MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:bytcr_rt5651");
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
index 4e2fcf188dd1..90588d6e64fc 100644
--- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c
+++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
@@ -41,12 +41,9 @@ struct cht_mc_private {
static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
{
- int i;
+ struct snd_soc_pcm_runtime *rtd;
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_pcm_runtime *rtd;
-
- rtd = card->rtd + i;
+ list_for_each_entry(rtd, &card->rtd_list, list) {
if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI,
strlen(CHT_CODEC_DAI)))
return rtd->codec_dai;
@@ -235,6 +232,18 @@ static struct snd_soc_dai_link cht_dailink[] = {
.dpcm_capture = 1,
.ops = &cht_aif1_ops,
},
+ [MERR_DPCM_DEEP_BUFFER] = {
+ .name = "Deep-Buffer Audio Port",
+ .stream_name = "Deep-Buffer Audio",
+ .cpu_dai_name = "deepbuffer-cpu-dai",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .platform_name = "sst-mfld-platform",
+ .nonatomic = true,
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &cht_aif1_ops,
+ },
[MERR_DPCM_COMPR] = {
.name = "Compressed Port",
.stream_name = "Compress",
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
index 38d65a3529c4..2d3afddb0a2e 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
@@ -47,12 +47,9 @@ struct cht_mc_private {
static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
{
- int i;
-
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_pcm_runtime *rtd;
- rtd = card->rtd + i;
+ list_for_each_entry(rtd, &card->rtd_list, list) {
if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI,
strlen(CHT_CODEC_DAI)))
return rtd->codec_dai;
@@ -263,6 +260,18 @@ static struct snd_soc_dai_link cht_dailink[] = {
.dpcm_capture = 1,
.ops = &cht_aif1_ops,
},
+ [MERR_DPCM_DEEP_BUFFER] = {
+ .name = "Deep-Buffer Audio Port",
+ .stream_name = "Deep-Buffer Audio",
+ .cpu_dai_name = "deepbuffer-cpu-dai",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .platform_name = "sst-mfld-platform",
+ .nonatomic = true,
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &cht_aif1_ops,
+ },
[MERR_DPCM_COMPR] = {
.name = "Compressed Port",
.stream_name = "Compress",
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c
index 5621ccd92992..2e5347f8f96c 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5672.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5672.c
@@ -46,12 +46,9 @@ static struct snd_soc_jack_pin cht_bsw_headset_pins[] = {
static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
{
- int i;
+ struct snd_soc_pcm_runtime *rtd;
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_pcm_runtime *rtd;
-
- rtd = card->rtd + i;
+ list_for_each_entry(rtd, &card->rtd_list, list) {
if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI,
strlen(CHT_CODEC_DAI)))
return rtd->codec_dai;
@@ -251,6 +248,18 @@ static struct snd_soc_dai_link cht_dailink[] = {
.dpcm_capture = 1,
.ops = &cht_aif1_ops,
},
+ [MERR_DPCM_DEEP_BUFFER] = {
+ .name = "Deep-Buffer Audio Port",
+ .stream_name = "Deep-Buffer Audio",
+ .cpu_dai_name = "deepbuffer-cpu-dai",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .platform_name = "sst-mfld-platform",
+ .nonatomic = true,
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .ops = &cht_aif1_ops,
+ },
[MERR_DPCM_COMPR] = {
.name = "Compressed Port",
.stream_name = "Compress",
diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
new file mode 100644
index 000000000000..ab7da9c304b2
--- /dev/null
+++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
@@ -0,0 +1,485 @@
+/*
+ * Intel Skylake I2S Machine Driver with MAXIM98357A
+ * and NAU88L25
+ *
+ * Copyright (C) 2015, Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "../../codecs/nau8825.h"
+
+#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi"
+#define SKL_MAXIM_CODEC_DAI "HiFi"
+
+static struct snd_soc_jack skylake_headset;
+static struct snd_soc_card skylake_audio_card;
+
+static inline struct snd_soc_dai *skl_get_codec_dai(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd;
+
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+
+ if (!strncmp(rtd->codec_dai->name, SKL_NUVOTON_CODEC_DAI,
+ strlen(SKL_NUVOTON_CODEC_DAI)))
+ return rtd->codec_dai;
+ }
+
+ return NULL;
+}
+
+static int platform_clock_control(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_soc_card *card = dapm->card;
+ struct snd_soc_dai *codec_dai;
+ int ret;
+
+ codec_dai = skl_get_codec_dai(card);
+ if (!codec_dai) {
+ dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n");
+ return -EIO;
+ }
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "set sysclk err = %d\n", ret);
+ return -EIO;
+ }
+ } else {
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "set sysclk err = %d\n", ret);
+ return -EIO;
+ }
+ }
+
+ return ret;
+}
+
+static const struct snd_kcontrol_new skylake_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_DAPM_PIN_SWITCH("Spk"),
+};
+
+static const struct snd_soc_dapm_widget skylake_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_SPK("Spk", NULL),
+ SND_SOC_DAPM_MIC("SoC DMIC", NULL),
+ SND_SOC_DAPM_SINK("WoV Sink"),
+ SND_SOC_DAPM_SPK("DP", NULL),
+ SND_SOC_DAPM_SPK("HDMI", NULL),
+ SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
+ platform_clock_control, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route skylake_map[] = {
+ /* HP jack connectors - unknown if we have jack detection */
+ { "Headphone Jack", NULL, "HPOL" },
+ { "Headphone Jack", NULL, "HPOR" },
+
+ /* speaker */
+ { "Spk", NULL, "Speaker" },
+
+ /* other jacks */
+ { "MIC", NULL, "Headset Mic" },
+ { "DMic", NULL, "SoC DMIC" },
+
+ {"WoV Sink", NULL, "hwd_in sink"},
+ {"HDMI", NULL, "hif5 Output"},
+ {"DP", NULL, "hif6 Output"},
+
+ /* CODEC BE connections */
+ { "HiFi Playback", NULL, "ssp0 Tx" },
+ { "ssp0 Tx", NULL, "codec0_out" },
+
+ { "Playback", NULL, "ssp1 Tx" },
+ { "ssp1 Tx", NULL, "codec1_out" },
+
+ { "codec0_in", NULL, "ssp1 Rx" },
+ { "ssp1 Rx", NULL, "Capture" },
+
+ /* DMIC */
+ { "dmic01_hifi", NULL, "DMIC01 Rx" },
+ { "DMIC01 Rx", NULL, "DMIC AIF" },
+ { "hifi1", NULL, "iDisp Tx"},
+ { "iDisp Tx", NULL, "iDisp_out"},
+ { "Headphone Jack", NULL, "Platform Clock" },
+ { "Headset Mic", NULL, "Platform Clock" },
+};
+
+static int skylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+ /* The ADSP will covert the FE rate to 48k, stereo */
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = 2;
+
+ /* set SSP0 to 24 bit */
+ snd_mask_none(fmt);
+ snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
+
+ return 0;
+}
+
+static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ int ret;
+ struct snd_soc_codec *codec = rtd->codec;
+
+ /*
+ * Headset buttons map to the google Reference headset.
+ * These can be configured by userspace.
+ */
+ ret = snd_soc_card_jack_new(&skylake_audio_card, "Headset Jack",
+ SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3, &skylake_headset,
+ NULL, 0);
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
+ return ret;
+ }
+
+ nau8825_enable_jack_detect(codec, &skylake_headset);
+
+ snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
+ snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink");
+
+ return ret;
+}
+
+static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dapm_context *dapm;
+ struct snd_soc_component *component = rtd->cpu_dai->component;
+
+ dapm = snd_soc_component_get_dapm(component);
+ snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
+
+ return 0;
+}
+
+static unsigned int rates[] = {
+ 48000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+};
+
+static unsigned int channels[] = {
+ 2,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+};
+
+static int skl_fe_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ /*
+ * On this platform for PCM device we support,
+ * 48Khz
+ * stereo
+ * 16 bit audio
+ */
+
+ runtime->hw.channels_max = 2;
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
+
+ snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+
+ return 0;
+}
+
+static const struct snd_soc_ops skylake_nau8825_fe_ops = {
+ .startup = skl_fe_startup,
+};
+
+static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN);
+
+ if (ret < 0)
+ dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
+
+ return ret;
+}
+
+static struct snd_soc_ops skylake_nau8825_ops = {
+ .hw_params = skylake_nau8825_hw_params,
+};
+
+static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ if (params_channels(params) == 2)
+ channels->min = channels->max = 2;
+ else
+ channels->min = channels->max = 4;
+
+ return 0;
+}
+
+static unsigned int channels_dmic[] = {
+ 2, 4,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
+ .count = ARRAY_SIZE(channels_dmic),
+ .list = channels_dmic,
+ .mask = 0,
+};
+
+static int skylake_dmic_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ runtime->hw.channels_max = 4;
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_dmic_channels);
+
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+}
+
+static struct snd_soc_ops skylake_dmic_ops = {
+ .startup = skylake_dmic_startup,
+};
+
+static unsigned int rates_16000[] = {
+ 16000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_16000 = {
+ .count = ARRAY_SIZE(rates_16000),
+ .list = rates_16000,
+};
+
+static int skylake_refcap_startup(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_16000);
+}
+
+static struct snd_soc_ops skylaye_refcap_ops = {
+ .startup = skylake_refcap_startup,
+};
+
+/* skylake digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link skylake_dais[] = {
+ /* Front End DAI links */
+ {
+ .name = "Skl Audio Port",
+ .stream_name = "Audio",
+ .cpu_dai_name = "System Pin",
+ .platform_name = "0000:00:1f.3",
+ .dynamic = 1,
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .nonatomic = 1,
+ .init = skylake_nau8825_fe_init,
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+ .dpcm_playback = 1,
+ .ops = &skylake_nau8825_fe_ops,
+ },
+ {
+ .name = "Skl Audio Capture Port",
+ .stream_name = "Audio Record",
+ .cpu_dai_name = "System Pin",
+ .platform_name = "0000:00:1f.3",
+ .dynamic = 1,
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .nonatomic = 1,
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+ .dpcm_capture = 1,
+ .ops = &skylake_nau8825_fe_ops,
+ },
+ {
+ .name = "Skl Audio Reference cap",
+ .stream_name = "Wake on Voice",
+ .cpu_dai_name = "Reference Pin",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .platform_name = "0000:00:1f.3",
+ .init = NULL,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ .nonatomic = 1,
+ .dynamic = 1,
+ .ops = &skylaye_refcap_ops,
+ },
+ {
+ .name = "Skl Audio DMIC cap",
+ .stream_name = "dmiccap",
+ .cpu_dai_name = "DMIC Pin",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .platform_name = "0000:00:1f.3",
+ .init = NULL,
+ .dpcm_capture = 1,
+ .nonatomic = 1,
+ .dynamic = 1,
+ .ops = &skylake_dmic_ops,
+ },
+ {
+ .name = "Skl HDMI Port",
+ .stream_name = "Hdmi",
+ .cpu_dai_name = "HDMI Pin",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .platform_name = "0000:00:1f.3",
+ .dpcm_playback = 1,
+ .init = NULL,
+ .nonatomic = 1,
+ .dynamic = 1,
+ },
+
+ /* Back End DAI links */
+ {
+ /* SSP0 - Codec */
+ .name = "SSP0-Codec",
+ .be_id = 0,
+ .cpu_dai_name = "SSP0 Pin",
+ .platform_name = "0000:00:1f.3",
+ .no_pcm = 1,
+ .codec_name = "MX98357A:00",
+ .codec_dai_name = SKL_MAXIM_CODEC_DAI,
+ .dai_fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .ignore_pmdown_time = 1,
+ .be_hw_params_fixup = skylake_ssp_fixup,
+ .dpcm_playback = 1,
+ },
+ {
+ /* SSP1 - Codec */
+ .name = "SSP1-Codec",
+ .be_id = 0,
+ .cpu_dai_name = "SSP1 Pin",
+ .platform_name = "0000:00:1f.3",
+ .no_pcm = 1,
+ .codec_name = "i2c-10508825:00",
+ .codec_dai_name = SKL_NUVOTON_CODEC_DAI,
+ .init = skylake_nau8825_codec_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .ignore_pmdown_time = 1,
+ .be_hw_params_fixup = skylake_ssp_fixup,
+ .ops = &skylake_nau8825_ops,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ },
+ {
+ .name = "dmic01",
+ .be_id = 1,
+ .cpu_dai_name = "DMIC01 Pin",
+ .codec_name = "dmic-codec",
+ .codec_dai_name = "dmic-hifi",
+ .platform_name = "0000:00:1f.3",
+ .be_hw_params_fixup = skylake_dmic_fixup,
+ .ignore_suspend = 1,
+ .dpcm_capture = 1,
+ .no_pcm = 1,
+ },
+ {
+ .name = "iDisp",
+ .be_id = 3,
+ .cpu_dai_name = "iDisp Pin",
+ .codec_name = "ehdaudio0D2",
+ .codec_dai_name = "intel-hdmi-hifi1",
+ .platform_name = "0000:00:1f.3",
+ .dpcm_playback = 1,
+ .no_pcm = 1,
+ },
+};
+
+/* skylake audio machine driver for SPT + NAU88L25 */
+static struct snd_soc_card skylake_audio_card = {
+ .name = "sklnau8825max",
+ .owner = THIS_MODULE,
+ .dai_link = skylake_dais,
+ .num_links = ARRAY_SIZE(skylake_dais),
+ .controls = skylake_controls,
+ .num_controls = ARRAY_SIZE(skylake_controls),
+ .dapm_widgets = skylake_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(skylake_widgets),
+ .dapm_routes = skylake_map,
+ .num_dapm_routes = ARRAY_SIZE(skylake_map),
+ .fully_routed = true,
+};
+
+static int skylake_audio_probe(struct platform_device *pdev)
+{
+ skylake_audio_card.dev = &pdev->dev;
+
+ return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card);
+}
+
+static struct platform_driver skylake_audio = {
+ .probe = skylake_audio_probe,
+ .driver = {
+ .name = "skl_nau88l25_max98357a_i2s",
+ .pm = &snd_soc_pm_ops,
+ },
+};
+
+module_platform_driver(skylake_audio)
+
+/* Module information */
+MODULE_DESCRIPTION("Audio Machine driver-NAU88L25 & MAX98357A in I2S mode");
+MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:skl_nau88l25_max98357a_i2s");
diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
new file mode 100644
index 000000000000..c071812f31e5
--- /dev/null
+++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
@@ -0,0 +1,536 @@
+/*
+ * Intel Skylake I2S Machine Driver for NAU88L25+SSM4567
+ *
+ * Copyright (C) 2015, Intel Corporation. All rights reserved.
+ *
+ * Modified from:
+ * Intel Skylake I2S Machine Driver for NAU88L25 and SSM4567
+ *
+ * Copyright (C) 2015, Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include "../../codecs/nau8825.h"
+
+#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi"
+#define SKL_SSM_CODEC_DAI "ssm4567-hifi"
+
+static struct snd_soc_jack skylake_headset;
+static struct snd_soc_card skylake_audio_card;
+
+static inline struct snd_soc_dai *skl_get_codec_dai(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd;
+
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+
+ if (!strncmp(rtd->codec_dai->name, SKL_NUVOTON_CODEC_DAI,
+ strlen(SKL_NUVOTON_CODEC_DAI)))
+ return rtd->codec_dai;
+ }
+
+ return NULL;
+}
+
+static const struct snd_kcontrol_new skylake_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
+ SOC_DAPM_PIN_SWITCH("Left Speaker"),
+ SOC_DAPM_PIN_SWITCH("Right Speaker"),
+};
+
+static int platform_clock_control(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_soc_card *card = dapm->card;
+ struct snd_soc_dai *codec_dai;
+ int ret;
+
+ codec_dai = skl_get_codec_dai(card);
+ if (!codec_dai) {
+ dev_err(card->dev, "Codec dai not found\n");
+ return -EIO;
+ }
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "set sysclk err = %d\n", ret);
+ return -EIO;
+ }
+ } else {
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "set sysclk err = %d\n", ret);
+ return -EIO;
+ }
+ }
+ return ret;
+}
+
+static const struct snd_soc_dapm_widget skylake_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_SPK("Left Speaker", NULL),
+ SND_SOC_DAPM_SPK("Right Speaker", NULL),
+ SND_SOC_DAPM_MIC("SoC DMIC", NULL),
+ SND_SOC_DAPM_SINK("WoV Sink"),
+ SND_SOC_DAPM_SPK("DP", NULL),
+ SND_SOC_DAPM_SPK("HDMI", NULL),
+ SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
+ platform_clock_control, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_route skylake_map[] = {
+ /* HP jack connectors - unknown if we have jack detection */
+ {"Headphone Jack", NULL, "HPOL"},
+ {"Headphone Jack", NULL, "HPOR"},
+
+ /* speaker */
+ {"Left Speaker", NULL, "Left OUT"},
+ {"Right Speaker", NULL, "Right OUT"},
+
+ /* other jacks */
+ {"MIC", NULL, "Headset Mic"},
+ {"DMic", NULL, "SoC DMIC"},
+
+ {"WoV Sink", NULL, "hwd_in sink"},
+
+ {"HDMI", NULL, "hif5 Output"},
+ {"DP", NULL, "hif6 Output"},
+ /* CODEC BE connections */
+ { "Left Playback", NULL, "ssp0 Tx"},
+ { "Right Playback", NULL, "ssp0 Tx"},
+ { "ssp0 Tx", NULL, "codec0_out"},
+
+ { "Playback", NULL, "ssp1 Tx"},
+ { "ssp1 Tx", NULL, "codec1_out"},
+
+ { "codec0_in", NULL, "ssp1 Rx" },
+ { "ssp1 Rx", NULL, "Capture" },
+
+ /* DMIC */
+ { "dmic01_hifi", NULL, "DMIC01 Rx" },
+ { "DMIC01 Rx", NULL, "DMIC AIF" },
+ { "hifi1", NULL, "iDisp Tx"},
+ { "iDisp Tx", NULL, "iDisp_out"},
+ { "Headphone Jack", NULL, "Platform Clock" },
+ { "Headset Mic", NULL, "Platform Clock" },
+};
+
+static struct snd_soc_codec_conf ssm4567_codec_conf[] = {
+ {
+ .dev_name = "i2c-INT343B:00",
+ .name_prefix = "Left",
+ },
+ {
+ .dev_name = "i2c-INT343B:01",
+ .name_prefix = "Right",
+ },
+};
+
+static struct snd_soc_dai_link_component ssm4567_codec_components[] = {
+ { /* Left */
+ .name = "i2c-INT343B:00",
+ .dai_name = SKL_SSM_CODEC_DAI,
+ },
+ { /* Right */
+ .name = "i2c-INT343B:01",
+ .dai_name = SKL_SSM_CODEC_DAI,
+ },
+};
+
+static int skylake_ssm4567_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ int ret;
+
+ /* Slot 1 for left */
+ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[0], 0x01, 0x01, 2, 48);
+ if (ret < 0)
+ return ret;
+
+ /* Slot 2 for right */
+ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[1], 0x02, 0x02, 2, 48);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+
+static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ int ret;
+ struct snd_soc_codec *codec = rtd->codec;
+
+ /*
+ * 4 buttons here map to the google Reference headset
+ * The use of these buttons can be decided by the user space.
+ */
+ ret = snd_soc_card_jack_new(&skylake_audio_card, "Headset Jack",
+ SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3, &skylake_headset,
+ NULL, 0);
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
+ return ret;
+ }
+
+ nau8825_enable_jack_detect(codec, &skylake_headset);
+
+ snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
+ snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink");
+
+ return ret;
+}
+
+static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dapm_context *dapm;
+ struct snd_soc_component *component = rtd->cpu_dai->component;
+
+ dapm = snd_soc_component_get_dapm(component);
+ snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
+
+ return 0;
+}
+
+static unsigned int rates[] = {
+ 48000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+};
+
+static unsigned int channels[] = {
+ 2,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+};
+
+static int skl_fe_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ /*
+ * on this platform for PCM device we support,
+ * 48Khz
+ * stereo
+ * 16 bit audio
+ */
+
+ runtime->hw.channels_max = 2;
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
+
+ snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+
+ return 0;
+}
+
+static const struct snd_soc_ops skylake_nau8825_fe_ops = {
+ .startup = skl_fe_startup,
+};
+
+static int skylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+ /* The ADSP will covert the FE rate to 48k, stereo */
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = 2;
+
+ /* set SSP0 to 24 bit */
+ snd_mask_none(fmt);
+ snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
+ return 0;
+}
+
+static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ if (params_channels(params) == 2)
+ channels->min = channels->max = 2;
+ else
+ channels->min = channels->max = 4;
+
+ return 0;
+}
+
+static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN);
+
+ if (ret < 0)
+ dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
+
+ return ret;
+}
+
+static struct snd_soc_ops skylake_nau8825_ops = {
+ .hw_params = skylake_nau8825_hw_params,
+};
+
+static unsigned int channels_dmic[] = {
+ 2, 4,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
+ .count = ARRAY_SIZE(channels_dmic),
+ .list = channels_dmic,
+ .mask = 0,
+};
+
+static int skylake_dmic_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ runtime->hw.channels_max = 4;
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_dmic_channels);
+
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+}
+
+static struct snd_soc_ops skylake_dmic_ops = {
+ .startup = skylake_dmic_startup,
+};
+
+static unsigned int rates_16000[] = {
+ 16000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_16000 = {
+ .count = ARRAY_SIZE(rates_16000),
+ .list = rates_16000,
+};
+
+static int skylake_refcap_startup(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_16000);
+}
+
+static struct snd_soc_ops skylaye_refcap_ops = {
+ .startup = skylake_refcap_startup,
+};
+
+/* skylake digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link skylake_dais[] = {
+ /* Front End DAI links */
+ {
+ .name = "Skl Audio Port",
+ .stream_name = "Audio",
+ .cpu_dai_name = "System Pin",
+ .platform_name = "0000:00:1f.3",
+ .dynamic = 1,
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .nonatomic = 1,
+ .init = skylake_nau8825_fe_init,
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+ .dpcm_playback = 1,
+ .ops = &skylake_nau8825_fe_ops,
+ },
+ {
+ .name = "Skl Audio Capture Port",
+ .stream_name = "Audio Record",
+ .cpu_dai_name = "System Pin",
+ .platform_name = "0000:00:1f.3",
+ .dynamic = 1,
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .nonatomic = 1,
+ .trigger = {
+ SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+ .dpcm_capture = 1,
+ .ops = &skylake_nau8825_fe_ops,
+ },
+ {
+ .name = "Skl Audio Reference cap",
+ .stream_name = "Wake on Voice",
+ .cpu_dai_name = "Reference Pin",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .platform_name = "0000:00:1f.3",
+ .init = NULL,
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ .nonatomic = 1,
+ .dynamic = 1,
+ .ops = &skylaye_refcap_ops,
+ },
+ {
+ .name = "Skl Audio DMIC cap",
+ .stream_name = "dmiccap",
+ .cpu_dai_name = "DMIC Pin",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .platform_name = "0000:00:1f.3",
+ .init = NULL,
+ .dpcm_capture = 1,
+ .nonatomic = 1,
+ .dynamic = 1,
+ .ops = &skylake_dmic_ops,
+ },
+ {
+ .name = "Skl HDMI Port",
+ .stream_name = "Hdmi",
+ .cpu_dai_name = "HDMI Pin",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .platform_name = "0000:00:1f.3",
+ .dpcm_playback = 1,
+ .init = NULL,
+ .nonatomic = 1,
+ .dynamic = 1,
+ },
+
+ /* Back End DAI links */
+ {
+ /* SSP0 - Codec */
+ .name = "SSP0-Codec",
+ .be_id = 0,
+ .cpu_dai_name = "SSP0 Pin",
+ .platform_name = "0000:00:1f.3",
+ .no_pcm = 1,
+ .codecs = ssm4567_codec_components,
+ .num_codecs = ARRAY_SIZE(ssm4567_codec_components),
+ .dai_fmt = SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .init = skylake_ssm4567_codec_init,
+ .ignore_pmdown_time = 1,
+ .be_hw_params_fixup = skylake_ssp_fixup,
+ .dpcm_playback = 1,
+ },
+ {
+ /* SSP1 - Codec */
+ .name = "SSP1-Codec",
+ .be_id = 0,
+ .cpu_dai_name = "SSP1 Pin",
+ .platform_name = "0000:00:1f.3",
+ .no_pcm = 1,
+ .codec_name = "i2c-10508825:00",
+ .codec_dai_name = SKL_NUVOTON_CODEC_DAI,
+ .init = skylake_nau8825_codec_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
+ .ignore_pmdown_time = 1,
+ .be_hw_params_fixup = skylake_ssp_fixup,
+ .ops = &skylake_nau8825_ops,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ },
+ {
+ .name = "dmic01",
+ .be_id = 1,
+ .cpu_dai_name = "DMIC01 Pin",
+ .codec_name = "dmic-codec",
+ .codec_dai_name = "dmic-hifi",
+ .platform_name = "0000:00:1f.3",
+ .ignore_suspend = 1,
+ .be_hw_params_fixup = skylake_dmic_fixup,
+ .dpcm_capture = 1,
+ .no_pcm = 1,
+ },
+ {
+ .name = "iDisp",
+ .be_id = 3,
+ .cpu_dai_name = "iDisp Pin",
+ .codec_name = "ehdaudio0D2",
+ .codec_dai_name = "intel-hdmi-hifi1",
+ .platform_name = "0000:00:1f.3",
+ .dpcm_playback = 1,
+ .no_pcm = 1,
+ },
+};
+
+/* skylake audio machine driver for SPT + NAU88L25 */
+static struct snd_soc_card skylake_audio_card = {
+ .name = "sklnau8825adi",
+ .owner = THIS_MODULE,
+ .dai_link = skylake_dais,
+ .num_links = ARRAY_SIZE(skylake_dais),
+ .controls = skylake_controls,
+ .num_controls = ARRAY_SIZE(skylake_controls),
+ .dapm_widgets = skylake_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(skylake_widgets),
+ .dapm_routes = skylake_map,
+ .num_dapm_routes = ARRAY_SIZE(skylake_map),
+ .codec_conf = ssm4567_codec_conf,
+ .num_configs = ARRAY_SIZE(ssm4567_codec_conf),
+ .fully_routed = true,
+};
+
+static int skylake_audio_probe(struct platform_device *pdev)
+{
+ skylake_audio_card.dev = &pdev->dev;
+
+ return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card);
+}
+
+static struct platform_driver skylake_audio = {
+ .probe = skylake_audio_probe,
+ .driver = {
+ .name = "skl_nau88l25_ssm4567_i2s",
+ .pm = &snd_soc_pm_ops,
+ },
+};
+
+module_platform_driver(skylake_audio)
+
+/* Module information */
+MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>");
+MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
+MODULE_AUTHOR("Naveen M <naveen.m@intel.com>");
+MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
+MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>");
+MODULE_DESCRIPTION("Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:skl_nau88l25_ssm4567_i2s");
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c
index a73a431bd8b7..7396ddb427d8 100644
--- a/sound/soc/intel/boards/skl_rt286.c
+++ b/sound/soc/intel/boards/skl_rt286.c
@@ -52,6 +52,7 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
SND_SOC_DAPM_MIC("Mic Jack", NULL),
SND_SOC_DAPM_MIC("DMIC2", NULL),
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
+ SND_SOC_DAPM_SINK("WoV Sink"),
};
static const struct snd_soc_dapm_route skylake_rt286_map[] = {
@@ -67,7 +68,9 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
/* digital mics */
{"DMIC1 Pin", NULL, "DMIC2"},
- {"DMIC AIF", NULL, "SoC DMIC"},
+ {"DMic", NULL, "SoC DMIC"},
+
+ {"WoV Sink", NULL, "hwd_in sink"},
/* CODEC BE connections */
{ "AIF1 Playback", NULL, "ssp0 Tx"},
@@ -79,13 +82,24 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
{ "ssp0 Rx", NULL, "AIF1 Capture" },
{ "dmic01_hifi", NULL, "DMIC01 Rx" },
- { "DMIC01 Rx", NULL, "Capture" },
+ { "DMIC01 Rx", NULL, "DMIC AIF" },
{ "hif1", NULL, "iDisp Tx"},
{ "iDisp Tx", NULL, "iDisp_out"},
};
+static int skylake_rt286_fe_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dapm_context *dapm;
+ struct snd_soc_component *component = rtd->cpu_dai->component;
+
+ dapm = snd_soc_component_get_dapm(component);
+ snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
+
+ return 0;
+}
+
static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
@@ -101,9 +115,59 @@ static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
rt286_mic_detect(codec, &skylake_headset);
+ snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
+ snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink");
+
return 0;
}
+static unsigned int rates[] = {
+ 48000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+};
+
+static unsigned int channels[] = {
+ 2,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_channels = {
+ .count = ARRAY_SIZE(channels),
+ .list = channels,
+ .mask = 0,
+};
+
+static int skl_fe_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ /*
+ * on this platform for PCM device we support,
+ * 48Khz
+ * stereo
+ * 16 bit audio
+ */
+
+ runtime->hw.channels_max = 2;
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_channels);
+
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
+
+ snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+
+ return 0;
+}
+
+static const struct snd_soc_ops skylake_rt286_fe_ops = {
+ .startup = skl_fe_startup,
+};
static int skylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
@@ -112,12 +176,15 @@ static int skylake_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
/* The output is 48KHz, stereo, 16bits */
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
- params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
+ /* set SSP0 to 24 bit */
+ snd_mask_none(fmt);
+ snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
return 0;
}
@@ -140,6 +207,42 @@ static struct snd_soc_ops skylake_rt286_ops = {
.hw_params = skylake_rt286_hw_params,
};
+static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ channels->min = channels->max = 4;
+
+ return 0;
+}
+
+static unsigned int channels_dmic[] = {
+ 2, 4,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
+ .count = ARRAY_SIZE(channels_dmic),
+ .list = channels_dmic,
+ .mask = 0,
+};
+
+static int skylake_dmic_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ runtime->hw.channels_max = 4;
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &constraints_dmic_channels);
+
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+}
+
+static struct snd_soc_ops skylake_dmic_ops = {
+ .startup = skylake_dmic_startup,
+};
+
/* skylake digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link skylake_rt286_dais[] = {
/* Front End DAI links */
@@ -152,11 +255,13 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.dynamic = 1,
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
+ .init = skylake_rt286_fe_init,
.trigger = {
SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST
},
.dpcm_playback = 1,
+ .ops = &skylake_rt286_fe_ops,
},
{
.name = "Skl Audio Capture Port",
@@ -172,6 +277,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
SND_SOC_DPCM_TRIGGER_POST
},
.dpcm_capture = 1,
+ .ops = &skylake_rt286_fe_ops,
},
{
.name = "Skl Audio Reference cap",
@@ -186,6 +292,19 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.nonatomic = 1,
.dynamic = 1,
},
+ {
+ .name = "Skl Audio DMIC cap",
+ .stream_name = "dmiccap",
+ .cpu_dai_name = "DMIC Pin",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .platform_name = "0000:00:1f.3",
+ .init = NULL,
+ .dpcm_capture = 1,
+ .nonatomic = 1,
+ .dynamic = 1,
+ .ops = &skylake_dmic_ops,
+ },
/* Back End DAI links */
{
@@ -201,7 +320,6 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .ignore_suspend = 1,
.ignore_pmdown_time = 1,
.be_hw_params_fixup = skylake_ssp0_fixup,
.ops = &skylake_rt286_ops,
@@ -215,6 +333,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.codec_name = "dmic-codec",
.codec_dai_name = "dmic-hifi",
.platform_name = "0000:00:1f.3",
+ .be_hw_params_fixup = skylake_dmic_fixup,
.ignore_suspend = 1,
.dpcm_capture = 1,
.no_pcm = 1,
@@ -247,6 +366,7 @@ static struct platform_driver skylake_audio = {
.probe = skylake_audio_probe,
.driver = {
.name = "skl_alc286s_i2s",
+ .pm = &snd_soc_pm_ops,
},
};
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
index d9105584c51f..668fdeee195e 100644
--- a/sound/soc/intel/common/Makefile
+++ b/sound/soc/intel/common/Makefile
@@ -1,11 +1,13 @@
snd-soc-sst-dsp-objs := sst-dsp.o
-snd-soc-sst-acpi-objs := sst-acpi.o
+ifneq ($(CONFIG_SND_SST_IPC_ACPI),)
+snd-soc-sst-acpi-objs := sst-match-acpi.o
+else
+snd-soc-sst-acpi-objs := sst-acpi.o sst-match-acpi.o
+endif
+
snd-soc-sst-ipc-objs := sst-ipc.o
-ifneq ($(CONFIG_DW_DMAC_CORE),)
-snd-soc-sst-dsp-objs += sst-firmware.o
-endif
+snd-soc-sst-dsp-$(CONFIG_DW_DMAC_CORE) += sst-firmware.o
obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o
-
diff --git a/sound/soc/intel/common/sst-acpi.c b/sound/soc/intel/common/sst-acpi.c
index 67b6d3d52f57..7a85c576dad3 100644
--- a/sound/soc/intel/common/sst-acpi.c
+++ b/sound/soc/intel/common/sst-acpi.c
@@ -21,21 +21,12 @@
#include <linux/platform_device.h>
#include "sst-dsp.h"
+#include "sst-acpi.h"
#define SST_LPT_DSP_DMA_ADDR_OFFSET 0x0F0000
#define SST_WPT_DSP_DMA_ADDR_OFFSET 0x0FE000
#define SST_LPT_DSP_DMA_SIZE (1024 - 1)
-/* Descriptor for SST ASoC machine driver */
-struct sst_acpi_mach {
- /* ACPI ID for the matching machine driver. Audio codec for instance */
- const u8 id[ACPI_ID_LEN];
- /* machine driver name */
- const char *drv_name;
- /* firmware file name */
- const char *fw_filename;
-};
-
/* Descriptor for setting up SST platform data */
struct sst_acpi_desc {
const char *drv_name;
@@ -88,28 +79,6 @@ static void sst_acpi_fw_cb(const struct firmware *fw, void *context)
return;
}
-static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
- void *context, void **ret)
-{
- *(bool *)context = true;
- return AE_OK;
-}
-
-static struct sst_acpi_mach *sst_acpi_find_machine(
- struct sst_acpi_mach *machines)
-{
- struct sst_acpi_mach *mach;
- bool found = false;
-
- for (mach = machines; mach->id[0]; mach++)
- if (ACPI_SUCCESS(acpi_get_devices(mach->id,
- sst_acpi_mach_match,
- &found, NULL)) && found)
- return mach;
-
- return NULL;
-}
-
static int sst_acpi_probe(struct platform_device *pdev)
{
const struct acpi_device_id *id;
@@ -211,7 +180,7 @@ static int sst_acpi_remove(struct platform_device *pdev)
}
static struct sst_acpi_mach haswell_machines[] = {
- { "INT33CA", "haswell-audio", "intel/IntcSST1.bin" },
+ { "INT33CA", "haswell-audio", "intel/IntcSST1.bin", NULL, NULL, NULL },
{}
};
@@ -229,7 +198,7 @@ static struct sst_acpi_desc sst_acpi_haswell_desc = {
};
static struct sst_acpi_mach broadwell_machines[] = {
- { "INT343A", "broadwell-audio", "intel/IntcSST2.bin" },
+ { "INT343A", "broadwell-audio", "intel/IntcSST2.bin", NULL, NULL, NULL },
{}
};
@@ -247,8 +216,8 @@ static struct sst_acpi_desc sst_acpi_broadwell_desc = {
};
static struct sst_acpi_mach baytrail_machines[] = {
- { "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-48kHz_i2s_master" },
- { "193C9890", "byt-max98090", "intel/fw_sst_0f28.bin-48kHz_i2s_master" },
+ { "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-48kHz_i2s_master", NULL, NULL, NULL },
+ { "193C9890", "byt-max98090", "intel/fw_sst_0f28.bin-48kHz_i2s_master", NULL, NULL, NULL },
{}
};
diff --git a/sound/soc/intel/common/sst-acpi.h b/sound/soc/intel/common/sst-acpi.h
new file mode 100644
index 000000000000..3ee3b7ab5d03
--- /dev/null
+++ b/sound/soc/intel/common/sst-acpi.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013-15, Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/acpi.h>
+
+/* acpi match */
+struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines);
+
+/* Descriptor for SST ASoC machine driver */
+struct sst_acpi_mach {
+ /* ACPI ID for the matching machine driver. Audio codec for instance */
+ const u8 id[ACPI_ID_LEN];
+ /* machine driver name */
+ const char *drv_name;
+ /* firmware file name */
+ const char *fw_filename;
+
+ /* board name */
+ const char *board;
+ void (*machine_quirk)(void);
+ void *pdata;
+};
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h
index 2151652d37b7..81aa1ed64201 100644
--- a/sound/soc/intel/common/sst-dsp-priv.h
+++ b/sound/soc/intel/common/sst-dsp-priv.h
@@ -243,7 +243,7 @@ struct sst_mem_block {
u32 size; /* block size */
u32 index; /* block index 0..N */
enum sst_mem_type type; /* block memory type IRAM/DRAM */
- struct sst_block_ops *ops; /* block operations, if any */
+ const struct sst_block_ops *ops;/* block operations, if any */
/* block status */
u32 bytes_used; /* bytes in use by modules */
@@ -308,6 +308,8 @@ struct sst_dsp {
/* SKL data */
+ const char *fw_name;
+
/* To allocate CL dma buffers */
struct skl_dsp_loader_ops dsp_ops;
struct skl_dsp_fw_ops fw_ops;
@@ -376,8 +378,8 @@ void sst_block_free_scratch(struct sst_dsp *dsp);
/* Register the DSPs memory blocks - would be nice to read from ACPI */
struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset,
- u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index,
- void *private);
+ u32 size, enum sst_mem_type type, const struct sst_block_ops *ops,
+ u32 index, void *private);
void sst_mem_block_unregister_all(struct sst_dsp *dsp);
/* Create/Free DMA resources */
diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c
index c9452e02e0dd..b5bbdf4fe93a 100644
--- a/sound/soc/intel/common/sst-dsp.c
+++ b/sound/soc/intel/common/sst-dsp.c
@@ -420,7 +420,7 @@ void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes)
}
EXPORT_SYMBOL_GPL(sst_dsp_inbox_read);
-#if IS_ENABLED(CONFIG_DW_DMAC_CORE)
+#ifdef CONFIG_DW_DMAC_CORE
struct sst_dsp *sst_dsp_new(struct device *dev,
struct sst_dsp_device *sst_dev, struct sst_pdata *pdata)
{
diff --git a/sound/soc/intel/common/sst-dsp.h b/sound/soc/intel/common/sst-dsp.h
index 859f0de00339..0b84c719ec48 100644
--- a/sound/soc/intel/common/sst-dsp.h
+++ b/sound/soc/intel/common/sst-dsp.h
@@ -216,7 +216,7 @@ struct sst_pdata {
void *dsp;
};
-#if IS_ENABLED(CONFIG_DW_DMAC_CORE)
+#ifdef CONFIG_DW_DMAC_CORE
/* Initialization */
struct sst_dsp *sst_dsp_new(struct device *dev,
struct sst_dsp_device *sst_dev, struct sst_pdata *pdata);
diff --git a/sound/soc/intel/common/sst-firmware.c b/sound/soc/intel/common/sst-firmware.c
index 1636a1eeb002..ef4881e7753a 100644
--- a/sound/soc/intel/common/sst-firmware.c
+++ b/sound/soc/intel/common/sst-firmware.c
@@ -51,8 +51,22 @@ struct sst_dma {
static inline void sst_memcpy32(volatile void __iomem *dest, void *src, u32 bytes)
{
+ u32 tmp = 0;
+ int i, m, n;
+ const u8 *src_byte = src;
+
+ m = bytes / 4;
+ n = bytes % 4;
+
/* __iowrite32_copy use 32bit size values so divide by 4 */
- __iowrite32_copy((void *)dest, src, bytes/4);
+ __iowrite32_copy((void *)dest, src, m);
+
+ if (n) {
+ for (i = 0; i < n; i++)
+ tmp |= (u32)*(src_byte + m * 4 + i) << (i * 8);
+ __iowrite32_copy((void *)(dest + m * 4), &tmp, 1);
+ }
+
}
static void sst_dma_transfer_complete(void *arg)
@@ -1014,8 +1028,8 @@ EXPORT_SYMBOL_GPL(sst_module_runtime_restore);
/* register a DSP memory block for use with FW based modules */
struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset,
- u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index,
- void *private)
+ u32 size, enum sst_mem_type type, const struct sst_block_ops *ops,
+ u32 index, void *private)
{
struct sst_mem_block *block;
diff --git a/sound/soc/intel/common/sst-match-acpi.c b/sound/soc/intel/common/sst-match-acpi.c
new file mode 100644
index 000000000000..dd077e116d25
--- /dev/null
+++ b/sound/soc/intel/common/sst-match-acpi.c
@@ -0,0 +1,43 @@
+/*
+ * sst_match_apci.c - SST (LPE) match for ACPI enumeration.
+ *
+ * Copyright (c) 2013-15, Intel Corporation.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "sst-acpi.h"
+
+static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
+ void *context, void **ret)
+{
+ *(bool *)context = true;
+ return AE_OK;
+}
+
+struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines)
+{
+ struct sst_acpi_mach *mach;
+ bool found = false;
+
+ for (mach = machines; mach->id[0]; mach++)
+ if (ACPI_SUCCESS(acpi_get_devices(mach->id,
+ sst_acpi_mach_match,
+ &found, NULL)) && found)
+ return mach;
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(sst_acpi_find_machine);
diff --git a/sound/soc/intel/haswell/sst-haswell-dsp.c b/sound/soc/intel/haswell/sst-haswell-dsp.c
index 7f94920c8a4d..b2bec36d074c 100644
--- a/sound/soc/intel/haswell/sst-haswell-dsp.c
+++ b/sound/soc/intel/haswell/sst-haswell-dsp.c
@@ -607,7 +607,7 @@ static int hsw_block_disable(struct sst_mem_block *block)
return 0;
}
-static struct sst_block_ops sst_hsw_ops = {
+static const struct sst_block_ops sst_hsw_ops = {
.enable = hsw_block_enable,
.disable = hsw_block_disable,
};
diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c
index b27f25f70730..ac60f1301e21 100644
--- a/sound/soc/intel/haswell/sst-haswell-ipc.c
+++ b/sound/soc/intel/haswell/sst-haswell-ipc.c
@@ -778,7 +778,6 @@ static irqreturn_t hsw_irq_thread(int irq, void *context)
struct sst_hsw *hsw = sst_dsp_get_thread_context(sst);
struct sst_generic_ipc *ipc = &hsw->ipc;
u32 ipcx, ipcd;
- int handled;
unsigned long flags;
spin_lock_irqsave(&sst->spinlock, flags);
@@ -790,34 +789,30 @@ static irqreturn_t hsw_irq_thread(int irq, void *context)
if (ipcx & SST_IPCX_DONE) {
/* Handle Immediate reply from DSP Core */
- handled = hsw_process_reply(hsw, ipcx);
+ hsw_process_reply(hsw, ipcx);
- if (handled > 0) {
- /* clear DONE bit - tell DSP we have completed */
- sst_dsp_shim_update_bits_unlocked(sst, SST_IPCX,
- SST_IPCX_DONE, 0);
+ /* clear DONE bit - tell DSP we have completed */
+ sst_dsp_shim_update_bits_unlocked(sst, SST_IPCX,
+ SST_IPCX_DONE, 0);
- /* unmask Done interrupt */
- sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX,
- SST_IMRX_DONE, 0);
- }
+ /* unmask Done interrupt */
+ sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX,
+ SST_IMRX_DONE, 0);
}
/* new message from DSP */
if (ipcd & SST_IPCD_BUSY) {
/* Handle Notification and Delayed reply from DSP Core */
- handled = hsw_process_notification(hsw);
+ hsw_process_notification(hsw);
/* clear BUSY bit and set DONE bit - accept new messages */
- if (handled > 0) {
- sst_dsp_shim_update_bits_unlocked(sst, SST_IPCD,
- SST_IPCD_BUSY | SST_IPCD_DONE, SST_IPCD_DONE);
+ sst_dsp_shim_update_bits_unlocked(sst, SST_IPCD,
+ SST_IPCD_BUSY | SST_IPCD_DONE, SST_IPCD_DONE);
- /* unmask busy interrupt */
- sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX,
- SST_IMRX_BUSY, 0);
- }
+ /* unmask busy interrupt */
+ sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX,
+ SST_IMRX_BUSY, 0);
}
spin_unlock_irqrestore(&sst->spinlock, flags);
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c
index 50a109503a3f..de6dac496a0d 100644
--- a/sound/soc/intel/skylake/skl-messages.c
+++ b/sound/soc/intel/skylake/skl-messages.c
@@ -96,7 +96,7 @@ int skl_init_dsp(struct skl *skl)
}
ret = skl_sst_dsp_init(bus->dev, mmio_base, irq,
- loader_ops, &skl->skl_sst);
+ skl->fw_name, loader_ops, &skl->skl_sst);
if (ret < 0)
return ret;
@@ -182,94 +182,6 @@ enum skl_bitdepth skl_get_bit_depth(int params)
}
}
-static u32 skl_create_channel_map(enum skl_ch_cfg ch_cfg)
-{
- u32 config;
-
- switch (ch_cfg) {
- case SKL_CH_CFG_MONO:
- config = (0xFFFFFFF0 | SKL_CHANNEL_LEFT);
- break;
-
- case SKL_CH_CFG_STEREO:
- config = (0xFFFFFF00 | SKL_CHANNEL_LEFT
- | (SKL_CHANNEL_RIGHT << 4));
- break;
-
- case SKL_CH_CFG_2_1:
- config = (0xFFFFF000 | SKL_CHANNEL_LEFT
- | (SKL_CHANNEL_RIGHT << 4)
- | (SKL_CHANNEL_LFE << 8));
- break;
-
- case SKL_CH_CFG_3_0:
- config = (0xFFFFF000 | SKL_CHANNEL_LEFT
- | (SKL_CHANNEL_CENTER << 4)
- | (SKL_CHANNEL_RIGHT << 8));
- break;
-
- case SKL_CH_CFG_3_1:
- config = (0xFFFF0000 | SKL_CHANNEL_LEFT
- | (SKL_CHANNEL_CENTER << 4)
- | (SKL_CHANNEL_RIGHT << 8)
- | (SKL_CHANNEL_LFE << 12));
- break;
-
- case SKL_CH_CFG_QUATRO:
- config = (0xFFFF0000 | SKL_CHANNEL_LEFT
- | (SKL_CHANNEL_RIGHT << 4)
- | (SKL_CHANNEL_LEFT_SURROUND << 8)
- | (SKL_CHANNEL_RIGHT_SURROUND << 12));
- break;
-
- case SKL_CH_CFG_4_0:
- config = (0xFFFF0000 | SKL_CHANNEL_LEFT
- | (SKL_CHANNEL_CENTER << 4)
- | (SKL_CHANNEL_RIGHT << 8)
- | (SKL_CHANNEL_CENTER_SURROUND << 12));
- break;
-
- case SKL_CH_CFG_5_0:
- config = (0xFFF00000 | SKL_CHANNEL_LEFT
- | (SKL_CHANNEL_CENTER << 4)
- | (SKL_CHANNEL_RIGHT << 8)
- | (SKL_CHANNEL_LEFT_SURROUND << 12)
- | (SKL_CHANNEL_RIGHT_SURROUND << 16));
- break;
-
- case SKL_CH_CFG_5_1:
- config = (0xFF000000 | SKL_CHANNEL_CENTER
- | (SKL_CHANNEL_LEFT << 4)
- | (SKL_CHANNEL_RIGHT << 8)
- | (SKL_CHANNEL_LEFT_SURROUND << 12)
- | (SKL_CHANNEL_RIGHT_SURROUND << 16)
- | (SKL_CHANNEL_LFE << 20));
- break;
-
- case SKL_CH_CFG_DUAL_MONO:
- config = (0xFFFFFF00 | SKL_CHANNEL_LEFT
- | (SKL_CHANNEL_LEFT << 4));
- break;
-
- case SKL_CH_CFG_I2S_DUAL_STEREO_0:
- config = (0xFFFFFF00 | SKL_CHANNEL_LEFT
- | (SKL_CHANNEL_RIGHT << 4));
- break;
-
- case SKL_CH_CFG_I2S_DUAL_STEREO_1:
- config = (0xFFFF00FF | (SKL_CHANNEL_LEFT << 8)
- | (SKL_CHANNEL_RIGHT << 12));
- break;
-
- default:
- config = 0xFFFFFFFF;
- break;
-
- }
-
- return config;
-}
-
/*
* Each module in DSP expects a base module configuration, which consists of
* PCM format information, which we calculate in driver and resource values
@@ -280,7 +192,7 @@ static void skl_set_base_module_format(struct skl_sst *ctx,
struct skl_module_cfg *mconfig,
struct skl_base_cfg *base_cfg)
{
- struct skl_module_fmt *format = &mconfig->in_fmt;
+ struct skl_module_fmt *format = &mconfig->in_fmt[0];
base_cfg->audio_fmt.number_of_channels = (u8)format->channels;
@@ -293,14 +205,14 @@ static void skl_set_base_module_format(struct skl_sst *ctx,
format->bit_depth, format->valid_bit_depth,
format->ch_cfg);
- base_cfg->audio_fmt.channel_map = skl_create_channel_map(
- base_cfg->audio_fmt.ch_cfg);
+ base_cfg->audio_fmt.channel_map = format->ch_map;
- base_cfg->audio_fmt.interleaving = SKL_INTERLEAVING_PER_CHANNEL;
+ base_cfg->audio_fmt.interleaving = format->interleaving_style;
base_cfg->cps = mconfig->mcps;
base_cfg->ibs = mconfig->ibs;
base_cfg->obs = mconfig->obs;
+ base_cfg->is_pages = mconfig->mem_pages;
}
/*
@@ -399,7 +311,7 @@ static void skl_setup_out_format(struct skl_sst *ctx,
struct skl_module_cfg *mconfig,
struct skl_audio_data_format *out_fmt)
{
- struct skl_module_fmt *format = &mconfig->out_fmt;
+ struct skl_module_fmt *format = &mconfig->out_fmt[0];
out_fmt->number_of_channels = (u8)format->channels;
out_fmt->s_freq = format->s_freq;
@@ -407,8 +319,9 @@ static void skl_setup_out_format(struct skl_sst *ctx,
out_fmt->valid_bit_depth = format->valid_bit_depth;
out_fmt->ch_cfg = format->ch_cfg;
- out_fmt->channel_map = skl_create_channel_map(out_fmt->ch_cfg);
- out_fmt->interleaving = SKL_INTERLEAVING_PER_CHANNEL;
+ out_fmt->channel_map = format->ch_map;
+ out_fmt->interleaving = format->interleaving_style;
+ out_fmt->sample_type = format->sample_type;
dev_dbg(ctx->dev, "copier out format chan=%d fre=%d bitdepth=%d\n",
out_fmt->number_of_channels, format->s_freq, format->bit_depth);
@@ -423,7 +336,7 @@ static void skl_set_src_format(struct skl_sst *ctx,
struct skl_module_cfg *mconfig,
struct skl_src_module_cfg *src_mconfig)
{
- struct skl_module_fmt *fmt = &mconfig->out_fmt;
+ struct skl_module_fmt *fmt = &mconfig->out_fmt[0];
skl_set_base_module_format(ctx, mconfig,
(struct skl_base_cfg *)src_mconfig);
@@ -440,7 +353,7 @@ static void skl_set_updown_mixer_format(struct skl_sst *ctx,
struct skl_module_cfg *mconfig,
struct skl_up_down_mixer_cfg *mixer_mconfig)
{
- struct skl_module_fmt *fmt = &mconfig->out_fmt;
+ struct skl_module_fmt *fmt = &mconfig->out_fmt[0];
int i = 0;
skl_set_base_module_format(ctx, mconfig,
@@ -475,6 +388,47 @@ static void skl_set_copier_format(struct skl_sst *ctx,
skl_setup_cpr_gateway_cfg(ctx, mconfig, cpr_mconfig);
}
+/*
+ * Algo module are DSP pre processing modules. Algo module take base module
+ * configuration and params
+ */
+
+static void skl_set_algo_format(struct skl_sst *ctx,
+ struct skl_module_cfg *mconfig,
+ struct skl_algo_cfg *algo_mcfg)
+{
+ struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg;
+
+ skl_set_base_module_format(ctx, mconfig, base_cfg);
+
+ if (mconfig->formats_config.caps_size == 0)
+ return;
+
+ memcpy(algo_mcfg->params,
+ mconfig->formats_config.caps,
+ mconfig->formats_config.caps_size);
+
+}
+
+/*
+ * Mic select module allows selecting one or many input channels, thus
+ * acting as a demux.
+ *
+ * Mic select module take base module configuration and out-format
+ * configuration
+ */
+static void skl_set_base_outfmt_format(struct skl_sst *ctx,
+ struct skl_module_cfg *mconfig,
+ struct skl_base_outfmt_cfg *base_outfmt_mcfg)
+{
+ struct skl_audio_data_format *out_fmt = &base_outfmt_mcfg->out_fmt;
+ struct skl_base_cfg *base_cfg =
+ (struct skl_base_cfg *)base_outfmt_mcfg;
+
+ skl_set_base_module_format(ctx, mconfig, base_cfg);
+ skl_setup_out_format(ctx, mconfig, out_fmt);
+}
+
static u16 skl_get_module_param_size(struct skl_sst *ctx,
struct skl_module_cfg *mconfig)
{
@@ -492,6 +446,14 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx,
case SKL_MODULE_TYPE_UPDWMIX:
return sizeof(struct skl_up_down_mixer_cfg);
+ case SKL_MODULE_TYPE_ALGO:
+ param_size = sizeof(struct skl_base_cfg);
+ param_size += mconfig->formats_config.caps_size;
+ return param_size;
+
+ case SKL_MODULE_TYPE_BASE_OUTFMT:
+ return sizeof(struct skl_base_outfmt_cfg);
+
default:
/*
* return only base cfg when no specific module type is
@@ -538,6 +500,14 @@ static int skl_set_module_format(struct skl_sst *ctx,
skl_set_updown_mixer_format(ctx, module_config, *param_data);
break;
+ case SKL_MODULE_TYPE_ALGO:
+ skl_set_algo_format(ctx, module_config, *param_data);
+ break;
+
+ case SKL_MODULE_TYPE_BASE_OUTFMT:
+ skl_set_base_outfmt_format(ctx, module_config, *param_data);
+ break;
+
default:
skl_set_base_module_format(ctx, module_config, *param_data);
break;
@@ -571,10 +541,10 @@ static int skl_get_queue_index(struct skl_module_pin *mpin,
* In static, the pin_index is fixed based on module_id and instance id
*/
static int skl_alloc_queue(struct skl_module_pin *mpin,
- struct skl_module_inst_id id, int max)
+ struct skl_module_cfg *tgt_cfg, int max)
{
int i;
-
+ struct skl_module_inst_id id = tgt_cfg->id;
/*
* if pin in dynamic, find first free pin
* otherwise find match module and instance id pin as topology will
@@ -583,16 +553,23 @@ static int skl_alloc_queue(struct skl_module_pin *mpin,
*/
for (i = 0; i < max; i++) {
if (mpin[i].is_dynamic) {
- if (!mpin[i].in_use) {
+ if (!mpin[i].in_use &&
+ mpin[i].pin_state == SKL_PIN_UNBIND) {
+
mpin[i].in_use = true;
mpin[i].id.module_id = id.module_id;
mpin[i].id.instance_id = id.instance_id;
+ mpin[i].tgt_mcfg = tgt_cfg;
return i;
}
} else {
if (mpin[i].id.module_id == id.module_id &&
- mpin[i].id.instance_id == id.instance_id)
+ mpin[i].id.instance_id == id.instance_id &&
+ mpin[i].pin_state == SKL_PIN_UNBIND) {
+
+ mpin[i].tgt_mcfg = tgt_cfg;
return i;
+ }
}
}
@@ -606,6 +583,28 @@ static void skl_free_queue(struct skl_module_pin *mpin, int q_index)
mpin[q_index].id.module_id = 0;
mpin[q_index].id.instance_id = 0;
}
+ mpin[q_index].pin_state = SKL_PIN_UNBIND;
+ mpin[q_index].tgt_mcfg = NULL;
+}
+
+/* Module state will be set to unint, if all the out pin state is UNBIND */
+
+static void skl_clear_module_state(struct skl_module_pin *mpin, int max,
+ struct skl_module_cfg *mcfg)
+{
+ int i;
+ bool found = false;
+
+ for (i = 0; i < max; i++) {
+ if (mpin[i].pin_state == SKL_PIN_UNBIND)
+ continue;
+ found = true;
+ break;
+ }
+
+ if (!found)
+ mcfg->m_state = SKL_MODULE_UNINIT;
+ return;
}
/*
@@ -615,7 +614,7 @@ static void skl_free_queue(struct skl_module_pin *mpin, int q_index)
* invoke the DSP by sending IPC INIT_INSTANCE using ipc helper
*/
int skl_init_module(struct skl_sst *ctx,
- struct skl_module_cfg *mconfig, char *param)
+ struct skl_module_cfg *mconfig)
{
u16 module_config_size = 0;
void *param_data = NULL;
@@ -682,37 +681,30 @@ int skl_unbind_modules(struct skl_sst *ctx,
struct skl_module_inst_id dst_id = dst_mcfg->id;
int in_max = dst_mcfg->max_in_queue;
int out_max = src_mcfg->max_out_queue;
- int src_index, dst_index;
+ int src_index, dst_index, src_pin_state, dst_pin_state;
skl_dump_bind_info(ctx, src_mcfg, dst_mcfg);
- if (src_mcfg->m_state != SKL_MODULE_BIND_DONE)
- return 0;
-
- /*
- * if intra module unbind, check if both modules are BIND,
- * then send unbind
- */
- if ((src_mcfg->pipe->ppl_id != dst_mcfg->pipe->ppl_id) &&
- dst_mcfg->m_state != SKL_MODULE_BIND_DONE)
- return 0;
- else if (src_mcfg->m_state < SKL_MODULE_INIT_DONE &&
- dst_mcfg->m_state < SKL_MODULE_INIT_DONE)
- return 0;
-
/* get src queue index */
src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max);
if (src_index < 0)
return -EINVAL;
- msg.src_queue = src_mcfg->m_out_pin[src_index].pin_index;
+ msg.src_queue = src_index;
/* get dst queue index */
dst_index = skl_get_queue_index(dst_mcfg->m_in_pin, src_id, in_max);
if (dst_index < 0)
return -EINVAL;
- msg.dst_queue = dst_mcfg->m_in_pin[dst_index].pin_index;
+ msg.dst_queue = dst_index;
+
+ src_pin_state = src_mcfg->m_out_pin[src_index].pin_state;
+ dst_pin_state = dst_mcfg->m_in_pin[dst_index].pin_state;
+
+ if (src_pin_state != SKL_PIN_BIND_DONE ||
+ dst_pin_state != SKL_PIN_BIND_DONE)
+ return 0;
msg.module_id = src_mcfg->id.module_id;
msg.instance_id = src_mcfg->id.instance_id;
@@ -722,10 +714,15 @@ int skl_unbind_modules(struct skl_sst *ctx,
ret = skl_ipc_bind_unbind(&ctx->ipc, &msg);
if (!ret) {
- src_mcfg->m_state = SKL_MODULE_UNINIT;
/* free queue only if unbind is success */
skl_free_queue(src_mcfg->m_out_pin, src_index);
skl_free_queue(dst_mcfg->m_in_pin, dst_index);
+
+ /*
+ * check only if src module bind state, bind is
+ * always from src -> sink
+ */
+ skl_clear_module_state(src_mcfg->m_out_pin, out_max, src_mcfg);
}
return ret;
@@ -744,8 +741,6 @@ int skl_bind_modules(struct skl_sst *ctx,
{
int ret;
struct skl_ipc_bind_unbind_msg msg;
- struct skl_module_inst_id src_id = src_mcfg->id;
- struct skl_module_inst_id dst_id = dst_mcfg->id;
int in_max = dst_mcfg->max_in_queue;
int out_max = src_mcfg->max_out_queue;
int src_index, dst_index;
@@ -756,18 +751,18 @@ int skl_bind_modules(struct skl_sst *ctx,
dst_mcfg->m_state < SKL_MODULE_INIT_DONE)
return 0;
- src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_id, out_max);
+ src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_mcfg, out_max);
if (src_index < 0)
return -EINVAL;
- msg.src_queue = src_mcfg->m_out_pin[src_index].pin_index;
- dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_id, in_max);
+ msg.src_queue = src_index;
+ dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_mcfg, in_max);
if (dst_index < 0) {
skl_free_queue(src_mcfg->m_out_pin, src_index);
return -EINVAL;
}
- msg.dst_queue = dst_mcfg->m_in_pin[dst_index].pin_index;
+ msg.dst_queue = dst_index;
dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n",
msg.src_queue, msg.dst_queue);
@@ -782,6 +777,8 @@ int skl_bind_modules(struct skl_sst *ctx,
if (!ret) {
src_mcfg->m_state = SKL_MODULE_BIND_DONE;
+ src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE;
+ dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE;
} else {
/* error case , if IPC fails, clear the queue index */
skl_free_queue(src_mcfg->m_out_pin, src_index);
@@ -852,6 +849,8 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe)
ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id);
if (ret < 0)
dev_err(ctx->dev, "Failed to delete pipeline\n");
+
+ pipe->state = SKL_PIPE_INVALID;
}
return ret;
@@ -916,3 +915,30 @@ int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe)
return 0;
}
+
+/* Algo parameter set helper function */
+int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size,
+ u32 param_id, struct skl_module_cfg *mcfg)
+{
+ struct skl_ipc_large_config_msg msg;
+
+ msg.module_id = mcfg->id.module_id;
+ msg.instance_id = mcfg->id.instance_id;
+ msg.param_data_size = size;
+ msg.large_param_id = param_id;
+
+ return skl_ipc_set_large_config(&ctx->ipc, &msg, params);
+}
+
+int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size,
+ u32 param_id, struct skl_module_cfg *mcfg)
+{
+ struct skl_ipc_large_config_msg msg;
+
+ msg.module_id = mcfg->id.module_id;
+ msg.instance_id = mcfg->id.instance_id;
+ msg.param_data_size = size;
+ msg.large_param_id = param_id;
+
+ return skl_ipc_get_large_config(&ctx->ipc, &msg, params);
+}
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c
index b0c7bd113aac..6e4b21cdb1bd 100644
--- a/sound/soc/intel/skylake/skl-nhlt.c
+++ b/sound/soc/intel/skylake/skl-nhlt.c
@@ -55,7 +55,7 @@ void skl_nhlt_free(void *addr)
static struct nhlt_specific_cfg *skl_get_specific_cfg(
struct device *dev, struct nhlt_fmt *fmt,
- u8 no_ch, u32 rate, u16 bps)
+ u8 no_ch, u32 rate, u16 bps, u8 linktype)
{
struct nhlt_specific_cfg *sp_config;
struct wav_fmt *wfmt;
@@ -68,11 +68,17 @@ static struct nhlt_specific_cfg *skl_get_specific_cfg(
wfmt = &fmt_config->fmt_ext.fmt;
dev_dbg(dev, "ch=%d fmt=%d s_rate=%d\n", wfmt->channels,
wfmt->bits_per_sample, wfmt->samples_per_sec);
- if (wfmt->channels == no_ch && wfmt->samples_per_sec == rate &&
- wfmt->bits_per_sample == bps) {
+ if (wfmt->channels == no_ch && wfmt->bits_per_sample == bps) {
+ /*
+ * if link type is dmic ignore rate check as the blob is
+ * generic for all rates
+ */
sp_config = &fmt_config->config;
+ if (linktype == NHLT_LINK_DMIC)
+ return sp_config;
- return sp_config;
+ if (wfmt->samples_per_sec == rate)
+ return sp_config;
}
fmt_config = (struct nhlt_fmt_cfg *)(fmt_config->config.caps +
@@ -115,7 +121,7 @@ struct nhlt_specific_cfg
struct device *dev = bus->dev;
struct nhlt_specific_cfg *sp_config;
struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
- u16 bps = num_ch * s_fmt;
+ u16 bps = (s_fmt == 16) ? 16 : 32;
u8 j;
dump_config(dev, instance, link_type, s_fmt, num_ch, s_rate, dirn, bps);
@@ -128,7 +134,8 @@ struct nhlt_specific_cfg
if (skl_check_ep_match(dev, epnt, instance, link_type, dirn)) {
fmt = (struct nhlt_fmt *)(epnt->config.caps +
epnt->config.size);
- sp_config = skl_get_specific_cfg(dev, fmt, num_ch, s_rate, bps);
+ sp_config = skl_get_specific_cfg(dev, fmt, num_ch,
+ s_rate, bps, link_type);
if (sp_config)
return sp_config;
}
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
index a2f94ce1679d..f3553258091a 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -25,9 +25,12 @@
#include <sound/soc.h>
#include "skl.h"
#include "skl-topology.h"
+#include "skl-sst-dsp.h"
+#include "skl-sst-ipc.h"
#define HDA_MONO 1
#define HDA_STEREO 2
+#define HDA_QUAD 4
static struct snd_pcm_hardware azx_pcm_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
@@ -35,16 +38,20 @@ static struct snd_pcm_hardware azx_pcm_hw = {
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_SYNC_START |
SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
SNDRV_PCM_INFO_HAS_LINK_ATIME |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_48000,
- .rate_min = 48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE |
+ SNDRV_PCM_FMTBIT_S24_LE,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_8000,
+ .rate_min = 8000,
.rate_max = 48000,
- .channels_min = 2,
- .channels_max = 2,
+ .channels_min = 1,
+ .channels_max = HDA_QUAD,
.buffer_bytes_max = AZX_MAX_BUF_SIZE,
.period_bytes_min = 128,
.period_bytes_max = AZX_MAX_BUF_SIZE / 2,
@@ -105,6 +112,31 @@ static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_ext_bus *e
return HDAC_EXT_STREAM_TYPE_COUPLED;
}
+/*
+ * check if the stream opened is marked as ignore_suspend by machine, if so
+ * then enable suspend_active refcount
+ *
+ * The count supend_active does not need lock as it is used in open/close
+ * and suspend context
+ */
+static void skl_set_suspend_active(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai, bool enable)
+{
+ struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
+ struct snd_soc_dapm_widget *w;
+ struct skl *skl = ebus_to_skl(ebus);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ w = dai->playback_widget;
+ else
+ w = dai->capture_widget;
+
+ if (w->ignore_suspend && enable)
+ skl->supend_active++;
+ else if (w->ignore_suspend && !enable)
+ skl->supend_active--;
+}
+
static int skl_pcm_open(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -112,12 +144,8 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
struct hdac_ext_stream *stream;
struct snd_pcm_runtime *runtime = substream->runtime;
struct skl_dma_params *dma_params;
- int ret;
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
- ret = pm_runtime_get_sync(dai->dev);
- if (ret < 0)
- return ret;
stream = snd_hdac_ext_stream_assign(ebus, substream,
skl_get_host_stream_type(ebus));
@@ -146,6 +174,7 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
dev_dbg(dai->dev, "stream tag set in dma params=%d\n",
dma_params->stream_tag);
+ skl_set_suspend_active(substream, dai, true);
snd_pcm_set_sync(substream);
return 0;
@@ -185,10 +214,6 @@ static int skl_pcm_prepare(struct snd_pcm_substream *substream,
int err;
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
- if (hdac_stream(stream)->prepared) {
- dev_dbg(dai->dev, "already stream is prepared - returning\n");
- return 0;
- }
format_val = skl_get_format(substream, dai);
dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n",
@@ -250,6 +275,7 @@ static void skl_pcm_close(struct snd_pcm_substream *substream,
struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
struct skl_dma_params *dma_params = NULL;
+ struct skl *skl = ebus_to_skl(ebus);
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
@@ -261,9 +287,18 @@ static void skl_pcm_close(struct snd_pcm_substream *substream,
* dma_params
*/
snd_soc_dai_set_dma_data(dai, substream, NULL);
+ skl_set_suspend_active(substream, dai, false);
+
+ /*
+ * check if close is for "Reference Pin" and set back the
+ * CGCTL.MISCBDCGE if disabled by driver
+ */
+ if (!strncmp(dai->name, "Reference Pin", 13) &&
+ skl->skl_sst->miscbdcg_disabled) {
+ skl->skl_sst->enable_miscbdcge(dai->dev, true);
+ skl->skl_sst->miscbdcg_disabled = false;
+ }
- pm_runtime_mark_last_busy(dai->dev);
- pm_runtime_put_autosuspend(dai->dev);
kfree(dma_params);
}
@@ -291,7 +326,53 @@ static int skl_be_hw_params(struct snd_pcm_substream *substream,
p_params.ch = params_channels(params);
p_params.s_freq = params_rate(params);
p_params.stream = substream->stream;
- skl_tplg_be_update_params(dai, &p_params);
+
+ return skl_tplg_be_update_params(dai, &p_params);
+}
+
+static int skl_decoupled_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct hdac_ext_bus *ebus = get_bus_ctx(substream);
+ struct hdac_bus *bus = ebus_to_hbus(ebus);
+ struct hdac_ext_stream *stream;
+ int start;
+ unsigned long cookie;
+ struct hdac_stream *hstr;
+
+ stream = get_hdac_ext_stream(substream);
+ hstr = hdac_stream(stream);
+
+ if (!hstr->prepared)
+ return -EPIPE;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ start = 1;
+ break;
+
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ start = 0;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&bus->reg_lock, cookie);
+
+ if (start) {
+ snd_hdac_stream_start(hdac_stream(stream), true);
+ snd_hdac_stream_timecounter_init(hstr, 0);
+ } else {
+ snd_hdac_stream_stop(hdac_stream(stream));
+ }
+
+ spin_unlock_irqrestore(&bus->reg_lock, cookie);
return 0;
}
@@ -302,23 +383,72 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
struct skl *skl = get_skl_ctx(dai->dev);
struct skl_sst *ctx = skl->skl_sst;
struct skl_module_cfg *mconfig;
+ struct hdac_ext_bus *ebus = get_bus_ctx(substream);
+ struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
+ int ret;
mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
if (!mconfig)
return -EIO;
switch (cmd) {
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
+ skl_pcm_prepare(substream, dai);
+ /*
+ * enable DMA Resume enable bit for the stream, set the dpib
+ * & lpib position to resune before starting the DMA
+ */
+ snd_hdac_ext_stream_drsm_enable(ebus, true,
+ hdac_stream(stream)->index);
+ snd_hdac_ext_stream_set_dpibr(ebus, stream, stream->dpib);
+ snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
+
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ /*
+ * Start HOST DMA and Start FE Pipe.This is to make sure that
+ * there are no underrun/overrun in the case when the FE
+ * pipeline is started but there is a delay in starting the
+ * DMA channel on the host.
+ */
+ snd_hdac_ext_stream_decouple(ebus, stream, true);
+ ret = skl_decoupled_trigger(substream, cmd);
+ if (ret < 0)
+ return ret;
return skl_run_pipe(ctx, mconfig->pipe);
+ break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
- return skl_stop_pipe(ctx, mconfig->pipe);
+ case SNDRV_PCM_TRIGGER_STOP:
+ /*
+ * Stop FE Pipe first and stop DMA. This is to make sure that
+ * there are no underrun/overrun in the case if there is a delay
+ * between the two operations.
+ */
+ ret = skl_stop_pipe(ctx, mconfig->pipe);
+ if (ret < 0)
+ return ret;
+
+ ret = skl_decoupled_trigger(substream, cmd);
+ if (cmd == SNDRV_PCM_TRIGGER_SUSPEND) {
+ /* save the dpib and lpib positions */
+ stream->dpib = readl(ebus->bus.remap_addr +
+ AZX_REG_VS_SDXDPIB_XBASE +
+ (AZX_REG_VS_SDXDPIB_XINTERVAL *
+ hdac_stream(stream)->index));
+
+ stream->lpib = snd_hdac_stream_get_pos_lpib(
+ hdac_stream(stream));
+ snd_hdac_ext_stream_decouple(ebus, stream, false);
+ }
+ break;
default:
- return 0;
+ return -EINVAL;
}
+
+ return 0;
}
static int skl_link_hw_params(struct snd_pcm_substream *substream,
@@ -352,9 +482,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
p_params.stream = substream->stream;
p_params.link_dma_id = hdac_stream(link_dev)->stream_tag - 1;
- skl_tplg_be_update_params(dai, &p_params);
-
- return 0;
+ return skl_tplg_be_update_params(dai, &p_params);
}
static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
@@ -369,11 +497,6 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct hdac_ext_link *link;
- if (link_dev->link_prepared) {
- dev_dbg(dai->dev, "already stream is prepared - returning\n");
- return 0;
- }
-
dma_params = (struct skl_dma_params *)
snd_soc_dai_get_dma_data(codec_dai, substream);
if (dma_params)
@@ -381,14 +504,15 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n",
hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name);
- snd_hdac_ext_link_stream_reset(link_dev);
-
- snd_hdac_ext_link_stream_setup(link_dev, format_val);
-
link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
if (!link)
return -EINVAL;
+ snd_hdac_ext_bus_link_power_up(link);
+ snd_hdac_ext_link_stream_reset(link_dev);
+
+ snd_hdac_ext_link_stream_setup(link_dev, format_val);
+
snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag);
link_dev->link_prepared = 1;
@@ -400,12 +524,16 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
{
struct hdac_ext_stream *link_dev =
snd_soc_dai_get_dma_data(dai, substream);
+ struct hdac_ext_bus *ebus = get_bus_ctx(substream);
+ struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
dev_dbg(dai->dev, "In %s cmd=%d\n", __func__, cmd);
switch (cmd) {
+ case SNDRV_PCM_TRIGGER_RESUME:
+ skl_link_pcm_prepare(substream, dai);
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_RESUME:
+ snd_hdac_ext_stream_decouple(ebus, stream, true);
snd_hdac_ext_link_stream_start(link_dev);
break;
@@ -413,6 +541,8 @@ static int skl_link_pcm_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
snd_hdac_ext_link_stream_clear(link_dev);
+ if (cmd == SNDRV_PCM_TRIGGER_SUSPEND)
+ snd_hdac_ext_stream_decouple(ebus, stream, false);
break;
default:
@@ -443,19 +573,6 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
return 0;
}
-static int skl_be_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- return pm_runtime_get_sync(dai->dev);
-}
-
-static void skl_be_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- pm_runtime_mark_last_busy(dai->dev);
- pm_runtime_put_autosuspend(dai->dev);
-}
-
static struct snd_soc_dai_ops skl_pcm_dai_ops = {
.startup = skl_pcm_open,
.shutdown = skl_pcm_close,
@@ -466,24 +583,18 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = {
};
static struct snd_soc_dai_ops skl_dmic_dai_ops = {
- .startup = skl_be_startup,
.hw_params = skl_be_hw_params,
- .shutdown = skl_be_shutdown,
};
static struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
- .startup = skl_be_startup,
.hw_params = skl_be_hw_params,
- .shutdown = skl_be_shutdown,
};
static struct snd_soc_dai_ops skl_link_dai_ops = {
- .startup = skl_be_startup,
.prepare = skl_link_pcm_prepare,
.hw_params = skl_link_hw_params,
.hw_free = skl_link_hw_free,
.trigger = skl_link_pcm_trigger,
- .shutdown = skl_be_shutdown,
};
static struct snd_soc_dai_driver skl_platform_dai[] = {
@@ -511,7 +622,7 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
.capture = {
.stream_name = "Reference Capture",
.channels_min = HDA_MONO,
- .channels_max = HDA_STEREO,
+ .channels_max = HDA_QUAD,
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
@@ -538,6 +649,18 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
},
+{
+ .name = "DMIC Pin",
+ .ops = &skl_pcm_dai_ops,
+ .capture = {
+ .stream_name = "DMIC Capture",
+ .channels_min = HDA_MONO,
+ .channels_max = HDA_QUAD,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+ },
+},
+
/* BE CPU Dais */
{
.name = "SSP0 Pin",
@@ -558,6 +681,24 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
},
},
{
+ .name = "SSP1 Pin",
+ .ops = &skl_be_ssp_dai_ops,
+ .playback = {
+ .stream_name = "ssp1 Tx",
+ .channels_min = HDA_STEREO,
+ .channels_max = HDA_STEREO,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .stream_name = "ssp1 Rx",
+ .channels_min = HDA_STEREO,
+ .channels_max = HDA_STEREO,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+},
+{
.name = "iDisp Pin",
.ops = &skl_link_dai_ops,
.playback = {
@@ -573,8 +714,8 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
.ops = &skl_dmic_dai_ops,
.capture = {
.stream_name = "DMIC01 Rx",
- .channels_min = HDA_STEREO,
- .channels_max = HDA_STEREO,
+ .channels_min = HDA_MONO,
+ .channels_max = HDA_QUAD,
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
@@ -688,66 +829,15 @@ static int skl_coupled_trigger(struct snd_pcm_substream *substream,
return 0;
}
-static int skl_decoupled_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct hdac_ext_bus *ebus = get_bus_ctx(substream);
- struct hdac_bus *bus = ebus_to_hbus(ebus);
- struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct hdac_ext_stream *stream;
- int start;
- unsigned long cookie;
- struct hdac_stream *hstr;
-
- dev_dbg(bus->dev, "In %s cmd=%d streamname=%s\n", __func__, cmd, cpu_dai->name);
-
- stream = get_hdac_ext_stream(substream);
- hstr = hdac_stream(stream);
-
- if (!hstr->prepared)
- return -EPIPE;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_RESUME:
- start = 1;
- break;
-
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_STOP:
- start = 0;
- break;
-
- default:
- return -EINVAL;
- }
-
- spin_lock_irqsave(&bus->reg_lock, cookie);
-
- if (start)
- snd_hdac_stream_start(hdac_stream(stream), true);
- else
- snd_hdac_stream_stop(hdac_stream(stream));
-
- if (start)
- snd_hdac_stream_timecounter_init(hstr, 0);
-
- spin_unlock_irqrestore(&bus->reg_lock, cookie);
-
- return 0;
-}
static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
int cmd)
{
struct hdac_ext_bus *ebus = get_bus_ctx(substream);
- if (ebus->ppcap)
- return skl_decoupled_trigger(substream, cmd);
- else
+ if (!ebus->ppcap)
return skl_coupled_trigger(substream, cmd);
+
+ return 0;
}
/* calculate runtime delay from LPIB */
@@ -789,7 +879,7 @@ static unsigned int skl_get_position(struct hdac_ext_stream *hstream,
{
struct hdac_stream *hstr = hdac_stream(hstream);
struct snd_pcm_substream *substream = hstr->substream;
- struct hdac_ext_bus *ebus = get_bus_ctx(substream);
+ struct hdac_ext_bus *ebus;
unsigned int pos;
int delay;
@@ -800,6 +890,7 @@ static unsigned int skl_get_position(struct hdac_ext_stream *hstream,
pos = 0;
if (substream->runtime) {
+ ebus = get_bus_ctx(substream);
delay = skl_get_delay_from_lpib(ebus, hstream, pos)
+ codec_delay;
substream->runtime->delay += delay;
@@ -941,7 +1032,6 @@ int skl_platform_register(struct device *dev)
struct skl *skl = ebus_to_skl(ebus);
INIT_LIST_HEAD(&skl->ppl_list);
- INIT_LIST_HEAD(&skl->dapm_path_list);
ret = snd_soc_register_platform(dev, &skl_platform_drv);
if (ret) {
diff --git a/sound/soc/intel/skylake/skl-sst-cldma.c b/sound/soc/intel/skylake/skl-sst-cldma.c
index 44748ba98da2..da2329d17f4d 100644
--- a/sound/soc/intel/skylake/skl-sst-cldma.c
+++ b/sound/soc/intel/skylake/skl-sst-cldma.c
@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/mm.h>
#include <linux/kthread.h>
+#include <linux/delay.h>
#include "../common/sst-dsp.h"
#include "../common/sst-dsp-priv.h"
@@ -33,6 +34,53 @@ void skl_cldma_int_disable(struct sst_dsp *ctx)
SKL_ADSP_REG_ADSPIC, SKL_ADSPIC_CL_DMA, 0);
}
+static void skl_cldma_stream_run(struct sst_dsp *ctx, bool enable)
+{
+ unsigned char val;
+ int timeout;
+
+ sst_dsp_shim_update_bits_unlocked(ctx,
+ SKL_ADSP_REG_CL_SD_CTL,
+ CL_SD_CTL_RUN_MASK, CL_SD_CTL_RUN(enable));
+
+ udelay(3);
+ timeout = 300;
+ do {
+ /* waiting for hardware to report that the stream Run bit set */
+ val = sst_dsp_shim_read(ctx, SKL_ADSP_REG_CL_SD_CTL) &
+ CL_SD_CTL_RUN_MASK;
+ if (enable && val)
+ break;
+ else if (!enable && !val)
+ break;
+ udelay(3);
+ } while (--timeout);
+
+ if (timeout == 0)
+ dev_err(ctx->dev, "Failed to set Run bit=%d enable=%d\n", val, enable);
+}
+
+static void skl_cldma_stream_clear(struct sst_dsp *ctx)
+{
+ /* make sure Run bit is cleared before setting stream register */
+ skl_cldma_stream_run(ctx, 0);
+
+ sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL,
+ CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(0));
+ sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL,
+ CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(0));
+ sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL,
+ CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(0));
+ sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL,
+ CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(0));
+
+ sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, CL_SD_BDLPLBA(0));
+ sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, 0);
+
+ sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, 0);
+ sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, 0);
+}
+
/* Code loader helper APIs */
static void skl_cldma_setup_bdle(struct sst_dsp *ctx,
struct snd_dma_buffer *dmab_data,
@@ -68,6 +116,7 @@ static void skl_cldma_setup_controller(struct sst_dsp *ctx,
struct snd_dma_buffer *dmab_bdl, unsigned int max_size,
u32 count)
{
+ skl_cldma_stream_clear(ctx);
sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL,
CL_SD_BDLPLBA(dmab_bdl->addr));
sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU,
@@ -107,36 +156,13 @@ static void skl_cldma_cleanup_spb(struct sst_dsp *ctx)
sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_CL_SPBFIFO_SPIB, 0);
}
-static void skl_cldma_trigger(struct sst_dsp *ctx, bool enable)
-{
- if (enable)
- sst_dsp_shim_update_bits_unlocked(ctx,
- SKL_ADSP_REG_CL_SD_CTL,
- CL_SD_CTL_RUN_MASK, CL_SD_CTL_RUN(1));
- else
- sst_dsp_shim_update_bits_unlocked(ctx,
- SKL_ADSP_REG_CL_SD_CTL,
- CL_SD_CTL_RUN_MASK, CL_SD_CTL_RUN(0));
-}
-
static void skl_cldma_cleanup(struct sst_dsp *ctx)
{
skl_cldma_cleanup_spb(ctx);
+ skl_cldma_stream_clear(ctx);
- sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL,
- CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(0));
- sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL,
- CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(0));
- sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL,
- CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(0));
- sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL,
- CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(0));
-
- sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, CL_SD_BDLPLBA(0));
- sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, 0);
-
- sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, 0);
- sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, 0);
+ ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data);
+ ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_bdl);
}
static int skl_cldma_wait_interruptible(struct sst_dsp *ctx)
@@ -164,7 +190,7 @@ cleanup:
static void skl_cldma_stop(struct sst_dsp *ctx)
{
- ctx->cl_dev.ops.cl_trigger(ctx, false);
+ skl_cldma_stream_run(ctx, false);
}
static void skl_cldma_fill_buffer(struct sst_dsp *ctx, unsigned int size,
@@ -175,6 +201,21 @@ static void skl_cldma_fill_buffer(struct sst_dsp *ctx, unsigned int size,
ctx->cl_dev.dma_buffer_offset, trigger);
dev_dbg(ctx->dev, "spib position: %d\n", ctx->cl_dev.curr_spib_pos);
+ /*
+ * Check if the size exceeds buffer boundary. If it exceeds
+ * max_buffer size, then copy till buffer size and then copy
+ * remaining buffer from the start of ring buffer.
+ */
+ if (ctx->cl_dev.dma_buffer_offset + size > ctx->cl_dev.bufsize) {
+ unsigned int size_b = ctx->cl_dev.bufsize -
+ ctx->cl_dev.dma_buffer_offset;
+ memcpy(ctx->cl_dev.dmab_data.area + ctx->cl_dev.dma_buffer_offset,
+ curr_pos, size_b);
+ size -= size_b;
+ curr_pos += size_b;
+ ctx->cl_dev.dma_buffer_offset = 0;
+ }
+
memcpy(ctx->cl_dev.dmab_data.area + ctx->cl_dev.dma_buffer_offset,
curr_pos, size);
@@ -291,7 +332,7 @@ int skl_cldma_prepare(struct sst_dsp *ctx)
ctx->cl_dev.ops.cl_setup_controller = skl_cldma_setup_controller;
ctx->cl_dev.ops.cl_setup_spb = skl_cldma_setup_spb;
ctx->cl_dev.ops.cl_cleanup_spb = skl_cldma_cleanup_spb;
- ctx->cl_dev.ops.cl_trigger = skl_cldma_trigger;
+ ctx->cl_dev.ops.cl_trigger = skl_cldma_stream_run;
ctx->cl_dev.ops.cl_cleanup_controller = skl_cldma_cleanup;
ctx->cl_dev.ops.cl_copy_to_dmabuf = skl_cldma_copy_to_buf;
ctx->cl_dev.ops.cl_stop_dma = skl_cldma_stop;
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h
index 6bfcef449bdc..cbb40751c37e 100644
--- a/sound/soc/intel/skylake/skl-sst-dsp.h
+++ b/sound/soc/intel/skylake/skl-sst-dsp.h
@@ -58,9 +58,9 @@ struct sst_dsp_device;
#define SKL_ADSP_MMIO_LEN 0x10000
-#define SKL_ADSP_W0_STAT_SZ 0x800
+#define SKL_ADSP_W0_STAT_SZ 0x1000
-#define SKL_ADSP_W0_UP_SZ 0x800
+#define SKL_ADSP_W0_UP_SZ 0x1000
#define SKL_ADSP_W1_SZ 0x1000
@@ -114,6 +114,9 @@ struct skl_dsp_fw_ops {
int (*set_state_D0)(struct sst_dsp *ctx);
int (*set_state_D3)(struct sst_dsp *ctx);
unsigned int (*get_fw_errcode)(struct sst_dsp *ctx);
+ int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, char *mod_name);
+ int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id);
+
};
struct skl_dsp_loader_ops {
@@ -123,6 +126,17 @@ struct skl_dsp_loader_ops {
struct snd_dma_buffer *dmab);
};
+struct skl_load_module_info {
+ u16 mod_id;
+ const struct firmware *fw;
+};
+
+struct skl_module_table {
+ struct skl_load_module_info *mod_info;
+ unsigned int usage_cnt;
+ struct list_head list;
+};
+
void skl_cldma_process_intr(struct sst_dsp *ctx);
void skl_cldma_int_disable(struct sst_dsp *ctx);
int skl_cldma_prepare(struct sst_dsp *ctx);
@@ -139,7 +153,8 @@ void skl_dsp_free(struct sst_dsp *dsp);
int skl_dsp_boot(struct sst_dsp *ctx);
int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
- struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp);
+ const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
+ struct skl_sst **dsp);
void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
#endif /*__SKL_SST_DSP_H__*/
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c
index 3345ea0d4414..543460293b00 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.c
+++ b/sound/soc/intel/skylake/skl-sst-ipc.c
@@ -16,8 +16,10 @@
#include "../common/sst-dsp.h"
#include "../common/sst-dsp-priv.h"
+#include "skl.h"
#include "skl-sst-dsp.h"
#include "skl-sst-ipc.h"
+#include "sound/hdaudio_ext.h"
#define IPC_IXC_STATUS_BITS 24
@@ -130,6 +132,11 @@
#define IPC_SRC_QUEUE_MASK 0x7
#define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \
<< IPC_SRC_QUEUE_SHIFT)
+/* Load Module count */
+#define IPC_LOAD_MODULE_SHIFT 0
+#define IPC_LOAD_MODULE_MASK 0xFF
+#define IPC_LOAD_MODULE_CNT(x) (((x) & IPC_LOAD_MODULE_MASK) \
+ << IPC_LOAD_MODULE_SHIFT)
/* Save pipeline messgae extension register */
#define IPC_DMA_ID_SHIFT 0
@@ -317,6 +324,19 @@ static int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
wake_up(&skl->boot_wait);
break;
+ case IPC_GLB_NOTIFY_PHRASE_DETECTED:
+ dev_dbg(ipc->dev, "***** Phrase Detected **********\n");
+
+ /*
+ * Per HW recomendation, After phrase detection,
+ * clear the CGCTL.MISCBDCGE.
+ *
+ * This will be set back on stream closure
+ */
+ skl->enable_miscbdcge(ipc->dev, false);
+ skl->miscbdcg_disabled = true;
+ break;
+
default:
dev_err(ipc->dev, "ipc: Unhandled error msg=%x",
header.primary);
@@ -344,6 +364,8 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
switch (reply) {
case IPC_GLB_REPLY_SUCCESS:
dev_info(ipc->dev, "ipc FW reply %x: success\n", header.primary);
+ /* copy the rx data from the mailbox */
+ sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size);
break;
case IPC_GLB_REPLY_OUT_OF_MEMORY:
@@ -650,7 +672,7 @@ int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
header.primary, header.extension);
ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
- dx, sizeof(dx), NULL, 0);
+ dx, sizeof(*dx), NULL, 0);
if (ret < 0) {
dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
return ret;
@@ -728,6 +750,54 @@ int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
}
EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
+/*
+ * In order to load a module we need to send IPC to initiate that. DMA will
+ * performed to load the module memory. The FW supports multiple module load
+ * at single shot, so we can send IPC with N modules represented by
+ * module_cnt
+ */
+int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
+ u8 module_cnt, void *data)
+{
+ struct skl_ipc_header header = {0};
+ u64 *ipc_header = (u64 *)(&header);
+ int ret;
+
+ header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
+ header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
+ header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
+ header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
+
+ ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
+ (sizeof(u16) * module_cnt), NULL, 0);
+ if (ret < 0)
+ dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(skl_ipc_load_modules);
+
+int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt,
+ void *data)
+{
+ struct skl_ipc_header header = {0};
+ u64 *ipc_header = (u64 *)(&header);
+ int ret;
+
+ header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
+ header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
+ header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
+ header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
+
+ ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
+ (sizeof(u16) * module_cnt), NULL, 0);
+ if (ret < 0)
+ dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(skl_ipc_unload_modules);
+
int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
struct skl_ipc_large_config_msg *msg, u32 *param)
{
@@ -781,3 +851,54 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
return ret;
}
EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
+
+int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
+ struct skl_ipc_large_config_msg *msg, u32 *param)
+{
+ struct skl_ipc_header header = {0};
+ u64 *ipc_header = (u64 *)(&header);
+ int ret = 0;
+ size_t sz_remaining, rx_size, data_offset;
+
+ header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
+ header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
+ header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
+ header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
+ header.primary |= IPC_MOD_ID(msg->module_id);
+
+ header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
+ header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
+ header.extension |= IPC_FINAL_BLOCK(1);
+ header.extension |= IPC_INITIAL_BLOCK(1);
+
+ sz_remaining = msg->param_data_size;
+ data_offset = 0;
+
+ while (sz_remaining != 0) {
+ rx_size = sz_remaining > SKL_ADSP_W1_SZ
+ ? SKL_ADSP_W1_SZ : sz_remaining;
+ if (rx_size == sz_remaining)
+ header.extension |= IPC_FINAL_BLOCK(1);
+
+ ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0,
+ ((char *)param) + data_offset,
+ msg->param_data_size);
+ if (ret < 0) {
+ dev_err(ipc->dev,
+ "ipc: get large config fail, err: %d\n", ret);
+ return ret;
+ }
+ sz_remaining -= rx_size;
+ data_offset = msg->param_data_size - sz_remaining;
+
+ /* clear the fields */
+ header.extension &= IPC_INITIAL_BLOCK_CLEAR;
+ header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
+ /* fill the fields */
+ header.extension |= IPC_INITIAL_BLOCK(1);
+ header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h
index f1a154e45dc3..d59d1ba62a43 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.h
+++ b/sound/soc/intel/skylake/skl-sst-ipc.h
@@ -55,6 +55,11 @@ struct skl_sst {
/* IPC messaging */
struct sst_generic_ipc ipc;
+
+ /* callback for miscbdge */
+ void (*enable_miscbdcge)(struct device *dev, bool enable);
+ /*Is CGCTL.MISCBDCGE disabled*/
+ bool miscbdcg_disabled;
};
struct skl_ipc_init_instance_msg {
@@ -108,12 +113,21 @@ int skl_ipc_init_instance(struct sst_generic_ipc *sst_ipc,
int skl_ipc_bind_unbind(struct sst_generic_ipc *sst_ipc,
struct skl_ipc_bind_unbind_msg *msg);
+int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
+ u8 module_cnt, void *data);
+
+int skl_ipc_unload_modules(struct sst_generic_ipc *ipc,
+ u8 module_cnt, void *data);
+
int skl_ipc_set_dx(struct sst_generic_ipc *ipc,
u8 instance_id, u16 module_id, struct skl_ipc_dxstate_info *dx);
int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
struct skl_ipc_large_config_msg *msg, u32 *param);
+int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
+ struct skl_ipc_large_config_msg *msg, u32 *param);
+
void skl_ipc_int_enable(struct sst_dsp *dsp);
void skl_ipc_op_int_enable(struct sst_dsp *ctx);
void skl_ipc_op_int_disable(struct sst_dsp *ctx);
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c
index 3b83dc99f1d4..e26f4746afb7 100644
--- a/sound/soc/intel/skylake/skl-sst.c
+++ b/sound/soc/intel/skylake/skl-sst.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/err.h>
#include "../common/sst-dsp.h"
#include "../common/sst-dsp-priv.h"
#include "../common/sst-ipc.h"
@@ -37,6 +38,8 @@
#define SKL_INSTANCE_ID 0
#define SKL_BASE_FW_MODULE_ID 0
+#define SKL_NUM_MODULES 1
+
static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status)
{
u32 cur_sts;
@@ -77,7 +80,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
init_waitqueue_head(&skl->boot_wait);
if (ctx->fw == NULL) {
- ret = request_firmware(&ctx->fw, "dsp_fw_release.bin", ctx->dev);
+ ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
if (ret < 0) {
dev_err(ctx->dev, "Request firmware failed %d\n", ret);
skl_dsp_disable_core(ctx);
@@ -115,27 +118,28 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
dev_err(ctx->dev,
"Timeout waiting for ROM init done, reg:0x%x\n", reg);
ret = -EIO;
- goto skl_load_base_firmware_failed;
+ goto transfer_firmware_failed;
}
ret = skl_transfer_firmware(ctx, ctx->fw->data, ctx->fw->size);
if (ret < 0) {
dev_err(ctx->dev, "Transfer firmware failed%d\n", ret);
- goto skl_load_base_firmware_failed;
+ goto transfer_firmware_failed;
} else {
ret = wait_event_timeout(skl->boot_wait, skl->boot_complete,
msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
if (ret == 0) {
dev_err(ctx->dev, "DSP boot failed, FW Ready timed-out\n");
ret = -EIO;
- goto skl_load_base_firmware_failed;
+ goto transfer_firmware_failed;
}
dev_dbg(ctx->dev, "Download firmware successful%d\n", ret);
skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING);
}
return 0;
-
+transfer_firmware_failed:
+ ctx->cl_dev.ops.cl_cleanup_controller(ctx);
skl_load_base_firmware_failed:
skl_dsp_disable_core(ctx);
release_firmware(ctx->fw);
@@ -175,10 +179,15 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx)
dx.core_mask = SKL_DSP_CORE0_MASK;
dx.dx_mask = SKL_IPC_D3_MASK;
ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, SKL_BASE_FW_MODULE_ID, &dx);
- if (ret < 0) {
- dev_err(ctx->dev, "Failed to set DSP to D3 state\n");
- return ret;
- }
+ if (ret < 0)
+ dev_err(ctx->dev,
+ "D3 request to FW failed, continuing reset: %d", ret);
+
+ /* disable Interrupt */
+ ctx->cl_dev.ops.cl_cleanup_controller(ctx);
+ skl_cldma_int_disable(ctx);
+ skl_ipc_op_int_disable(ctx);
+ skl_ipc_int_disable(ctx);
ret = skl_dsp_disable_core(ctx);
if (ret < 0) {
@@ -187,12 +196,6 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx)
}
skl_dsp_set_state_locked(ctx, SKL_DSP_RESET);
- /* disable Interrupt */
- ctx->cl_dev.ops.cl_cleanup_controller(ctx);
- skl_cldma_int_disable(ctx);
- skl_ipc_op_int_disable(ctx);
- skl_ipc_int_disable(ctx);
-
return ret;
}
@@ -201,11 +204,182 @@ static unsigned int skl_get_errorcode(struct sst_dsp *ctx)
return sst_dsp_shim_read(ctx, SKL_ADSP_ERROR_CODE);
}
+/*
+ * since get/set_module are called from DAPM context,
+ * we don't need lock for usage count
+ */
+static int skl_get_module(struct sst_dsp *ctx, u16 mod_id)
+{
+ struct skl_module_table *module;
+
+ list_for_each_entry(module, &ctx->module_list, list) {
+ if (module->mod_info->mod_id == mod_id)
+ return ++module->usage_cnt;
+ }
+
+ return -EINVAL;
+}
+
+static int skl_put_module(struct sst_dsp *ctx, u16 mod_id)
+{
+ struct skl_module_table *module;
+
+ list_for_each_entry(module, &ctx->module_list, list) {
+ if (module->mod_info->mod_id == mod_id)
+ return --module->usage_cnt;
+ }
+
+ return -EINVAL;
+}
+
+static struct skl_module_table *skl_fill_module_table(struct sst_dsp *ctx,
+ char *mod_name, int mod_id)
+{
+ const struct firmware *fw;
+ struct skl_module_table *skl_module;
+ unsigned int size;
+ int ret;
+
+ ret = request_firmware(&fw, mod_name, ctx->dev);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Request Module %s failed :%d\n",
+ mod_name, ret);
+ return NULL;
+ }
+
+ skl_module = devm_kzalloc(ctx->dev, sizeof(*skl_module), GFP_KERNEL);
+ if (skl_module == NULL) {
+ release_firmware(fw);
+ return NULL;
+ }
+
+ size = sizeof(*skl_module->mod_info);
+ skl_module->mod_info = devm_kzalloc(ctx->dev, size, GFP_KERNEL);
+ if (skl_module->mod_info == NULL) {
+ release_firmware(fw);
+ return NULL;
+ }
+
+ skl_module->mod_info->mod_id = mod_id;
+ skl_module->mod_info->fw = fw;
+ list_add(&skl_module->list, &ctx->module_list);
+
+ return skl_module;
+}
+
+/* get a module from it's unique ID */
+static struct skl_module_table *skl_module_get_from_id(
+ struct sst_dsp *ctx, u16 mod_id)
+{
+ struct skl_module_table *module;
+
+ if (list_empty(&ctx->module_list)) {
+ dev_err(ctx->dev, "Module list is empty\n");
+ return NULL;
+ }
+
+ list_for_each_entry(module, &ctx->module_list, list) {
+ if (module->mod_info->mod_id == mod_id)
+ return module;
+ }
+
+ return NULL;
+}
+
+static int skl_transfer_module(struct sst_dsp *ctx,
+ struct skl_load_module_info *module)
+{
+ int ret;
+ struct skl_sst *skl = ctx->thread_context;
+
+ ret = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, module->fw->data,
+ module->fw->size);
+ if (ret < 0)
+ return ret;
+
+ ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES,
+ (void *)&module->mod_id);
+ if (ret < 0)
+ dev_err(ctx->dev, "Failed to Load module: %d\n", ret);
+
+ ctx->cl_dev.ops.cl_stop_dma(ctx);
+
+ return ret;
+}
+
+static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, char *guid)
+{
+ struct skl_module_table *module_entry = NULL;
+ int ret = 0;
+ char mod_name[64]; /* guid str = 32 chars + 4 hyphens */
+
+ snprintf(mod_name, sizeof(mod_name), "%s%s%s",
+ "intel/dsp_fw_", guid, ".bin");
+
+ module_entry = skl_module_get_from_id(ctx, mod_id);
+ if (module_entry == NULL) {
+ module_entry = skl_fill_module_table(ctx, mod_name, mod_id);
+ if (module_entry == NULL) {
+ dev_err(ctx->dev, "Failed to Load module\n");
+ return -EINVAL;
+ }
+ }
+
+ if (!module_entry->usage_cnt) {
+ ret = skl_transfer_module(ctx, module_entry->mod_info);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Failed to Load module\n");
+ return ret;
+ }
+ }
+
+ ret = skl_get_module(ctx, mod_id);
+
+ return ret;
+}
+
+static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id)
+{
+ int usage_cnt;
+ struct skl_sst *skl = ctx->thread_context;
+ int ret = 0;
+
+ usage_cnt = skl_put_module(ctx, mod_id);
+ if (usage_cnt < 0) {
+ dev_err(ctx->dev, "Module bad usage cnt!:%d\n", usage_cnt);
+ return -EIO;
+ }
+ ret = skl_ipc_unload_modules(&skl->ipc,
+ SKL_NUM_MODULES, &mod_id);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Failed to UnLoad module\n");
+ skl_get_module(ctx, mod_id);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void skl_clear_module_table(struct sst_dsp *ctx)
+{
+ struct skl_module_table *module, *tmp;
+
+ if (list_empty(&ctx->module_list))
+ return;
+
+ list_for_each_entry_safe(module, tmp, &ctx->module_list, list) {
+ list_del(&module->list);
+ release_firmware(module->mod_info->fw);
+ }
+}
+
static struct skl_dsp_fw_ops skl_fw_ops = {
.set_state_D0 = skl_set_dsp_D0,
.set_state_D3 = skl_set_dsp_D3,
.load_fw = skl_load_base_firmware,
.get_fw_errcode = skl_get_errorcode,
+ .load_mod = skl_load_module,
+ .unload_mod = skl_unload_module,
};
static struct sst_ops skl_ops = {
@@ -223,7 +397,7 @@ static struct sst_dsp_device skl_dev = {
};
int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
- struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp)
+ const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp)
{
struct skl_sst *skl;
struct sst_dsp *sst;
@@ -244,11 +418,13 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
sst = skl->dsp;
+ sst->fw_name = fw_name;
sst->addr.lpe = mmio_base;
sst->addr.shim = mmio_base;
sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);
+ INIT_LIST_HEAD(&sst->module_list);
sst->dsp_ops = dsp_ops;
sst->fw_ops = skl_fw_ops;
@@ -259,23 +435,24 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
ret = sst->fw_ops.load_fw(sst);
if (ret < 0) {
dev_err(dev, "Load base fw failed : %d", ret);
- return ret;
+ goto cleanup;
}
if (dsp)
*dsp = skl;
- return 0;
+ return ret;
- skl_ipc_free(&skl->ipc);
+cleanup:
+ skl_sst_dsp_cleanup(dev, skl);
return ret;
}
EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
{
+ skl_clear_module_table(ctx->dsp);
skl_ipc_free(&ctx->ipc);
- ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp);
ctx->dsp->ops->free(ctx->dsp);
}
EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup);
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index ad4d0f82603e..4624556f486d 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -26,6 +26,8 @@
#include "skl-topology.h"
#include "skl.h"
#include "skl-tplg-interface.h"
+#include "../common/sst-dsp.h"
+#include "../common/sst-dsp-priv.h"
#define SKL_CH_FIXUP_MASK (1 << 0)
#define SKL_RATE_FIXUP_MASK (1 << 1)
@@ -129,17 +131,15 @@ static void skl_dump_mconfig(struct skl_sst *ctx,
{
dev_dbg(ctx->dev, "Dumping config\n");
dev_dbg(ctx->dev, "Input Format:\n");
- dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt.channels);
- dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt.s_freq);
- dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt.ch_cfg);
- dev_dbg(ctx->dev, "valid bit depth = %d\n",
- mcfg->in_fmt.valid_bit_depth);
+ dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt[0].channels);
+ dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt[0].s_freq);
+ dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt[0].ch_cfg);
+ dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->in_fmt[0].valid_bit_depth);
dev_dbg(ctx->dev, "Output Format:\n");
- dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt.channels);
- dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt.s_freq);
- dev_dbg(ctx->dev, "valid bit depth = %d\n",
- mcfg->out_fmt.valid_bit_depth);
- dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt.ch_cfg);
+ dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt[0].channels);
+ dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt[0].s_freq);
+ dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->out_fmt[0].valid_bit_depth);
+ dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt[0].ch_cfg);
}
static void skl_tplg_update_params(struct skl_module_fmt *fmt,
@@ -149,8 +149,24 @@ static void skl_tplg_update_params(struct skl_module_fmt *fmt,
fmt->s_freq = params->s_freq;
if (fixup & SKL_CH_FIXUP_MASK)
fmt->channels = params->ch;
- if (fixup & SKL_FMT_FIXUP_MASK)
- fmt->valid_bit_depth = params->s_fmt;
+ if (fixup & SKL_FMT_FIXUP_MASK) {
+ fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt);
+
+ /*
+ * 16 bit is 16 bit container whereas 24 bit is in 32 bit
+ * container so update bit depth accordingly
+ */
+ switch (fmt->valid_bit_depth) {
+ case SKL_DEPTH_16BIT:
+ fmt->bit_depth = fmt->valid_bit_depth;
+ break;
+
+ default:
+ fmt->bit_depth = SKL_DEPTH_32BIT;
+ break;
+ }
+ }
+
}
/*
@@ -171,8 +187,9 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg,
int in_fixup, out_fixup;
struct skl_module_fmt *in_fmt, *out_fmt;
- in_fmt = &m_cfg->in_fmt;
- out_fmt = &m_cfg->out_fmt;
+ /* Fixups will be applied to pin 0 only */
+ in_fmt = &m_cfg->in_fmt[0];
+ out_fmt = &m_cfg->out_fmt[0];
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (is_fe) {
@@ -209,18 +226,25 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx,
struct skl_module_cfg *mcfg)
{
int multiplier = 1;
+ struct skl_module_fmt *in_fmt, *out_fmt;
+
+
+ /* Since fixups is applied to pin 0 only, ibs, obs needs
+ * change for pin 0 only
+ */
+ in_fmt = &mcfg->in_fmt[0];
+ out_fmt = &mcfg->out_fmt[0];
if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
multiplier = 5;
-
- mcfg->ibs = (mcfg->in_fmt.s_freq / 1000) *
- (mcfg->in_fmt.channels) *
- (mcfg->in_fmt.bit_depth >> 3) *
+ mcfg->ibs = (in_fmt->s_freq / 1000) *
+ (mcfg->in_fmt->channels) *
+ (mcfg->in_fmt->bit_depth >> 3) *
multiplier;
- mcfg->obs = (mcfg->out_fmt.s_freq / 1000) *
- (mcfg->out_fmt.channels) *
- (mcfg->out_fmt.bit_depth >> 3) *
+ mcfg->obs = (mcfg->out_fmt->s_freq / 1000) *
+ (mcfg->out_fmt->channels) *
+ (mcfg->out_fmt->bit_depth >> 3) *
multiplier;
}
@@ -292,6 +316,83 @@ static int skl_tplg_alloc_pipe_widget(struct device *dev,
}
/*
+ * some modules can have multiple params set from user control and
+ * need to be set after module is initialized. If set_param flag is
+ * set module params will be done after module is initialised.
+ */
+static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w,
+ struct skl_sst *ctx)
+{
+ int i, ret;
+ struct skl_module_cfg *mconfig = w->priv;
+ const struct snd_kcontrol_new *k;
+ struct soc_bytes_ext *sb;
+ struct skl_algo_data *bc;
+ struct skl_specific_cfg *sp_cfg;
+
+ if (mconfig->formats_config.caps_size > 0 &&
+ mconfig->formats_config.set_params == SKL_PARAM_SET) {
+ sp_cfg = &mconfig->formats_config;
+ ret = skl_set_module_params(ctx, sp_cfg->caps,
+ sp_cfg->caps_size,
+ sp_cfg->param_id, mconfig);
+ if (ret < 0)
+ return ret;
+ }
+
+ for (i = 0; i < w->num_kcontrols; i++) {
+ k = &w->kcontrol_news[i];
+ if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+ sb = (void *) k->private_value;
+ bc = (struct skl_algo_data *)sb->dobj.private;
+
+ if (bc->set_params == SKL_PARAM_SET) {
+ ret = skl_set_module_params(ctx,
+ (u32 *)bc->params, bc->max,
+ bc->param_id, mconfig);
+ if (ret < 0)
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * some module param can set from user control and this is required as
+ * when module is initailzed. if module param is required in init it is
+ * identifed by set_param flag. if set_param flag is not set, then this
+ * parameter needs to set as part of module init.
+ */
+static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w)
+{
+ const struct snd_kcontrol_new *k;
+ struct soc_bytes_ext *sb;
+ struct skl_algo_data *bc;
+ struct skl_module_cfg *mconfig = w->priv;
+ int i;
+
+ for (i = 0; i < w->num_kcontrols; i++) {
+ k = &w->kcontrol_news[i];
+ if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+ sb = (struct soc_bytes_ext *)k->private_value;
+ bc = (struct skl_algo_data *)sb->dobj.private;
+
+ if (bc->set_params != SKL_PARAM_INIT)
+ continue;
+
+ mconfig->formats_config.caps = (u32 *)&bc->params;
+ mconfig->formats_config.caps_size = bc->max;
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
* Inside a pipe instance, we can have various modules. These modules need
* to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by
* skl_init_module() routine, so invoke that for all modules in a pipeline
@@ -313,12 +414,25 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
if (!skl_tplg_alloc_pipe_mcps(skl, mconfig))
return -ENOMEM;
+ if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) {
+ ret = ctx->dsp->fw_ops.load_mod(ctx->dsp,
+ mconfig->id.module_id, mconfig->guid);
+ if (ret < 0)
+ return ret;
+ }
+
/*
* apply fix/conversion to module params based on
* FE/BE params
*/
skl_tplg_update_module_params(w, ctx);
- ret = skl_init_module(ctx, mconfig, NULL);
+
+ skl_tplg_set_module_init_data(w);
+ ret = skl_init_module(ctx, mconfig);
+ if (ret < 0)
+ return ret;
+
+ ret = skl_tplg_set_module_params(w, ctx);
if (ret < 0)
return ret;
}
@@ -326,6 +440,24 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
return 0;
}
+static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
+ struct skl_pipe *pipe)
+{
+ struct skl_pipe_module *w_module = NULL;
+ struct skl_module_cfg *mconfig = NULL;
+
+ list_for_each_entry(w_module, &pipe->w_list, node) {
+ mconfig = w_module->w->priv;
+
+ if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod)
+ return ctx->dsp->fw_ops.unload_mod(ctx->dsp,
+ mconfig->id.module_id);
+ }
+
+ /* no modules to unload in this path, so return */
+ return 0;
+}
+
/*
* Mixer module represents a pipeline. So in the Pre-PMU event of mixer we
* need create the pipeline. So we do following:
@@ -397,41 +529,24 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
return 0;
}
-/*
- * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA
- * we need to do following:
- * - Bind to sink pipeline
- * Since the sink pipes can be running and we don't get mixer event on
- * connect for already running mixer, we need to find the sink pipes
- * here and bind to them. This way dynamic connect works.
- * - Start sink pipeline, if not running
- * - Then run current pipe
- */
-static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
- struct skl *skl)
+static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
+ struct skl *skl,
+ struct skl_module_cfg *src_mconfig)
{
struct snd_soc_dapm_path *p;
- struct skl_dapm_path_list *path_list;
- struct snd_soc_dapm_widget *source, *sink;
- struct skl_module_cfg *src_mconfig, *sink_mconfig;
+ struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL;
+ struct skl_module_cfg *sink_mconfig;
struct skl_sst *ctx = skl->skl_sst;
- int ret = 0;
-
- source = w;
- src_mconfig = source->priv;
+ int ret;
- /*
- * find which sink it is connected to, bind with the sink,
- * if sink is not started, start sink pipe first, then start
- * this pipe
- */
- snd_soc_dapm_widget_for_each_source_path(w, p) {
+ snd_soc_dapm_widget_for_each_sink_path(w, p) {
if (!p->connect)
continue;
dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name);
dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name);
+ next_sink = p->sink;
/*
* here we will check widgets in sink pipelines, so that
* can be any widgets type and we are only interested if
@@ -441,7 +556,6 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
is_skl_dsp_widget_type(p->sink)) {
sink = p->sink;
- src_mconfig = source->priv;
sink_mconfig = sink->priv;
/* Bind source to sink, mixin is always source */
@@ -451,32 +565,89 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
/* Start sinks pipe first */
if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) {
- ret = skl_run_pipe(ctx, sink_mconfig->pipe);
+ if (sink_mconfig->pipe->conn_type !=
+ SKL_PIPE_CONN_TYPE_FE)
+ ret = skl_run_pipe(ctx,
+ sink_mconfig->pipe);
if (ret)
return ret;
}
-
- path_list = kzalloc(
- sizeof(struct skl_dapm_path_list),
- GFP_KERNEL);
- if (path_list == NULL)
- return -ENOMEM;
-
- /* Add connected path to one global list */
- path_list->dapm_path = p;
- list_add_tail(&path_list->node, &skl->dapm_path_list);
- break;
}
}
- /* Start source pipe last after starting all sinks */
- ret = skl_run_pipe(ctx, src_mconfig->pipe);
+ if (!sink)
+ return skl_tplg_bind_sinks(next_sink, skl, src_mconfig);
+
+ return 0;
+}
+
+/*
+ * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA
+ * we need to do following:
+ * - Bind to sink pipeline
+ * Since the sink pipes can be running and we don't get mixer event on
+ * connect for already running mixer, we need to find the sink pipes
+ * here and bind to them. This way dynamic connect works.
+ * - Start sink pipeline, if not running
+ * - Then run current pipe
+ */
+static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
+ struct skl *skl)
+{
+ struct skl_module_cfg *src_mconfig;
+ struct skl_sst *ctx = skl->skl_sst;
+ int ret = 0;
+
+ src_mconfig = w->priv;
+
+ /*
+ * find which sink it is connected to, bind with the sink,
+ * if sink is not started, start sink pipe first, then start
+ * this pipe
+ */
+ ret = skl_tplg_bind_sinks(w, skl, src_mconfig);
if (ret)
return ret;
+ /* Start source pipe last after starting all sinks */
+ if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
+ return skl_run_pipe(ctx, src_mconfig->pipe);
+
return 0;
}
+static struct snd_soc_dapm_widget *skl_get_src_dsp_widget(
+ struct snd_soc_dapm_widget *w, struct skl *skl)
+{
+ struct snd_soc_dapm_path *p;
+ struct snd_soc_dapm_widget *src_w = NULL;
+ struct skl_sst *ctx = skl->skl_sst;
+
+ snd_soc_dapm_widget_for_each_source_path(w, p) {
+ src_w = p->source;
+ if (!p->connect)
+ continue;
+
+ dev_dbg(ctx->dev, "sink widget=%s\n", w->name);
+ dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
+
+ /*
+ * here we will check widgets in sink pipelines, so that can
+ * be any widgets type and we are only interested if they are
+ * ones used for SKL so check that first
+ */
+ if ((p->source->priv != NULL) &&
+ is_skl_dsp_widget_type(p->source)) {
+ return p->source;
+ }
+ }
+
+ if (src_w != NULL)
+ return skl_get_src_dsp_widget(src_w, skl);
+
+ return NULL;
+}
+
/*
* in the Post-PMU event of mixer we need to do following:
* - Check if this pipe is running
@@ -490,7 +661,6 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
struct skl *skl)
{
int ret = 0;
- struct snd_soc_dapm_path *p;
struct snd_soc_dapm_widget *source, *sink;
struct skl_module_cfg *src_mconfig, *sink_mconfig;
struct skl_sst *ctx = skl->skl_sst;
@@ -504,32 +674,18 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
* one more sink before this sink got connected, Since source is
* started, bind this sink to source and start this pipe.
*/
- snd_soc_dapm_widget_for_each_sink_path(w, p) {
- if (!p->connect)
- continue;
-
- dev_dbg(ctx->dev, "sink widget=%s\n", w->name);
- dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
+ source = skl_get_src_dsp_widget(w, skl);
+ if (source != NULL) {
+ src_mconfig = source->priv;
+ sink_mconfig = sink->priv;
+ src_pipe_started = 1;
/*
- * here we will check widgets in sink pipelines, so that
- * can be any widgets type and we are only interested if
- * they are ones used for SKL so check that first
+ * check pipe state, then no need to bind or start the
+ * pipe
*/
- if ((p->source->priv != NULL) &&
- is_skl_dsp_widget_type(p->source)) {
- source = p->source;
- src_mconfig = source->priv;
- sink_mconfig = sink->priv;
- src_pipe_started = 1;
-
- /*
- * check pipe state, then no need to bind or start
- * the pipe
- */
- if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
- src_pipe_started = 0;
- }
+ if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
+ src_pipe_started = 0;
}
if (src_pipe_started) {
@@ -537,7 +693,8 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
if (ret)
return ret;
- ret = skl_run_pipe(ctx, sink_mconfig->pipe);
+ if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
+ ret = skl_run_pipe(ctx, sink_mconfig->pipe);
}
return ret;
@@ -552,52 +709,35 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w,
struct skl *skl)
{
- struct snd_soc_dapm_widget *source, *sink;
struct skl_module_cfg *src_mconfig, *sink_mconfig;
- int ret = 0, path_found = 0;
- struct skl_dapm_path_list *path_list, *tmp_list;
+ int ret = 0, i;
struct skl_sst *ctx = skl->skl_sst;
- sink = w;
- sink_mconfig = sink->priv;
+ sink_mconfig = w->priv;
/* Stop the pipe */
ret = skl_stop_pipe(ctx, sink_mconfig->pipe);
if (ret)
return ret;
- /*
- * This list, dapm_path_list handling here does not need any locks
- * as we are under dapm lock while handling widget events.
- * List can be manipulated safely only under dapm widgets handler
- * routines
- */
- list_for_each_entry_safe(path_list, tmp_list,
- &skl->dapm_path_list, node) {
- if (path_list->dapm_path->sink == sink) {
- dev_dbg(ctx->dev, "Path found = %s\n",
- path_list->dapm_path->name);
- source = path_list->dapm_path->source;
- src_mconfig = source->priv;
- path_found = 1;
-
- list_del(&path_list->node);
- kfree(path_list);
- break;
- }
- }
-
- /*
- * If path_found == 1, that means pmd for source pipe has
- * not occurred, source is connected to some other sink.
- * so its responsibility of sink to unbind itself from source.
- */
- if (path_found) {
- ret = skl_stop_pipe(ctx, src_mconfig->pipe);
- if (ret < 0)
- return ret;
+ for (i = 0; i < sink_mconfig->max_in_queue; i++) {
+ if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) {
+ src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg;
+ if (!src_mconfig)
+ continue;
+ /*
+ * If path_found == 1, that means pmd for source
+ * pipe has not occurred, source is connected to
+ * some other sink. so its responsibility of sink
+ * to unbind itself from source.
+ */
+ ret = skl_stop_pipe(ctx, src_mconfig->pipe);
+ if (ret < 0)
+ return ret;
- ret = skl_unbind_modules(ctx, src_mconfig, sink_mconfig);
+ ret = skl_unbind_modules(ctx,
+ src_mconfig, sink_mconfig);
+ }
}
return ret;
@@ -622,10 +762,12 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
int ret = 0;
skl_tplg_free_pipe_mcps(skl, mconfig);
+ skl_tplg_free_pipe_mem(skl, mconfig);
list_for_each_entry(w_module, &s_pipe->w_list, node) {
dst_module = w_module->w->priv;
+ skl_tplg_free_pipe_mcps(skl, dst_module);
if (src_module == NULL) {
src_module = dst_module;
continue;
@@ -639,9 +781,8 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
}
ret = skl_delete_pipe(ctx, mconfig->pipe);
- skl_tplg_free_pipe_mem(skl, mconfig);
- return ret;
+ return skl_tplg_unload_pipe_modules(ctx, s_pipe);
}
/*
@@ -653,47 +794,34 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
struct skl *skl)
{
- struct snd_soc_dapm_widget *source, *sink;
struct skl_module_cfg *src_mconfig, *sink_mconfig;
- int ret = 0, path_found = 0;
- struct skl_dapm_path_list *path_list, *tmp_path_list;
+ int ret = 0, i;
struct skl_sst *ctx = skl->skl_sst;
- source = w;
- src_mconfig = source->priv;
+ src_mconfig = w->priv;
- skl_tplg_free_pipe_mcps(skl, src_mconfig);
/* Stop the pipe since this is a mixin module */
ret = skl_stop_pipe(ctx, src_mconfig->pipe);
if (ret)
return ret;
- list_for_each_entry_safe(path_list, tmp_path_list, &skl->dapm_path_list, node) {
- if (path_list->dapm_path->source == source) {
- dev_dbg(ctx->dev, "Path found = %s\n",
- path_list->dapm_path->name);
- sink = path_list->dapm_path->sink;
- sink_mconfig = sink->priv;
- path_found = 1;
-
- list_del(&path_list->node);
- kfree(path_list);
- break;
+ for (i = 0; i < src_mconfig->max_out_queue; i++) {
+ if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) {
+ sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg;
+ if (!sink_mconfig)
+ continue;
+ /*
+ * This is a connecter and if path is found that means
+ * unbind between source and sink has not happened yet
+ */
+ ret = skl_stop_pipe(ctx, sink_mconfig->pipe);
+ if (ret < 0)
+ return ret;
+ ret = skl_unbind_modules(ctx, src_mconfig,
+ sink_mconfig);
}
}
- /*
- * This is a connector and if path is found that means
- * unbind between source and sink has not happened yet
- */
- if (path_found) {
- ret = skl_stop_pipe(ctx, src_mconfig->pipe);
- if (ret < 0)
- return ret;
-
- ret = skl_unbind_modules(ctx, src_mconfig, sink_mconfig);
- }
-
return ret;
}
@@ -774,6 +902,67 @@ static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol,
+ unsigned int __user *data, unsigned int size)
+{
+ struct soc_bytes_ext *sb =
+ (struct soc_bytes_ext *)kcontrol->private_value;
+ struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private;
+ struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+ struct skl_module_cfg *mconfig = w->priv;
+ struct skl *skl = get_skl_ctx(w->dapm->dev);
+
+ if (w->power)
+ skl_get_module_params(skl->skl_sst, (u32 *)bc->params,
+ bc->max, bc->param_id, mconfig);
+
+ if (bc->params) {
+ if (copy_to_user(data, &bc->param_id, sizeof(u32)))
+ return -EFAULT;
+ if (copy_to_user(data + 1, &size, sizeof(u32)))
+ return -EFAULT;
+ if (copy_to_user(data + 2, bc->params, size))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+#define SKL_PARAM_VENDOR_ID 0xff
+
+static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
+ const unsigned int __user *data, unsigned int size)
+{
+ struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+ struct skl_module_cfg *mconfig = w->priv;
+ struct soc_bytes_ext *sb =
+ (struct soc_bytes_ext *)kcontrol->private_value;
+ struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private;
+ struct skl *skl = get_skl_ctx(w->dapm->dev);
+
+ if (ac->params) {
+ /*
+ * if the param_is is of type Vendor, firmware expects actual
+ * parameter id and size from the control.
+ */
+ if (ac->param_id == SKL_PARAM_VENDOR_ID) {
+ if (copy_from_user(ac->params, data, size))
+ return -EFAULT;
+ } else {
+ if (copy_from_user(ac->params,
+ data + 2 * sizeof(u32), size))
+ return -EFAULT;
+ }
+
+ if (w->power)
+ return skl_set_module_params(skl->skl_sst,
+ (u32 *)ac->params, ac->max,
+ ac->param_id, mconfig);
+ }
+
+ return 0;
+}
+
/*
* The FE params are passed by hw_params of the DAI.
* On hw_params, the params are stored in Gateway module of the FE and we
@@ -790,9 +979,9 @@ int skl_tplg_update_pipe_params(struct device *dev,
memcpy(pipe->p_params, params, sizeof(*params));
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
- format = &mconfig->in_fmt;
+ format = &mconfig->in_fmt[0];
else
- format = &mconfig->out_fmt;
+ format = &mconfig->out_fmt[0];
/* set the hw_params */
format->s_freq = params->s_freq;
@@ -809,6 +998,7 @@ int skl_tplg_update_pipe_params(struct device *dev,
break;
case SKL_DEPTH_24BIT:
+ case SKL_DEPTH_32BIT:
format->bit_depth = SKL_DEPTH_32BIT;
break;
@@ -846,7 +1036,7 @@ skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream)
w = dai->playback_widget;
snd_soc_dapm_widget_for_each_sink_path(w, p) {
if (p->connect && p->sink->power &&
- is_skl_dsp_widget_type(p->sink))
+ !is_skl_dsp_widget_type(p->sink))
continue;
if (p->sink->priv) {
@@ -859,7 +1049,7 @@ skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream)
w = dai->capture_widget;
snd_soc_dapm_widget_for_each_source_path(w, p) {
if (p->connect && p->source->power &&
- is_skl_dsp_widget_type(p->source))
+ !is_skl_dsp_widget_type(p->source))
continue;
if (p->source->priv) {
@@ -920,6 +1110,9 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
memcpy(pipe->p_params, params, sizeof(*params));
+ if (link_type == NHLT_LINK_HDA)
+ return 0;
+
/* update the blob based on virtual bus_id*/
cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type,
params->s_fmt, params->ch,
@@ -950,18 +1143,13 @@ static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai,
if (p->connect && is_skl_dsp_widget_type(p->source) &&
p->source->priv) {
- if (!p->source->power) {
- ret = skl_tplg_be_fill_pipe_params(
- dai, p->source->priv,
- params);
- if (ret < 0)
- return ret;
- } else {
- return -EBUSY;
- }
+ ret = skl_tplg_be_fill_pipe_params(dai,
+ p->source->priv, params);
+ if (ret < 0)
+ return ret;
} else {
- ret = skl_tplg_be_set_src_pipe_params(
- dai, p->source, params);
+ ret = skl_tplg_be_set_src_pipe_params(dai,
+ p->source, params);
if (ret < 0)
return ret;
}
@@ -980,15 +1168,10 @@ static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai,
if (p->connect && is_skl_dsp_widget_type(p->sink) &&
p->sink->priv) {
- if (!p->sink->power) {
- ret = skl_tplg_be_fill_pipe_params(
- dai, p->sink->priv, params);
- if (ret < 0)
- return ret;
- } else {
- return -EBUSY;
- }
-
+ ret = skl_tplg_be_fill_pipe_params(dai,
+ p->sink->priv, params);
+ if (ret < 0)
+ return ret;
} else {
ret = skl_tplg_be_set_sink_pipe_params(
dai, p->sink, params);
@@ -1030,6 +1213,11 @@ static const struct snd_soc_tplg_widget_events skl_tplg_widget_ops[] = {
{SKL_PGA_EVENT, skl_tplg_pga_event},
};
+static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = {
+ {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get,
+ skl_tplg_tlv_control_set},
+};
+
/*
* The topology binary passes the pin info for a module so initialize the pin
* info passed into module instance
@@ -1045,6 +1233,7 @@ static void skl_fill_module_pin_info(struct skl_dfw_module_pin *dfw_pin,
m_pin[i].id.instance_id = dfw_pin[i].instance_id;
m_pin[i].in_use = false;
m_pin[i].is_dynamic = is_dynamic;
+ m_pin[i].pin_state = SKL_PIN_UNBIND;
}
}
@@ -1092,6 +1281,24 @@ static struct skl_pipe *skl_tplg_add_pipe(struct device *dev,
return ppl->pipe;
}
+static void skl_tplg_fill_fmt(struct skl_module_fmt *dst_fmt,
+ struct skl_dfw_module_fmt *src_fmt,
+ int pins)
+{
+ int i;
+
+ for (i = 0; i < pins; i++) {
+ dst_fmt[i].channels = src_fmt[i].channels;
+ dst_fmt[i].s_freq = src_fmt[i].freq;
+ dst_fmt[i].bit_depth = src_fmt[i].bit_depth;
+ dst_fmt[i].valid_bit_depth = src_fmt[i].valid_bit_depth;
+ dst_fmt[i].ch_cfg = src_fmt[i].ch_cfg;
+ dst_fmt[i].ch_map = src_fmt[i].ch_map;
+ dst_fmt[i].interleaving_style = src_fmt[i].interleaving_style;
+ dst_fmt[i].sample_type = src_fmt[i].sample_type;
+ }
+}
+
/*
* Topology core widget load callback
*
@@ -1130,22 +1337,16 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
mconfig->max_in_queue = dfw_config->max_in_queue;
mconfig->max_out_queue = dfw_config->max_out_queue;
mconfig->is_loadable = dfw_config->is_loadable;
- mconfig->in_fmt.channels = dfw_config->in_fmt.channels;
- mconfig->in_fmt.s_freq = dfw_config->in_fmt.freq;
- mconfig->in_fmt.bit_depth = dfw_config->in_fmt.bit_depth;
- mconfig->in_fmt.valid_bit_depth =
- dfw_config->in_fmt.valid_bit_depth;
- mconfig->in_fmt.ch_cfg = dfw_config->in_fmt.ch_cfg;
- mconfig->out_fmt.channels = dfw_config->out_fmt.channels;
- mconfig->out_fmt.s_freq = dfw_config->out_fmt.freq;
- mconfig->out_fmt.bit_depth = dfw_config->out_fmt.bit_depth;
- mconfig->out_fmt.valid_bit_depth =
- dfw_config->out_fmt.valid_bit_depth;
- mconfig->out_fmt.ch_cfg = dfw_config->out_fmt.ch_cfg;
+ skl_tplg_fill_fmt(mconfig->in_fmt, dfw_config->in_fmt,
+ MODULE_MAX_IN_PINS);
+ skl_tplg_fill_fmt(mconfig->out_fmt, dfw_config->out_fmt,
+ MODULE_MAX_OUT_PINS);
+
mconfig->params_fixup = dfw_config->params_fixup;
mconfig->converter = dfw_config->converter;
mconfig->m_type = dfw_config->module_type;
mconfig->vbus_id = dfw_config->vbus_id;
+ mconfig->mem_pages = dfw_config->mem_pages;
pipe = skl_tplg_add_pipe(bus->dev, skl, &dfw_config->pipe);
if (pipe)
@@ -1156,10 +1357,13 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
mconfig->time_slot = dfw_config->time_slot;
mconfig->formats_config.caps_size = dfw_config->caps.caps_size;
- mconfig->m_in_pin = devm_kzalloc(bus->dev,
- (mconfig->max_in_queue) *
- sizeof(*mconfig->m_in_pin),
- GFP_KERNEL);
+ if (dfw_config->is_loadable)
+ memcpy(mconfig->guid, dfw_config->uuid,
+ ARRAY_SIZE(dfw_config->uuid));
+
+ mconfig->m_in_pin = devm_kzalloc(bus->dev, (mconfig->max_in_queue) *
+ sizeof(*mconfig->m_in_pin),
+ GFP_KERNEL);
if (!mconfig->m_in_pin)
return -ENOMEM;
@@ -1188,7 +1392,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
return -ENOMEM;
memcpy(mconfig->formats_config.caps, dfw_config->caps.caps,
- dfw_config->caps.caps_size);
+ dfw_config->caps.caps_size);
+ mconfig->formats_config.param_id = dfw_config->caps.param_id;
+ mconfig->formats_config.set_params = dfw_config->caps.set_params;
bind_event:
if (tplg_w->event_type == 0) {
@@ -1209,8 +1415,70 @@ bind_event:
return 0;
}
+static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
+ struct snd_soc_tplg_bytes_control *bc)
+{
+ struct skl_algo_data *ac;
+ struct skl_dfw_algo_data *dfw_ac =
+ (struct skl_dfw_algo_data *)bc->priv.data;
+
+ ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL);
+ if (!ac)
+ return -ENOMEM;
+
+ /* Fill private data */
+ ac->max = dfw_ac->max;
+ ac->param_id = dfw_ac->param_id;
+ ac->set_params = dfw_ac->set_params;
+
+ if (ac->max) {
+ ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL);
+ if (!ac->params)
+ return -ENOMEM;
+
+ if (dfw_ac->params)
+ memcpy(ac->params, dfw_ac->params, ac->max);
+ }
+
+ be->dobj.private = ac;
+ return 0;
+}
+
+static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
+ struct snd_kcontrol_new *kctl,
+ struct snd_soc_tplg_ctl_hdr *hdr)
+{
+ struct soc_bytes_ext *sb;
+ struct snd_soc_tplg_bytes_control *tplg_bc;
+ struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
+ struct hdac_bus *bus = ebus_to_hbus(ebus);
+
+ switch (hdr->ops.info) {
+ case SND_SOC_TPLG_CTL_BYTES:
+ tplg_bc = container_of(hdr,
+ struct snd_soc_tplg_bytes_control, hdr);
+ if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+ sb = (struct soc_bytes_ext *)kctl->private_value;
+ if (tplg_bc->priv.size)
+ return skl_init_algo_data(
+ bus->dev, sb, tplg_bc);
+ }
+ break;
+
+ default:
+ dev_warn(bus->dev, "Control load not supported %d:%d:%d\n",
+ hdr->ops.get, hdr->ops.put, hdr->ops.info);
+ break;
+ }
+
+ return 0;
+}
+
static struct snd_soc_tplg_ops skl_tplg_ops = {
.widget_load = skl_tplg_widget_load,
+ .control_load = skl_tplg_control_load,
+ .bytes_ext_ops = skl_tlv_ops,
+ .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
};
/* This will be read from topology manifest, currently defined here */
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h
index 76053a8de41c..9aa2a2b6598a 100644
--- a/sound/soc/intel/skylake/skl-topology.h
+++ b/sound/soc/intel/skylake/skl-topology.h
@@ -36,6 +36,9 @@
/* Maximum number of coefficients up down mixer module */
#define UP_DOWN_MIXER_MAX_COEFF 6
+#define MODULE_MAX_IN_PINS 8
+#define MODULE_MAX_OUT_PINS 8
+
enum skl_channel_index {
SKL_CHANNEL_LEFT = 0,
SKL_CHANNEL_RIGHT = 1,
@@ -55,12 +58,6 @@ enum skl_bitdepth {
SKL_DEPTH_INVALID
};
-enum skl_interleaving {
- /* [s1_ch1...s1_chN,...,sM_ch1...sM_chN] */
- SKL_INTERLEAVING_PER_CHANNEL = 0,
- /* [s1_ch1...sM_ch1,...,s1_chN...sM_chN] */
- SKL_INTERLEAVING_PER_SAMPLE = 1,
-};
enum skl_s_freq {
SKL_FS_8000 = 8000,
@@ -143,6 +140,16 @@ struct skl_up_down_mixer_cfg {
s32 coeff[UP_DOWN_MIXER_MAX_COEFF];
} __packed;
+struct skl_algo_cfg {
+ struct skl_base_cfg base_cfg;
+ char params[0];
+} __packed;
+
+struct skl_base_outfmt_cfg {
+ struct skl_base_cfg base_cfg;
+ struct skl_audio_data_format out_fmt;
+} __packed;
+
enum skl_dma_type {
SKL_DMA_HDA_HOST_OUTPUT_CLASS = 0,
SKL_DMA_HDA_HOST_INPUT_CLASS = 1,
@@ -178,21 +185,34 @@ struct skl_module_fmt {
u32 bit_depth;
u32 valid_bit_depth;
u32 ch_cfg;
+ u32 interleaving_style;
+ u32 sample_type;
+ u32 ch_map;
};
+struct skl_module_cfg;
+
struct skl_module_inst_id {
u32 module_id;
u32 instance_id;
};
+enum skl_module_pin_state {
+ SKL_PIN_UNBIND = 0,
+ SKL_PIN_BIND_DONE = 1,
+};
+
struct skl_module_pin {
struct skl_module_inst_id id;
- u8 pin_index;
bool is_dynamic;
bool in_use;
+ enum skl_module_pin_state pin_state;
+ struct skl_module_cfg *tgt_mcfg;
};
struct skl_specific_cfg {
+ u32 set_params;
+ u32 param_id;
u32 caps_size;
u32 *caps;
};
@@ -238,9 +258,13 @@ enum skl_module_state {
};
struct skl_module_cfg {
+ char guid[SKL_UUID_STR_SZ];
struct skl_module_inst_id id;
- struct skl_module_fmt in_fmt;
- struct skl_module_fmt out_fmt;
+ u8 domain;
+ bool homogenous_inputs;
+ bool homogenous_outputs;
+ struct skl_module_fmt in_fmt[MODULE_MAX_IN_PINS];
+ struct skl_module_fmt out_fmt[MODULE_MAX_OUT_PINS];
u8 max_in_queue;
u8 max_out_queue;
u8 in_queue_mask;
@@ -258,6 +282,7 @@ struct skl_module_cfg {
u32 params_fixup;
u32 converter;
u32 vbus_id;
+ u32 mem_pages;
struct skl_module_pin *m_in_pin;
struct skl_module_pin *m_out_pin;
enum skl_module_type m_type;
@@ -267,13 +292,15 @@ struct skl_module_cfg {
struct skl_specific_cfg formats_config;
};
-struct skl_pipeline {
- struct skl_pipe *pipe;
- struct list_head node;
+struct skl_algo_data {
+ u32 param_id;
+ u32 set_params;
+ u32 max;
+ char *params;
};
-struct skl_dapm_path_list {
- struct snd_soc_dapm_path *dapm_path;
+struct skl_pipeline {
+ struct skl_pipe *pipe;
struct list_head node;
};
@@ -305,8 +332,7 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
-int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config,
- char *param);
+int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config);
int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg
*src_module, struct skl_module_cfg *dst_module);
@@ -314,5 +340,10 @@ int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg
int skl_unbind_modules(struct skl_sst *ctx, struct skl_module_cfg
*src_module, struct skl_module_cfg *dst_module);
+int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size,
+ u32 param_id, struct skl_module_cfg *mcfg);
+int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size,
+ u32 param_id, struct skl_module_cfg *mcfg);
+
enum skl_bitdepth skl_get_bit_depth(int params);
#endif
diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h
index 2bc396d54cbe..c9ae010b3cc8 100644
--- a/sound/soc/intel/skylake/skl-tplg-interface.h
+++ b/sound/soc/intel/skylake/skl-tplg-interface.h
@@ -23,15 +23,13 @@
* Default types range from 0~12. type can range from 0 to 0xff
* SST types start at higher to avoid any overlapping in future
*/
-#define SOC_CONTROL_TYPE_HDA_SST_ALGO_PARAMS 0x100
-#define SOC_CONTROL_TYPE_HDA_SST_MUX 0x101
-#define SOC_CONTROL_TYPE_HDA_SST_MIX 0x101
-#define SOC_CONTROL_TYPE_HDA_SST_BYTE 0x103
+#define SKL_CONTROL_TYPE_BYTE_TLV 0x100
#define HDA_SST_CFG_MAX 900 /* size of copier cfg*/
#define MAX_IN_QUEUE 8
#define MAX_OUT_QUEUE 8
+#define SKL_UUID_STR_SZ 40
/* Event types goes here */
/* Reserve event type 0 for no event handlers */
enum skl_event_types {
@@ -72,6 +70,7 @@ enum skl_ch_cfg {
SKL_CH_CFG_DUAL_MONO = 9,
SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10,
SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11,
+ SKL_CH_CFG_4_CHANNEL = 12,
SKL_CH_CFG_INVALID
};
@@ -79,7 +78,9 @@ enum skl_module_type {
SKL_MODULE_TYPE_MIXER = 0,
SKL_MODULE_TYPE_COPIER,
SKL_MODULE_TYPE_UPDWMIX,
- SKL_MODULE_TYPE_SRCINT
+ SKL_MODULE_TYPE_SRCINT,
+ SKL_MODULE_TYPE_ALGO,
+ SKL_MODULE_TYPE_BASE_OUTFMT
};
enum skl_core_affinity {
@@ -110,6 +111,42 @@ enum skl_dev_type {
SKL_DEVICE_NONE
};
+/**
+ * enum skl_interleaving - interleaving style
+ *
+ * @SKL_INTERLEAVING_PER_CHANNEL: [s1_ch1...s1_chN,...,sM_ch1...sM_chN]
+ * @SKL_INTERLEAVING_PER_SAMPLE: [s1_ch1...sM_ch1,...,s1_chN...sM_chN]
+ */
+enum skl_interleaving {
+ SKL_INTERLEAVING_PER_CHANNEL = 0,
+ SKL_INTERLEAVING_PER_SAMPLE = 1,
+};
+
+enum skl_sample_type {
+ SKL_SAMPLE_TYPE_INT_MSB = 0,
+ SKL_SAMPLE_TYPE_INT_LSB = 1,
+ SKL_SAMPLE_TYPE_INT_SIGNED = 2,
+ SKL_SAMPLE_TYPE_INT_UNSIGNED = 3,
+ SKL_SAMPLE_TYPE_FLOAT = 4
+};
+
+enum module_pin_type {
+ /* All pins of the module takes same PCM inputs or outputs
+ * e.g. mixout
+ */
+ SKL_PIN_TYPE_HOMOGENEOUS,
+ /* All pins of the module takes different PCM inputs or outputs
+ * e.g mux
+ */
+ SKL_PIN_TYPE_HETEROGENEOUS,
+};
+
+enum skl_module_param_type {
+ SKL_PARAM_DEFAULT = 0,
+ SKL_PARAM_INIT,
+ SKL_PARAM_SET
+};
+
struct skl_dfw_module_pin {
u16 module_id;
u16 instance_id;
@@ -121,9 +158,15 @@ struct skl_dfw_module_fmt {
u32 bit_depth;
u32 valid_bit_depth;
u32 ch_cfg;
+ u32 interleaving_style;
+ u32 sample_type;
+ u32 ch_map;
} __packed;
struct skl_dfw_module_caps {
+ u32 set_params:2;
+ u32 rsvd:30;
+ u32 param_id;
u32 caps_size;
u32 caps[HDA_SST_CFG_MAX];
};
@@ -131,41 +174,57 @@ struct skl_dfw_module_caps {
struct skl_dfw_pipe {
u8 pipe_id;
u8 pipe_priority;
- u16 conn_type;
- u32 memory_pages;
+ u16 conn_type:4;
+ u16 rsvd:4;
+ u16 memory_pages:8;
} __packed;
struct skl_dfw_module {
+ char uuid[SKL_UUID_STR_SZ];
+
u16 module_id;
u16 instance_id;
u32 max_mcps;
- u8 core_id;
- u8 max_in_queue;
- u8 max_out_queue;
- u8 is_loadable;
- u8 conn_type;
- u8 dev_type;
- u8 hw_conn_type;
- u8 time_slot;
+ u32 mem_pages;
u32 obs;
u32 ibs;
- u32 params_fixup;
- u32 converter;
- u32 module_type;
u32 vbus_id;
- u8 is_dynamic_in_pin;
- u8 is_dynamic_out_pin;
+
+ u32 max_in_queue:8;
+ u32 max_out_queue:8;
+ u32 time_slot:8;
+ u32 core_id:4;
+ u32 rsvd1:4;
+
+ u32 module_type:8;
+ u32 conn_type:4;
+ u32 dev_type:4;
+ u32 hw_conn_type:4;
+ u32 rsvd2:12;
+
+ u32 params_fixup:8;
+ u32 converter:8;
+ u32 input_pin_type:1;
+ u32 output_pin_type:1;
+ u32 is_dynamic_in_pin:1;
+ u32 is_dynamic_out_pin:1;
+ u32 is_loadable:1;
+ u32 rsvd3:11;
+
struct skl_dfw_pipe pipe;
- struct skl_dfw_module_fmt in_fmt;
- struct skl_dfw_module_fmt out_fmt;
+ struct skl_dfw_module_fmt in_fmt[MAX_IN_QUEUE];
+ struct skl_dfw_module_fmt out_fmt[MAX_OUT_QUEUE];
struct skl_dfw_module_pin in_pin[MAX_IN_QUEUE];
struct skl_dfw_module_pin out_pin[MAX_OUT_QUEUE];
struct skl_dfw_module_caps caps;
} __packed;
struct skl_dfw_algo_data {
+ u32 set_params:2;
+ u32 rsvd:30;
+ u32 param_id;
u32 max;
- char *params;
+ char params[0];
} __packed;
#endif
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index caa69c4598a6..443a15de94b5 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -27,7 +27,10 @@
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <sound/pcm.h>
+#include "../common/sst-acpi.h"
#include "skl.h"
+#include "skl-sst-dsp.h"
+#include "skl-sst-ipc.h"
/*
* initialize the PCI registers
@@ -58,6 +61,49 @@ static void skl_init_pci(struct skl *skl)
skl_update_pci_byte(skl->pci, AZX_PCIREG_TCSEL, 0x07, 0);
}
+static void update_pci_dword(struct pci_dev *pci,
+ unsigned int reg, u32 mask, u32 val)
+{
+ u32 data = 0;
+
+ pci_read_config_dword(pci, reg, &data);
+ data &= ~mask;
+ data |= (val & mask);
+ pci_write_config_dword(pci, reg, data);
+}
+
+/*
+ * skl_enable_miscbdcge - enable/dsiable CGCTL.MISCBDCGE bits
+ *
+ * @dev: device pointer
+ * @enable: enable/disable flag
+ */
+static void skl_enable_miscbdcge(struct device *dev, bool enable)
+{
+ struct pci_dev *pci = to_pci_dev(dev);
+ u32 val;
+
+ val = enable ? AZX_CGCTL_MISCBDCGE_MASK : 0;
+
+ update_pci_dword(pci, AZX_PCIREG_CGCTL, AZX_CGCTL_MISCBDCGE_MASK, val);
+}
+
+/*
+ * While performing reset, controller may not come back properly causing
+ * issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset
+ * (init chip) and then again set CGCTL.MISCBDCGE to 1
+ */
+static int skl_init_chip(struct hdac_bus *bus, bool full_reset)
+{
+ int ret;
+
+ skl_enable_miscbdcge(bus->dev, false);
+ ret = snd_hdac_bus_init_chip(bus, full_reset);
+ skl_enable_miscbdcge(bus->dev, true);
+
+ return ret;
+}
+
/* called from IRQ */
static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr)
{
@@ -130,6 +176,39 @@ static int skl_acquire_irq(struct hdac_ext_bus *ebus, int do_disconnect)
return 0;
}
+#ifdef CONFIG_PM
+static int _skl_suspend(struct hdac_ext_bus *ebus)
+{
+ struct skl *skl = ebus_to_skl(ebus);
+ struct hdac_bus *bus = ebus_to_hbus(ebus);
+ int ret;
+
+ snd_hdac_ext_bus_link_power_down_all(ebus);
+
+ ret = skl_suspend_dsp(skl);
+ if (ret < 0)
+ return ret;
+
+ snd_hdac_bus_stop_chip(bus);
+ skl_enable_miscbdcge(bus->dev, false);
+ snd_hdac_bus_enter_link_reset(bus);
+ skl_enable_miscbdcge(bus->dev, true);
+
+ return 0;
+}
+
+static int _skl_resume(struct hdac_ext_bus *ebus)
+{
+ struct skl *skl = ebus_to_skl(ebus);
+ struct hdac_bus *bus = ebus_to_hbus(ebus);
+
+ skl_init_pci(skl);
+ skl_init_chip(bus, true);
+
+ return skl_resume_dsp(skl);
+}
+#endif
+
#ifdef CONFIG_PM_SLEEP
/*
* power management
@@ -138,26 +217,46 @@ static int skl_suspend(struct device *dev)
{
struct pci_dev *pci = to_pci_dev(dev);
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
+ struct skl *skl = ebus_to_skl(ebus);
struct hdac_bus *bus = ebus_to_hbus(ebus);
- snd_hdac_bus_stop_chip(bus);
- snd_hdac_bus_enter_link_reset(bus);
-
- return 0;
+ /*
+ * Do not suspend if streams which are marked ignore suspend are
+ * running, we need to save the state for these and continue
+ */
+ if (skl->supend_active) {
+ snd_hdac_ext_bus_link_power_down_all(ebus);
+ enable_irq_wake(bus->irq);
+ pci_save_state(pci);
+ pci_disable_device(pci);
+ return 0;
+ } else {
+ return _skl_suspend(ebus);
+ }
}
static int skl_resume(struct device *dev)
{
struct pci_dev *pci = to_pci_dev(dev);
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
+ struct skl *skl = ebus_to_skl(ebus);
struct hdac_bus *bus = ebus_to_hbus(ebus);
- struct skl *hda = ebus_to_skl(ebus);
-
- skl_init_pci(hda);
+ int ret;
- snd_hdac_bus_init_chip(bus, 1);
+ /*
+ * resume only when we are not in suspend active, otherwise need to
+ * restore the device
+ */
+ if (skl->supend_active) {
+ pci_restore_state(pci);
+ ret = pci_enable_device(pci);
+ snd_hdac_ext_bus_link_power_up_all(ebus);
+ disable_irq_wake(bus->irq);
+ } else {
+ ret = _skl_resume(ebus);
+ }
- return 0;
+ return ret;
}
#endif /* CONFIG_PM_SLEEP */
@@ -167,24 +266,10 @@ static int skl_runtime_suspend(struct device *dev)
struct pci_dev *pci = to_pci_dev(dev);
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
struct hdac_bus *bus = ebus_to_hbus(ebus);
- struct skl *skl = ebus_to_skl(ebus);
- int ret;
dev_dbg(bus->dev, "in %s\n", __func__);
- /* enable controller wake up event */
- snd_hdac_chip_updatew(bus, WAKEEN, 0, STATESTS_INT_MASK);
-
- snd_hdac_ext_bus_link_power_down_all(ebus);
-
- ret = skl_suspend_dsp(skl);
- if (ret < 0)
- return ret;
-
- snd_hdac_bus_stop_chip(bus);
- snd_hdac_bus_enter_link_reset(bus);
-
- return 0;
+ return _skl_suspend(ebus);
}
static int skl_runtime_resume(struct device *dev)
@@ -192,20 +277,10 @@ static int skl_runtime_resume(struct device *dev)
struct pci_dev *pci = to_pci_dev(dev);
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
struct hdac_bus *bus = ebus_to_hbus(ebus);
- struct skl *skl = ebus_to_skl(ebus);
- int status;
dev_dbg(bus->dev, "in %s\n", __func__);
- /* Read STATESTS before controller reset */
- status = snd_hdac_chip_readw(bus, STATESTS);
-
- skl_init_pci(skl);
- snd_hdac_bus_init_chip(bus, true);
- /* disable controller Wake Up event */
- snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, 0);
-
- return skl_resume_dsp(skl);
+ return _skl_resume(ebus);
}
#endif /* CONFIG_PM */
@@ -242,6 +317,43 @@ static int skl_free(struct hdac_ext_bus *ebus)
return 0;
}
+static int skl_machine_device_register(struct skl *skl, void *driver_data)
+{
+ struct hdac_bus *bus = ebus_to_hbus(&skl->ebus);
+ struct platform_device *pdev;
+ struct sst_acpi_mach *mach = driver_data;
+ int ret;
+
+ mach = sst_acpi_find_machine(mach);
+ if (mach == NULL) {
+ dev_err(bus->dev, "No matching machine driver found\n");
+ return -ENODEV;
+ }
+ skl->fw_name = mach->fw_filename;
+
+ pdev = platform_device_alloc(mach->drv_name, -1);
+ if (pdev == NULL) {
+ dev_err(bus->dev, "platform device alloc failed\n");
+ return -EIO;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ dev_err(bus->dev, "failed to add machine device\n");
+ platform_device_put(pdev);
+ return -EIO;
+ }
+ skl->i2s_dev = pdev;
+
+ return 0;
+}
+
+static void skl_machine_device_unregister(struct skl *skl)
+{
+ if (skl->i2s_dev)
+ platform_device_unregister(skl->i2s_dev);
+}
+
static int skl_dmic_device_register(struct skl *skl)
{
struct hdac_bus *bus = ebus_to_hbus(&skl->ebus);
@@ -321,7 +433,7 @@ static int skl_codec_create(struct hdac_ext_bus *ebus)
* back to the sanity state.
*/
snd_hdac_bus_stop_chip(bus);
- snd_hdac_bus_init_chip(bus, true);
+ skl_init_chip(bus, true);
}
}
}
@@ -431,12 +543,11 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
/* initialize chip */
skl_init_pci(skl);
- snd_hdac_bus_init_chip(bus, true);
+ skl_init_chip(bus, true);
/* codec detection */
if (!bus->codec_mask) {
- dev_err(bus->dev, "no codecs found!\n");
- return -ENODEV;
+ dev_info(bus->dev, "no hda codecs found!\n");
}
return 0;
@@ -471,11 +582,18 @@ static int skl_probe(struct pci_dev *pci,
/* check if dsp is there */
if (ebus->ppcap) {
+ err = skl_machine_device_register(skl,
+ (void *)pci_id->driver_data);
+ if (err < 0)
+ goto out_free;
+
err = skl_init_dsp(skl);
if (err < 0) {
dev_dbg(bus->dev, "error failed to register dsp\n");
- goto out_free;
+ goto out_mach_free;
}
+ skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
+
}
if (ebus->mlcap)
snd_hdac_ext_bus_get_ml_capabilities(ebus);
@@ -509,6 +627,8 @@ out_dmic_free:
skl_dmic_device_unregister(skl);
out_dsp_free:
skl_free_dsp(skl);
+out_mach_free:
+ skl_machine_device_unregister(skl);
out_free:
skl->init_failed = 1;
skl_free(ebus);
@@ -529,15 +649,26 @@ static void skl_remove(struct pci_dev *pci)
pci_dev_put(pci);
skl_platform_unregister(&pci->dev);
skl_free_dsp(skl);
+ skl_machine_device_unregister(skl);
skl_dmic_device_unregister(skl);
skl_free(ebus);
dev_set_drvdata(&pci->dev, NULL);
}
+static struct sst_acpi_mach sst_skl_devdata[] = {
+ { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL },
+ { "INT343B", "skl_nau88l25_ssm4567_i2s", "intel/dsp_fw_release.bin",
+ NULL, NULL, NULL },
+ { "MX98357A", "skl_nau88l25_max98357a_i2s", "intel/dsp_fw_release.bin",
+ NULL, NULL, NULL },
+ {}
+};
+
/* PCI IDs */
static const struct pci_device_id skl_ids[] = {
/* Sunrise Point-LP */
- { PCI_DEVICE(0x8086, 0x9d70), 0},
+ { PCI_DEVICE(0x8086, 0x9d70),
+ .driver_data = (unsigned long)&sst_skl_devdata},
{ 0, }
};
MODULE_DEVICE_TABLE(pci, skl_ids);
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h
index a0709e344d44..4d18293b5537 100644
--- a/sound/soc/intel/skylake/skl.h
+++ b/sound/soc/intel/skylake/skl.h
@@ -48,6 +48,9 @@
#define AZX_REG_VS_SDXEFIFOS_XBASE 0x1094
#define AZX_REG_VS_SDXEFIFOS_XINTERVAL 0x20
+#define AZX_PCIREG_CGCTL 0x48
+#define AZX_CGCTL_MISCBDCGE_MASK (1 << 6)
+
struct skl_dsp_resource {
u32 max_mcps;
u32 max_mem;
@@ -61,15 +64,18 @@ struct skl {
unsigned int init_failed:1; /* delayed init failed */
struct platform_device *dmic_dev;
+ struct platform_device *i2s_dev;
void *nhlt; /* nhlt ptr */
struct skl_sst *skl_sst; /* sst skl ctx */
struct skl_dsp_resource resource;
struct list_head ppl_list;
- struct list_head dapm_path_list;
+ const char *fw_name;
const struct firmware *tplg;
+
+ int supend_active;
};
#define skl_to_ebus(s) (&(s)->ebus)
diff --git a/sound/soc/mediatek/mtk-afe-common.h b/sound/soc/mediatek/mtk-afe-common.h
index cc4393cb1130..9b1af1a70874 100644
--- a/sound/soc/mediatek/mtk-afe-common.h
+++ b/sound/soc/mediatek/mtk-afe-common.h
@@ -92,7 +92,6 @@ struct mtk_afe_memif_data {
struct mtk_afe_memif {
unsigned int phys_buf_addr;
int buffer_size;
- unsigned int hw_ptr; /* Previous IRQ's HW ptr */
struct snd_pcm_substream *substream;
const struct mtk_afe_memif_data *data;
const struct mtk_afe_irq_data *irqdata;
diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c
index f5baf3c38863..08af9f5dc4ab 100644
--- a/sound/soc/mediatek/mtk-afe-pcm.c
+++ b/sound/soc/mediatek/mtk-afe-pcm.c
@@ -175,8 +175,17 @@ static snd_pcm_uframes_t mtk_afe_pcm_pointer
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
+ unsigned int hw_ptr;
+ int ret;
+
+ ret = regmap_read(afe->regmap, memif->data->reg_ofs_cur, &hw_ptr);
+ if (ret || hw_ptr == 0) {
+ dev_err(afe->dev, "%s hw_ptr err\n", __func__);
+ hw_ptr = memif->phys_buf_addr;
+ }
- return bytes_to_frames(substream->runtime, memif->hw_ptr);
+ return bytes_to_frames(substream->runtime,
+ hw_ptr - memif->phys_buf_addr);
}
static const struct snd_pcm_ops mtk_afe_pcm_ops = {
@@ -299,8 +308,6 @@ static int mtk_afe_dais_enable_clks(struct mtk_afe *afe,
dev_err(afe->dev, "Failed to enable m_ck\n");
return ret;
}
- regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
- AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0);
}
if (b_ck) {
@@ -340,12 +347,8 @@ static int mtk_afe_dais_set_clks(struct mtk_afe *afe,
static void mtk_afe_dais_disable_clks(struct mtk_afe *afe,
struct clk *m_ck, struct clk *b_ck)
{
- if (m_ck) {
- regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
- AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M,
- AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M);
+ if (m_ck)
clk_disable_unprepare(m_ck);
- }
if (b_ck)
clk_disable_unprepare(b_ck);
}
@@ -360,6 +363,8 @@ static int mtk_afe_i2s_startup(struct snd_pcm_substream *substream,
return 0;
mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
+ AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0);
return 0;
}
@@ -373,10 +378,10 @@ static void mtk_afe_i2s_shutdown(struct snd_pcm_substream *substream,
return;
mtk_afe_set_i2s_enable(afe, false);
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
+ AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M,
+ AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M);
mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
-
- /* disable AFE */
- regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0);
}
static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream,
@@ -425,9 +430,6 @@ static void mtk_afe_hdmi_shutdown(struct snd_pcm_substream *substream,
mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S3_M],
afe->clocks[MTK_CLK_I2S3_B]);
-
- /* disable AFE */
- regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0);
}
static int mtk_afe_hdmi_prepare(struct snd_pcm_substream *substream,
@@ -603,7 +605,6 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream,
memif->phys_buf_addr = substream->runtime->dma_addr;
memif->buffer_size = substream->runtime->dma_bytes;
- memif->hw_ptr = 0;
/* start */
regmap_write(afe->regmap,
@@ -672,17 +673,6 @@ static int mtk_afe_dais_hw_free(struct snd_pcm_substream *substream,
return snd_pcm_lib_free_pages(substream);
}
-static int mtk_afe_dais_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
-
- /* enable AFE */
- regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
- return 0;
-}
-
static int mtk_afe_dais_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
@@ -738,7 +728,6 @@ static int mtk_afe_dais_trigger(struct snd_pcm_substream *substream, int cmd,
/* and clear pending IRQ */
regmap_write(afe->regmap, AFE_IRQ_CLR,
1 << memif->data->irq_clr_shift);
- memif->hw_ptr = 0;
return 0;
default:
return -EINVAL;
@@ -751,7 +740,6 @@ static const struct snd_soc_dai_ops mtk_afe_dai_ops = {
.shutdown = mtk_afe_dais_shutdown,
.hw_params = mtk_afe_dais_hw_params,
.hw_free = mtk_afe_dais_hw_free,
- .prepare = mtk_afe_dais_prepare,
.trigger = mtk_afe_dais_trigger,
};
@@ -1082,7 +1070,7 @@ static const struct regmap_config mtk_afe_regmap_config = {
static irqreturn_t mtk_afe_irq_handler(int irq, void *dev_id)
{
struct mtk_afe *afe = dev_id;
- unsigned int reg_value, hw_ptr;
+ unsigned int reg_value;
int i, ret;
ret = regmap_read(afe->regmap, AFE_IRQ_STATUS, &reg_value);
@@ -1098,13 +1086,6 @@ static irqreturn_t mtk_afe_irq_handler(int irq, void *dev_id)
if (!(reg_value & (1 << memif->data->irq_clr_shift)))
continue;
- ret = regmap_read(afe->regmap, memif->data->reg_ofs_cur,
- &hw_ptr);
- if (ret || hw_ptr == 0) {
- dev_err(afe->dev, "%s hw_ptr err\n", __func__);
- hw_ptr = memif->phys_buf_addr;
- }
- memif->hw_ptr = hw_ptr - memif->phys_buf_addr;
snd_pcm_period_elapsed(memif->substream);
}
@@ -1119,6 +1100,9 @@ static int mtk_afe_runtime_suspend(struct device *dev)
{
struct mtk_afe *afe = dev_get_drvdata(dev);
+ /* disable AFE */
+ regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0);
+
/* disable AFE clk */
regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
AUD_TCON0_PDN_AFE, AUD_TCON0_PDN_AFE);
@@ -1165,6 +1149,9 @@ static int mtk_afe_runtime_resume(struct device *dev)
/* unmask all IRQs */
regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN, 0xff, 0xff);
+
+ /* enable AFE */
+ regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
return 0;
err_bck0:
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c
index 584b2372339e..f83cc2bc0fc4 100644
--- a/sound/soc/omap/omap-hdmi-audio.c
+++ b/sound/soc/omap/omap-hdmi-audio.c
@@ -368,6 +368,8 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev)
card->owner = THIS_MODULE;
card->dai_link =
devm_kzalloc(dev, sizeof(*(card->dai_link)), GFP_KERNEL);
+ if (!card->dai_link)
+ return -ENOMEM;
card->dai_link->name = card->name;
card->dai_link->stream_name = card->name;
card->dai_link->cpu_dai_name = dev_name(ad->dssdev);
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
index 6147e86e9b0f..416ea646c3b1 100644
--- a/sound/soc/pxa/brownstone.c
+++ b/sound/soc/pxa/brownstone.c
@@ -63,8 +63,7 @@ static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream,
sysclk = params_rate(params) * 512;
sspa_mclk = params_rate(params) * 64;
}
- sspa_div = freq_out;
- do_div(sspa_div, sspa_mclk);
+ sspa_div = freq_out / sspa_mclk;
snd_soc_dai_set_sysclk(cpu_dai, MMP_SSPA_CLK_AUDIO, freq_out, 0);
snd_soc_dai_set_pll(cpu_dai, MMP_SYSCLK, 0, freq_out, sysclk);
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 29bc60e85e92..5c8f9db50a47 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -81,8 +81,12 @@ static int rear_amp_power(struct snd_soc_codec *codec, int power)
static int rear_amp_event(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kctl, int event)
{
- struct snd_soc_codec *codec = widget->dapm->card->rtd[0].codec;
+ struct snd_soc_card *card = widget->dapm->card;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_codec *codec;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec = rtd->codec;
return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event));
}
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
index e5101e0d2d37..00b6c9d039cf 100644
--- a/sound/soc/qcom/lpass-cpu.c
+++ b/sound/soc/qcom/lpass-cpu.c
@@ -355,6 +355,7 @@ static struct regmap_config lpass_cpu_regmap_config = {
.readable_reg = lpass_cpu_regmap_readable,
.volatile_reg = lpass_cpu_regmap_volatile,
.cache_type = REGCACHE_FLAT,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
};
int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 58ee64594f07..6561c4cc2edd 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -34,13 +34,7 @@ struct rk_i2s_dev {
struct regmap *regmap;
-/*
- * Used to indicate the tx/rx status.
- * I2S controller hopes to start the tx and rx together,
- * also to stop them when they are both try to stop.
-*/
- bool tx_start;
- bool rx_start;
+ bool is_master_mode;
};
static int i2s_runtime_suspend(struct device *dev)
@@ -81,37 +75,29 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
regmap_update_bits(i2s->regmap, I2S_XFER,
- I2S_XFER_TXS_START | I2S_XFER_RXS_START,
- I2S_XFER_TXS_START | I2S_XFER_RXS_START);
-
- i2s->tx_start = true;
+ I2S_XFER_TXS_START,
+ I2S_XFER_TXS_START);
} else {
- i2s->tx_start = false;
-
regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
- if (!i2s->rx_start) {
- regmap_update_bits(i2s->regmap, I2S_XFER,
- I2S_XFER_TXS_START |
- I2S_XFER_RXS_START,
- I2S_XFER_TXS_STOP |
- I2S_XFER_RXS_STOP);
+ regmap_update_bits(i2s->regmap, I2S_XFER,
+ I2S_XFER_TXS_START,
+ I2S_XFER_TXS_STOP);
- regmap_update_bits(i2s->regmap, I2S_CLR,
- I2S_CLR_TXC | I2S_CLR_RXC,
- I2S_CLR_TXC | I2S_CLR_RXC);
+ regmap_update_bits(i2s->regmap, I2S_CLR,
+ I2S_CLR_TXC,
+ I2S_CLR_TXC);
- regmap_read(i2s->regmap, I2S_CLR, &val);
+ regmap_read(i2s->regmap, I2S_CLR, &val);
- /* Should wait for clear operation to finish */
- while (val) {
- regmap_read(i2s->regmap, I2S_CLR, &val);
- retry--;
- if (!retry) {
- dev_warn(i2s->dev, "fail to clear\n");
- break;
- }
+ /* Should wait for clear operation to finish */
+ while (val & I2S_CLR_TXC) {
+ regmap_read(i2s->regmap, I2S_CLR, &val);
+ retry--;
+ if (!retry) {
+ dev_warn(i2s->dev, "fail to clear\n");
+ break;
}
}
}
@@ -127,37 +113,29 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
regmap_update_bits(i2s->regmap, I2S_XFER,
- I2S_XFER_TXS_START | I2S_XFER_RXS_START,
- I2S_XFER_TXS_START | I2S_XFER_RXS_START);
-
- i2s->rx_start = true;
+ I2S_XFER_RXS_START,
+ I2S_XFER_RXS_START);
} else {
- i2s->rx_start = false;
-
regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
- if (!i2s->tx_start) {
- regmap_update_bits(i2s->regmap, I2S_XFER,
- I2S_XFER_TXS_START |
- I2S_XFER_RXS_START,
- I2S_XFER_TXS_STOP |
- I2S_XFER_RXS_STOP);
+ regmap_update_bits(i2s->regmap, I2S_XFER,
+ I2S_XFER_RXS_START,
+ I2S_XFER_RXS_STOP);
- regmap_update_bits(i2s->regmap, I2S_CLR,
- I2S_CLR_TXC | I2S_CLR_RXC,
- I2S_CLR_TXC | I2S_CLR_RXC);
+ regmap_update_bits(i2s->regmap, I2S_CLR,
+ I2S_CLR_RXC,
+ I2S_CLR_RXC);
- regmap_read(i2s->regmap, I2S_CLR, &val);
+ regmap_read(i2s->regmap, I2S_CLR, &val);
- /* Should wait for clear operation to finish */
- while (val) {
- regmap_read(i2s->regmap, I2S_CLR, &val);
- retry--;
- if (!retry) {
- dev_warn(i2s->dev, "fail to clear\n");
- break;
- }
+ /* Should wait for clear operation to finish */
+ while (val & I2S_CLR_RXC) {
+ regmap_read(i2s->regmap, I2S_CLR, &val);
+ retry--;
+ if (!retry) {
+ dev_warn(i2s->dev, "fail to clear\n");
+ break;
}
}
}
@@ -174,9 +152,11 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
case SND_SOC_DAIFMT_CBS_CFS:
/* Set source clock in Master mode */
val = I2S_CKR_MSS_MASTER;
+ i2s->is_master_mode = true;
break;
case SND_SOC_DAIFMT_CBM_CFM:
val = I2S_CKR_MSS_SLAVE;
+ i2s->is_master_mode = false;
break;
default:
return -EINVAL;
@@ -228,6 +208,26 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
struct rk_i2s_dev *i2s = to_info(dai);
struct snd_soc_pcm_runtime *rtd = substream->private_data;
unsigned int val = 0;
+ unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck;
+
+ if (i2s->is_master_mode) {
+ mclk_rate = clk_get_rate(i2s->mclk);
+ bclk_rate = 2 * 32 * params_rate(params);
+ if (bclk_rate && mclk_rate % bclk_rate)
+ return -EINVAL;
+
+ div_bclk = mclk_rate / bclk_rate;
+ div_lrck = bclk_rate / params_rate(params);
+ regmap_update_bits(i2s->regmap, I2S_CKR,
+ I2S_CKR_MDIV_MASK,
+ I2S_CKR_MDIV(div_bclk));
+
+ regmap_update_bits(i2s->regmap, I2S_CKR,
+ I2S_CKR_TSD_MASK |
+ I2S_CKR_RSD_MASK,
+ I2S_CKR_TSD(div_lrck) |
+ I2S_CKR_RSD(div_lrck));
+ }
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
@@ -242,6 +242,9 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S24_LE:
val |= I2S_TXCR_VDW(24);
break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ val |= I2S_TXCR_VDW(32);
+ break;
default:
return -EINVAL;
}
@@ -360,7 +363,8 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
.formats = (SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE |
- SNDRV_PCM_FMTBIT_S24_LE),
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE),
},
.capture = {
.stream_name = "Capture",
@@ -370,7 +374,8 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
.formats = (SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE |
- SNDRV_PCM_FMTBIT_S24_LE),
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE),
},
.ops = &rockchip_i2s_dai_ops,
.symmetric_rates = 1,
@@ -451,6 +456,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct rk_i2s_dev *i2s;
+ struct snd_soc_dai_driver *soc_dai;
struct resource *res;
void __iomem *regs;
int ret;
@@ -511,17 +517,26 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
goto err_pm_disable;
}
- /* refine capture channels */
+ soc_dai = devm_kzalloc(&pdev->dev,
+ sizeof(*soc_dai), GFP_KERNEL);
+ if (!soc_dai)
+ return -ENOMEM;
+
+ memcpy(soc_dai, &rockchip_i2s_dai, sizeof(*soc_dai));
+ if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {
+ if (val >= 2 && val <= 8)
+ soc_dai->playback.channels_max = val;
+ }
+
if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
if (val >= 2 && val <= 8)
- rockchip_i2s_dai.capture.channels_max = val;
- else
- rockchip_i2s_dai.capture.channels_max = 2;
+ soc_dai->capture.channels_max = val;
}
ret = devm_snd_soc_register_component(&pdev->dev,
&rockchip_i2s_component,
- &rockchip_i2s_dai, 1);
+ soc_dai, 1);
+
if (ret) {
dev_err(&pdev->dev, "Could not register DAI\n");
goto err_suspend;
diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c
index 26567b10393a..543610282cdb 100644
--- a/sound/soc/rockchip/rockchip_max98090.c
+++ b/sound/soc/rockchip/rockchip_max98090.c
@@ -80,11 +80,17 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
switch (params_rate(params)) {
case 8000:
case 16000:
+ case 24000:
+ case 32000:
case 48000:
+ case 64000:
case 96000:
mclk = 12288000;
break;
+ case 11025:
+ case 22050:
case 44100:
+ case 88200:
mclk = 11289600;
break;
default:
diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c
index 68c62e4c2316..440a8026346a 100644
--- a/sound/soc/rockchip/rockchip_rt5645.c
+++ b/sound/soc/rockchip/rockchip_rt5645.c
@@ -79,11 +79,17 @@ static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
switch (params_rate(params)) {
case 8000:
case 16000:
+ case 24000:
+ case 32000:
case 48000:
+ case 64000:
case 96000:
mclk = 12288000;
break;
+ case 11025:
+ case 22050:
case 44100:
+ case 88200:
mclk = 11289600;
break;
default:
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 3744c9ed5370..78baa26e938b 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -1,8 +1,6 @@
config SND_SOC_SAMSUNG
tristate "ASoC support for Samsung"
depends on (PLAT_SAMSUNG || ARCH_EXYNOS)
- depends on S3C64XX_PL080 || !ARCH_S3C64XX
- depends on S3C24XX_DMAC || !ARCH_S3C24XX
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M if you want to add support for codecs attached to
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index e4145509d63c..4a7a503fe13c 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -324,7 +324,7 @@ static const struct snd_soc_component_driver s3c_ac97_component = {
static int s3c_ac97_probe(struct platform_device *pdev)
{
- struct resource *mem_res, *dmatx_res, *dmarx_res, *dmamic_res, *irq_res;
+ struct resource *mem_res, *irq_res;
struct s3c_audio_pdata *ac97_pdata;
int ret;
@@ -335,24 +335,6 @@ static int s3c_ac97_probe(struct platform_device *pdev)
}
/* Check for availability of necessary resource */
- dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!dmatx_res) {
- dev_err(&pdev->dev, "Unable to get AC97-TX dma resource\n");
- return -ENXIO;
- }
-
- dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (!dmarx_res) {
- dev_err(&pdev->dev, "Unable to get AC97-RX dma resource\n");
- return -ENXIO;
- }
-
- dmamic_res = platform_get_resource(pdev, IORESOURCE_DMA, 2);
- if (!dmamic_res) {
- dev_err(&pdev->dev, "Unable to get AC97-MIC dma resource\n");
- return -ENXIO;
- }
-
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq_res) {
dev_err(&pdev->dev, "AC97 IRQ not provided!\n");
@@ -364,11 +346,11 @@ static int s3c_ac97_probe(struct platform_device *pdev)
if (IS_ERR(s3c_ac97.regs))
return PTR_ERR(s3c_ac97.regs);
- s3c_ac97_pcm_out.channel = dmatx_res->start;
+ s3c_ac97_pcm_out.slave = ac97_pdata->dma_playback;
s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA;
- s3c_ac97_pcm_in.channel = dmarx_res->start;
+ s3c_ac97_pcm_in.slave = ac97_pdata->dma_capture;
s3c_ac97_pcm_in.dma_addr = mem_res->start + S3C_AC97_PCM_DATA;
- s3c_ac97_mic_in.channel = dmamic_res->start;
+ s3c_ac97_mic_in.slave = ac97_pdata->dma_capture_mic;
s3c_ac97_mic_in.dma_addr = mem_res->start + S3C_AC97_MIC_DATA;
init_completion(&s3c_ac97.done);
@@ -406,7 +388,8 @@ static int s3c_ac97_probe(struct platform_device *pdev)
if (ret)
goto err5;
- ret = samsung_asoc_dma_platform_register(&pdev->dev);
+ ret = samsung_asoc_dma_platform_register(&pdev->dev,
+ ac97_pdata->dma_filter);
if (ret) {
dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
goto err5;
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index e5f05e62fa3c..3dd246fa0059 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -58,11 +58,16 @@ static int bells_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
- struct snd_soc_codec *codec = codec_dai->codec;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_codec *codec;
struct bells_drvdata *bells = card->drvdata;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_DSP_CODEC].name);
+ codec_dai = rtd->codec_dai;
+ codec = codec_dai->codec;
+
if (dapm->dev != codec_dai->dev)
return 0;
@@ -99,11 +104,16 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
- struct snd_soc_codec *codec = codec_dai->codec;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_codec *codec;
struct bells_drvdata *bells = card->drvdata;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_DSP_CODEC].name);
+ codec_dai = rtd->codec_dai;
+ codec = codec_dai->codec;
+
if (dapm->dev != codec_dai->dev)
return 0;
@@ -137,14 +147,22 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
static int bells_late_probe(struct snd_soc_card *card)
{
struct bells_drvdata *bells = card->drvdata;
- struct snd_soc_codec *wm0010 = card->rtd[DAI_AP_DSP].codec;
- struct snd_soc_codec *codec = card->rtd[DAI_DSP_CODEC].codec;
- struct snd_soc_dai *aif1_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_codec *wm0010;
+ struct snd_soc_codec *codec;
+ struct snd_soc_dai *aif1_dai;
struct snd_soc_dai *aif2_dai;
struct snd_soc_dai *aif3_dai;
struct snd_soc_dai *wm9081_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_AP_DSP].name);
+ wm0010 = rtd->codec;
+
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_DSP_CODEC].name);
+ codec = rtd->codec;
+ aif1_dai = rtd->codec_dai;
+
ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
ARIZONA_CLK_SRC_FLL1,
bells->sysclk_rate,
@@ -181,7 +199,8 @@ static int bells_late_probe(struct snd_soc_card *card)
return ret;
}
- aif2_dai = card->rtd[DAI_CODEC_CP].cpu_dai;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_CODEC_CP].name);
+ aif2_dai = rtd->cpu_dai;
ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
if (ret != 0) {
@@ -192,8 +211,9 @@ static int bells_late_probe(struct snd_soc_card *card)
if (card->num_rtd == DAI_CODEC_SUB)
return 0;
- aif3_dai = card->rtd[DAI_CODEC_SUB].cpu_dai;
- wm9081_dai = card->rtd[DAI_CODEC_SUB].codec_dai;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[DAI_CODEC_SUB].name);
+ aif3_dai = rtd->cpu_dai;
+ wm9081_dai = rtd->codec_dai;
ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
if (ret != 0) {
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index 0e85dcfec023..a7616cc9b39e 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -13,9 +13,10 @@
#define _S3C_AUDIO_H
#include <sound/dmaengine_pcm.h>
+#include <linux/dmaengine.h>
struct s3c_dma_params {
- int channel; /* Channel ID */
+ void *slave; /* Channel ID */
dma_addr_t dma_addr;
int dma_size; /* Size of the DMA transfer */
char *ch_name;
@@ -25,6 +26,7 @@ struct s3c_dma_params {
void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
struct s3c_dma_params *playback,
struct s3c_dma_params *capture);
-int samsung_asoc_dma_platform_register(struct device *dev);
+int samsung_asoc_dma_platform_register(struct device *dev,
+ dma_filter_fn fn);
#endif
diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c
index 506f5bf6d082..063125937311 100644
--- a/sound/soc/samsung/dmaengine.c
+++ b/sound/soc/samsung/dmaengine.c
@@ -28,17 +28,8 @@
#include "dma.h"
-#ifdef CONFIG_ARCH_S3C64XX
-#define filter_fn pl08x_filter_id
-#elif defined(CONFIG_ARCH_S3C24XX)
-#define filter_fn s3c24xx_dma_filter
-#else
-#define filter_fn NULL
-#endif
-
-static const struct snd_dmaengine_pcm_config samsung_dmaengine_pcm_config = {
+static struct snd_dmaengine_pcm_config samsung_dmaengine_pcm_config = {
.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
- .compat_filter_fn = filter_fn,
};
void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
@@ -50,14 +41,14 @@ void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
if (playback) {
playback_data = &playback->dma_data;
- playback_data->filter_data = (void *)playback->channel;
+ playback_data->filter_data = playback->slave;
playback_data->chan_name = playback->ch_name;
playback_data->addr = playback->dma_addr;
playback_data->addr_width = playback->dma_size;
}
if (capture) {
capture_data = &capture->dma_data;
- capture_data->filter_data = (void *)capture->channel;
+ capture_data->filter_data = capture->slave;
capture_data->chan_name = capture->ch_name;
capture_data->addr = capture->dma_addr;
capture_data->addr_width = capture->dma_size;
@@ -67,8 +58,11 @@ void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
}
EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data);
-int samsung_asoc_dma_platform_register(struct device *dev)
+int samsung_asoc_dma_platform_register(struct device *dev,
+ dma_filter_fn filter)
{
+ samsung_dmaengine_pcm_config.compat_filter_fn = filter;
+
return devm_snd_dmaengine_pcm_register(dev,
&samsung_dmaengine_pcm_config,
SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index ea4ab374a223..84d9e77c0fbe 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -89,6 +89,7 @@ struct i2s_dai {
struct s3c_dma_params dma_playback;
struct s3c_dma_params dma_capture;
struct s3c_dma_params idma_playback;
+ dma_filter_fn filter;
u32 quirks;
u32 suspend_i2smod;
u32 suspend_i2scon;
@@ -1244,7 +1245,8 @@ static int samsung_i2s_probe(struct platform_device *pdev)
if (ret != 0)
return ret;
- return samsung_asoc_dma_platform_register(&pdev->dev);
+ return samsung_asoc_dma_platform_register(&pdev->dev,
+ sec_dai->filter);
}
pri_dai = i2s_alloc_dai(pdev, false);
@@ -1257,27 +1259,15 @@ static int samsung_i2s_probe(struct platform_device *pdev)
pri_dai->lock = &pri_dai->spinlock;
if (!np) {
- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!res) {
- dev_err(&pdev->dev,
- "Unable to get I2S-TX dma resource\n");
- return -ENXIO;
- }
- pri_dai->dma_playback.channel = res->start;
-
- res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (!res) {
- dev_err(&pdev->dev,
- "Unable to get I2S-RX dma resource\n");
- return -ENXIO;
- }
- pri_dai->dma_capture.channel = res->start;
-
if (i2s_pdata == NULL) {
dev_err(&pdev->dev, "Can't work without s3c_audio_pdata\n");
return -EINVAL;
}
+ pri_dai->dma_playback.slave = i2s_pdata->dma_playback;
+ pri_dai->dma_capture.slave = i2s_pdata->dma_capture;
+ pri_dai->filter = i2s_pdata->dma_filter;
+
if (&i2s_pdata->type)
i2s_cfg = &i2s_pdata->type.i2s;
@@ -1339,9 +1329,8 @@ static int samsung_i2s_probe(struct platform_device *pdev)
sec_dai->dma_playback.ch_name = "tx-sec";
if (!np) {
- res = platform_get_resource(pdev, IORESOURCE_DMA, 2);
- if (res)
- sec_dai->dma_playback.channel = res->start;
+ sec_dai->dma_playback.slave = i2s_pdata->dma_play_sec;
+ sec_dai->filter = i2s_pdata->dma_filter;
}
sec_dai->dma_playback.dma_size = 4;
@@ -1364,7 +1353,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
- ret = samsung_asoc_dma_platform_register(&pdev->dev);
+ ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter);
if (ret != 0)
return ret;
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index 31a820eb0ac3..7cb204e649ca 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -23,9 +23,13 @@ static int littlemill_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *aif1_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ aif1_dai = rtd->codec_dai;
+
if (dapm->dev != aif1_dai->dev)
return 0;
@@ -66,9 +70,13 @@ static int littlemill_set_bias_level_post(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *aif1_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ aif1_dai = rtd->codec_dai;
+
if (dapm->dev != aif1_dai->dev)
return 0;
@@ -168,9 +176,13 @@ static int bbclk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_card *card = w->dapm->card;
- struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *aif2_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name);
+ aif2_dai = rtd->cpu_dai;
+
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
ret = snd_soc_dai_set_pll(aif2_dai, WM8994_FLL2,
@@ -245,11 +257,19 @@ static struct snd_soc_jack littlemill_headset;
static int littlemill_late_probe(struct snd_soc_card *card)
{
- struct snd_soc_codec *codec = card->rtd[0].codec;
- struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
- struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_codec *codec;
+ struct snd_soc_dai *aif1_dai;
+ struct snd_soc_dai *aif2_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec = rtd->codec;
+ aif1_dai = rtd->codec_dai;
+
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name);
+ aif2_dai = rtd->cpu_dai;
+
ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
32768, SND_SOC_CLOCK_IN);
if (ret < 0)
diff --git a/sound/soc/samsung/odroidx2_max98090.c b/sound/soc/samsung/odroidx2_max98090.c
index 596f1180a369..04217279fe25 100644
--- a/sound/soc/samsung/odroidx2_max98090.c
+++ b/sound/soc/samsung/odroidx2_max98090.c
@@ -25,10 +25,15 @@ static struct snd_soc_dai_link odroidx2_dai[];
static int odroidx2_late_probe(struct snd_soc_card *card)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
- struct snd_soc_dai *cpu_dai = card->rtd[0].cpu_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_dai *cpu_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec_dai = rtd->codec_dai;
+ cpu_dai = rtd->cpu_dai;
+
ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK,
SND_SOC_CLOCK_IN);
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index b320a9d3fbf8..498f563a4c9c 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -486,8 +486,9 @@ static const struct snd_soc_component_driver s3c_pcm_component = {
static int s3c_pcm_dev_probe(struct platform_device *pdev)
{
struct s3c_pcm_info *pcm;
- struct resource *mem_res, *dmatx_res, *dmarx_res;
+ struct resource *mem_res;
struct s3c_audio_pdata *pcm_pdata;
+ dma_filter_fn filter;
int ret;
/* Check for valid device index */
@@ -499,18 +500,6 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
pcm_pdata = pdev->dev.platform_data;
/* Check for availability of necessary resource */
- dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!dmatx_res) {
- dev_err(&pdev->dev, "Unable to get PCM-TX dma resource\n");
- return -ENXIO;
- }
-
- dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (!dmarx_res) {
- dev_err(&pdev->dev, "Unable to get PCM-RX dma resource\n");
- return -ENXIO;
- }
-
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem_res) {
dev_err(&pdev->dev, "Unable to get register resource\n");
@@ -568,8 +557,12 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
s3c_pcm_stereo_out[pdev->id].dma_addr = mem_res->start
+ S3C_PCM_TXFIFO;
- s3c_pcm_stereo_in[pdev->id].channel = dmarx_res->start;
- s3c_pcm_stereo_out[pdev->id].channel = dmatx_res->start;
+ filter = NULL;
+ if (pcm_pdata) {
+ s3c_pcm_stereo_in[pdev->id].slave = pcm_pdata->dma_capture;
+ s3c_pcm_stereo_out[pdev->id].slave = pcm_pdata->dma_playback;
+ filter = pcm_pdata->dma_filter;
+ }
pcm->dma_capture = &s3c_pcm_stereo_in[pdev->id];
pcm->dma_playback = &s3c_pcm_stereo_out[pdev->id];
@@ -583,7 +576,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
goto err5;
}
- ret = samsung_asoc_dma_platform_register(&pdev->dev);
+ ret = samsung_asoc_dma_platform_register(&pdev->dev, filter);
if (ret) {
dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
goto err5;
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 2b766d212ce0..204029d12f5b 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -25,7 +25,6 @@
#include <sound/soc.h>
#include <sound/pcm_params.h>
-#include <mach/dma.h>
#include <mach/gpio-samsung.h>
#include <plat/gpio-cfg.h>
@@ -33,14 +32,14 @@
#include "regs-i2s-v2.h"
#include "s3c2412-i2s.h"
+#include <linux/platform_data/asoc-s3c.h>
+
static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
- .channel = DMACH_I2S_OUT,
.ch_name = "tx",
.dma_size = 4,
};
static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
- .channel = DMACH_I2S_IN,
.ch_name = "rx",
.dma_size = 4,
};
@@ -152,6 +151,12 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev)
{
int ret = 0;
struct resource *res;
+ struct s3c_audio_pdata *pdata = dev_get_platdata(&pdev->dev);
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "missing platform data");
+ return -ENXIO;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
s3c2412_i2s.regs = devm_ioremap_resource(&pdev->dev, res);
@@ -159,7 +164,9 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev)
return PTR_ERR(s3c2412_i2s.regs);
s3c2412_i2s_pcm_stereo_out.dma_addr = res->start + S3C2412_IISTXD;
+ s3c2412_i2s_pcm_stereo_out.slave = pdata->dma_playback;
s3c2412_i2s_pcm_stereo_in.dma_addr = res->start + S3C2412_IISRXD;
+ s3c2412_i2s_pcm_stereo_in.slave = pdata->dma_capture;
ret = s3c_i2sv2_register_component(&pdev->dev, -1,
&s3c2412_i2s_component,
@@ -169,7 +176,8 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev)
return ret;
}
- ret = samsung_asoc_dma_platform_register(&pdev->dev);
+ ret = samsung_asoc_dma_platform_register(&pdev->dev,
+ pdata->dma_filter);
if (ret)
pr_err("failed to register the DMA: %d\n", ret);
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 5bf723689692..b3a475d73ba7 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -23,7 +23,6 @@
#include <sound/soc.h>
#include <sound/pcm_params.h>
-#include <mach/dma.h>
#include <mach/gpio-samsung.h>
#include <plat/gpio-cfg.h>
#include "regs-iis.h"
@@ -31,14 +30,14 @@
#include "dma.h"
#include "s3c24xx-i2s.h"
+#include <linux/platform_data/asoc-s3c.h>
+
static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = {
- .channel = DMACH_I2S_OUT,
.ch_name = "tx",
.dma_size = 2,
};
static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = {
- .channel = DMACH_I2S_IN,
.ch_name = "rx",
.dma_size = 2,
};
@@ -454,6 +453,12 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
{
int ret = 0;
struct resource *res;
+ struct s3c_audio_pdata *pdata = dev_get_platdata(&pdev->dev);
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "missing platform data");
+ return -ENXIO;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -465,7 +470,9 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
return PTR_ERR(s3c24xx_i2s.regs);
s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO;
+ s3c24xx_i2s_pcm_stereo_out.slave = pdata->dma_playback;
s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO;
+ s3c24xx_i2s_pcm_stereo_in.slave = pdata->dma_capture;
ret = devm_snd_soc_register_component(&pdev->dev,
&s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1);
@@ -474,7 +481,8 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
return ret;
}
- ret = samsung_asoc_dma_platform_register(&pdev->dev);
+ ret = samsung_asoc_dma_platform_register(&pdev->dev,
+ pdata->dma_filter);
if (ret)
pr_err("failed to register the dma: %d\n", ret);
diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c
index 07ce2cfa4845..d8ac907bbb0d 100644
--- a/sound/soc/samsung/snow.c
+++ b/sound/soc/samsung/snow.c
@@ -35,10 +35,15 @@ static struct snd_soc_dai_link snow_dai[] = {
static int snow_late_probe(struct snd_soc_card *card)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
- struct snd_soc_dai *cpu_dai = card->rtd[0].cpu_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_dai *cpu_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec_dai = rtd->codec_dai;
+ cpu_dai = rtd->cpu_dai;
+
/* Set the MCLK rate for the codec */
ret = snd_soc_dai_set_sysclk(codec_dai, 0,
FIN_PLL_RATE, SND_SOC_CLOCK_IN);
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 36dbc0e96004..4687f521197c 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -359,20 +359,15 @@ static const struct snd_soc_component_driver samsung_spdif_component = {
static int spdif_probe(struct platform_device *pdev)
{
struct s3c_audio_pdata *spdif_pdata;
- struct resource *mem_res, *dma_res;
+ struct resource *mem_res;
struct samsung_spdif_info *spdif;
+ dma_filter_fn filter;
int ret;
spdif_pdata = pdev->dev.platform_data;
dev_dbg(&pdev->dev, "Entered %s\n", __func__);
- dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!dma_res) {
- dev_err(&pdev->dev, "Unable to get dma resource.\n");
- return -ENXIO;
- }
-
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem_res) {
dev_err(&pdev->dev, "Unable to get register resource.\n");
@@ -432,11 +427,15 @@ static int spdif_probe(struct platform_device *pdev)
spdif_stereo_out.dma_size = 2;
spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
- spdif_stereo_out.channel = dma_res->start;
+ filter = NULL;
+ if (spdif_pdata) {
+ spdif_stereo_out.slave = spdif_pdata->dma_playback;
+ filter = spdif_pdata->dma_filter;
+ }
spdif->dma_playback = &spdif_stereo_out;
- ret = samsung_asoc_dma_platform_register(&pdev->dev);
+ ret = samsung_asoc_dma_platform_register(&pdev->dev, filter);
if (ret) {
dev_err(&pdev->dev, "failed to register DMA: %d\n", ret);
goto err4;
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
index d1ae21c5e253..083ef5e21b17 100644
--- a/sound/soc/samsung/speyside.c
+++ b/sound/soc/samsung/speyside.c
@@ -25,9 +25,13 @@ static int speyside_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name);
+ codec_dai = rtd->codec_dai;
+
if (dapm->dev != codec_dai->dev)
return 0;
@@ -57,9 +61,13 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[1].name);
+ codec_dai = rtd->codec_dai;
+
if (dapm->dev != codec_dai->dev)
return 0;
diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
index 85ccfb7188cb..3310eda7cf53 100644
--- a/sound/soc/samsung/tobermory.c
+++ b/sound/soc/samsung/tobermory.c
@@ -23,9 +23,13 @@ static int tobermory_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec_dai = rtd->codec_dai;
+
if (dapm->dev != codec_dai->dev)
return 0;
@@ -62,9 +66,13 @@ static int tobermory_set_bias_level_post(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *codec_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec_dai = rtd->codec_dai;
+
if (dapm->dev != codec_dai->dev)
return 0;
@@ -170,10 +178,15 @@ static struct snd_soc_jack_pin tobermory_headset_pins[] = {
static int tobermory_late_probe(struct snd_soc_card *card)
{
- struct snd_soc_codec *codec = card->rtd[0].codec;
- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_codec *codec;
+ struct snd_soc_dai *codec_dai;
int ret;
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ codec = rtd->codec;
+ codec_dai = rtd->codec_dai;
+
ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
32768, SND_SOC_CLOCK_IN);
if (ret < 0)
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 206d1edab07c..c9902a6d6fa0 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -36,7 +36,6 @@ config SND_SOC_SH4_SIU
config SND_SOC_RCAR
tristate "R-Car series SRU/SCU/SSIU/SSI support"
- depends on DMA_OF
depends on COMMON_CLK
select SND_SIMPLE_CARD
select REGMAP_MMIO
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 0215c78cbddf..ead520182e26 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -1362,15 +1362,18 @@ static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev)
{
- dma_cap_mask_t mask;
int is_play = fsi_stream_is_play(fsi, io);
+#ifdef CONFIG_SUPERH
+ dma_cap_mask_t mask;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- io->chan = dma_request_slave_channel_compat(mask,
- shdma_chan_filter, (void *)io->dma_id,
- dev, is_play ? "tx" : "rx");
+ io->chan = dma_request_channel(mask, shdma_chan_filter,
+ (void *)io->dma_id);
+#else
+ io->chan = dma_request_slave_channel(dev, is_play ? "tx" : "rx");
+#endif
if (io->chan) {
struct dma_slave_config cfg = {};
int ret;
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile
index 8b258501aa35..a89ddf758695 100644
--- a/sound/soc/sh/rcar/Makefile
+++ b/sound/soc/sh/rcar/Makefile
@@ -1,4 +1,4 @@
-snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o ctu.o mix.o dvc.o
+snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o ssiu.o src.o ctu.o mix.o dvc.o cmd.o
obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
snd-soc-rsrc-card-objs := rsrc-card.o
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 2a5b3a293cd2..6d3ef366d536 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -68,8 +68,8 @@ static u32 rsnd_adg_calculate_rbgx(unsigned long div)
static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
{
- struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
- int id = rsnd_mod_id(mod);
+ struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
+ int id = rsnd_mod_id(ssi_mod);
int ws = id;
if (rsnd_ssi_is_pin_sharing(io)) {
@@ -90,13 +90,13 @@ static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
return (0x6 + ws) << 8;
}
-int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
+int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
struct rsnd_dai_stream *io)
{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+ struct rsnd_priv *priv = rsnd_mod_to_priv(cmd_mod);
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- int id = rsnd_mod_id(mod);
+ int id = rsnd_mod_id(cmd_mod);
int shift = (id % 2) ? 16 : 0;
u32 mask, val;
@@ -242,68 +242,6 @@ int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *src_mod,
return rsnd_adg_set_src_timsel_gen2(src_mod, io, val);
}
-int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- unsigned int src_rate,
- unsigned int dst_rate)
-{
- struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- struct device *dev = rsnd_priv_to_dev(priv);
- int idx, sel, div, shift;
- u32 mask, val;
- int id = rsnd_mod_id(mod);
- unsigned int sel_rate [] = {
- clk_get_rate(adg->clk[CLKA]), /* 000: CLKA */
- clk_get_rate(adg->clk[CLKB]), /* 001: CLKB */
- clk_get_rate(adg->clk[CLKC]), /* 010: CLKC */
- 0, /* 011: MLBCLK (not used) */
- adg->rbga_rate_for_441khz, /* 100: RBGA */
- adg->rbgb_rate_for_48khz, /* 101: RBGB */
- };
-
- /* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */
- for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) {
- for (div = 128, idx = 0;
- div <= 2048;
- div *= 2, idx++) {
- if (src_rate == sel_rate[sel] / div) {
- val = (idx << 4) | sel;
- goto find_rate;
- }
- }
- }
- dev_err(dev, "can't find convert src clk\n");
- return -EINVAL;
-
-find_rate:
- shift = (id % 4) * 8;
- mask = 0xFF << shift;
- val = val << shift;
-
- dev_dbg(dev, "adg convert src clk = %02x\n", val);
-
- switch (id / 4) {
- case 0:
- rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL3, mask, val);
- break;
- case 1:
- rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL4, mask, val);
- break;
- case 2:
- rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL5, mask, val);
- break;
- }
-
- /*
- * Gen1 doesn't need dst_rate settings,
- * since it uses SSI WS pin.
- * see also rsnd_src_set_route_if_gen1()
- */
-
- return 0;
-}
-
static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
@@ -337,20 +275,16 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)
}
}
-int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod)
+int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod)
{
- /*
- * "mod" = "ssi" here.
- * we can get "ssi id" from mod
- */
- rsnd_adg_set_ssi_clk(mod, 0);
+ rsnd_adg_set_ssi_clk(ssi_mod, 0);
return 0;
}
-int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
+int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+ struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct device *dev = rsnd_priv_to_dev(priv);
struct clk *clk;
@@ -394,14 +328,10 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
found_clock:
- /*
- * This "mod" = "ssi" here.
- * we can get "ssi id" from mod
- */
- rsnd_adg_set_ssi_clk(mod, data);
+ rsnd_adg_set_ssi_clk(ssi_mod, data);
dev_dbg(dev, "ADG: %s[%d] selects 0x%x for %d\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod),
+ rsnd_mod_name(ssi_mod), rsnd_mod_id(ssi_mod),
data, rate);
return 0;
@@ -418,15 +348,20 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv,
[CLKC] = "clk_c",
[CLKI] = "clk_i",
};
- int i;
+ int i, ret;
for (i = 0; i < CLKMAX; i++) {
clk = devm_clk_get(dev, clk_name[i]);
adg->clk[i] = IS_ERR(clk) ? NULL : clk;
}
- for_each_rsnd_clk(clk, adg, i)
+ for_each_rsnd_clk(clk, adg, i) {
+ ret = clk_prepare_enable(clk);
+ if (ret < 0)
+ dev_warn(dev, "can't use clk %d\n", i);
+
dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk));
+ }
}
static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
@@ -437,7 +372,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node;
u32 ckr, rbgx, rbga, rbgb;
- u32 rate, req_rate, div;
+ u32 rate, req_rate = 0, div;
uint32_t count = 0;
unsigned long req_48kHz_rate, req_441kHz_rate;
int i;
@@ -572,9 +507,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
ckr, rbga, rbgb);
}
-int rsnd_adg_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+int rsnd_adg_probe(struct rsnd_priv *priv)
{
struct rsnd_adg *adg;
struct device *dev = rsnd_priv_to_dev(priv);
@@ -600,3 +533,14 @@ int rsnd_adg_probe(struct platform_device *pdev,
return 0;
}
+
+void rsnd_adg_remove(struct rsnd_priv *priv)
+{
+ struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
+ struct clk *clk;
+ int i;
+
+ for_each_rsnd_clk(clk, adg, i) {
+ clk_disable_unprepare(clk);
+ }
+}
diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c
new file mode 100644
index 000000000000..cd1f064e63c4
--- /dev/null
+++ b/sound/soc/sh/rcar/cmd.c
@@ -0,0 +1,171 @@
+/*
+ * Renesas R-Car CMD support
+ *
+ * Copyright (C) 2015 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "rsnd.h"
+
+struct rsnd_cmd {
+ struct rsnd_mod mod;
+};
+
+#define CMD_NAME "cmd"
+
+#define rsnd_cmd_nr(priv) ((priv)->cmd_nr)
+#define for_each_rsnd_cmd(pos, priv, i) \
+ for ((i) = 0; \
+ ((i) < rsnd_cmd_nr(priv)) && \
+ ((pos) = (struct rsnd_cmd *)(priv)->cmd + i); \
+ i++)
+
+static int rsnd_cmd_init(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
+ struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
+ struct rsnd_mod *src = rsnd_io_to_mod_src(io);
+ struct device *dev = rsnd_priv_to_dev(priv);
+ u32 data;
+
+ if (!mix && !dvc)
+ return 0;
+
+ if (mix) {
+ struct rsnd_dai *rdai;
+ int i;
+ u32 path[] = {
+ [0] = 0,
+ [1] = 1 << 0,
+ [2] = 0,
+ [3] = 0,
+ [4] = 0,
+ [5] = 1 << 8
+ };
+
+ /*
+ * it is assuming that integrater is well understanding about
+ * data path. Here doesn't check impossible connection,
+ * like src2 + src5
+ */
+ data = 0;
+ for_each_rsnd_dai(rdai, priv, i) {
+ io = &rdai->playback;
+ if (mix == rsnd_io_to_mod_mix(io))
+ data |= path[rsnd_mod_id(src)];
+
+ io = &rdai->capture;
+ if (mix == rsnd_io_to_mod_mix(io))
+ data |= path[rsnd_mod_id(src)];
+ }
+
+ } else {
+ u32 path[] = {
+ [0] = 0x30000,
+ [1] = 0x30001,
+ [2] = 0x40000,
+ [3] = 0x10000,
+ [4] = 0x20000,
+ [5] = 0x40100
+ };
+
+ data = path[rsnd_mod_id(src)];
+ }
+
+ dev_dbg(dev, "ctu/mix path = 0x%08x", data);
+
+ rsnd_mod_write(mod, CMD_ROUTE_SLCT, data);
+ rsnd_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
+
+ rsnd_adg_set_cmd_timsel_gen2(mod, io);
+
+ return 0;
+}
+
+static int rsnd_cmd_start(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ rsnd_mod_write(mod, CMD_CTRL, 0x10);
+
+ return 0;
+}
+
+static int rsnd_cmd_stop(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ rsnd_mod_write(mod, CMD_CTRL, 0);
+
+ return 0;
+}
+
+static struct rsnd_mod_ops rsnd_cmd_ops = {
+ .name = CMD_NAME,
+ .init = rsnd_cmd_init,
+ .start = rsnd_cmd_start,
+ .stop = rsnd_cmd_stop,
+};
+
+int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id)
+{
+ struct rsnd_priv *priv = rsnd_io_to_priv(io);
+ struct rsnd_mod *mod = rsnd_cmd_mod_get(priv, id);
+
+ return rsnd_dai_connect(mod, io, mod->type);
+}
+
+struct rsnd_mod *rsnd_cmd_mod_get(struct rsnd_priv *priv, int id)
+{
+ if (WARN_ON(id < 0 || id >= rsnd_cmd_nr(priv)))
+ id = 0;
+
+ return rsnd_mod_get((struct rsnd_cmd *)(priv->cmd) + id);
+}
+
+int rsnd_cmd_probe(struct rsnd_priv *priv)
+{
+ struct device *dev = rsnd_priv_to_dev(priv);
+ struct rsnd_cmd *cmd;
+ int i, nr, ret;
+
+ /* This driver doesn't support Gen1 at this point */
+ if (rsnd_is_gen1(priv))
+ return 0;
+
+ /* same number as DVC */
+ nr = priv->dvc_nr;
+ if (!nr)
+ return 0;
+
+ cmd = devm_kzalloc(dev, sizeof(*cmd) * nr, GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ priv->cmd_nr = nr;
+ priv->cmd = cmd;
+
+ for_each_rsnd_cmd(cmd, priv, i) {
+ ret = rsnd_mod_init(priv, rsnd_mod_get(cmd),
+ &rsnd_cmd_ops, NULL, RSND_MOD_CMD, i);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+void rsnd_cmd_remove(struct rsnd_priv *priv)
+{
+ struct rsnd_cmd *cmd;
+ int i;
+
+ for_each_rsnd_cmd(cmd, priv, i) {
+ rsnd_mod_quit(rsnd_mod_get(cmd));
+ }
+}
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index deed48ef28b8..02b4b085b8d7 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -99,34 +99,17 @@
#define RSND_RATES SNDRV_PCM_RATE_8000_96000
#define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
-static const struct rsnd_of_data rsnd_of_data_gen1 = {
- .flags = RSND_GEN1,
-};
-
-static const struct rsnd_of_data rsnd_of_data_gen2 = {
- .flags = RSND_GEN2,
-};
-
static const struct of_device_id rsnd_of_match[] = {
- { .compatible = "renesas,rcar_sound-gen1", .data = &rsnd_of_data_gen1 },
- { .compatible = "renesas,rcar_sound-gen2", .data = &rsnd_of_data_gen2 },
- { .compatible = "renesas,rcar_sound-gen3", .data = &rsnd_of_data_gen2 }, /* gen2 compatible */
+ { .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 },
+ { .compatible = "renesas,rcar_sound-gen2", .data = (void *)RSND_GEN2 },
+ { .compatible = "renesas,rcar_sound-gen3", .data = (void *)RSND_GEN2 }, /* gen2 compatible */
{},
};
MODULE_DEVICE_TABLE(of, rsnd_of_match);
/*
- * rsnd_platform functions
+ * rsnd_mod functions
*/
-#define rsnd_platform_call(priv, dai, func, param...) \
- (!(priv->info->func) ? 0 : \
- priv->info->func(param))
-
-#define rsnd_is_enable_path(io, name) \
- ((io)->info ? (io)->info->name : NULL)
-#define rsnd_info_id(priv, io, name) \
- ((io)->info->name - priv->info->name##_info)
-
void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type)
{
if (mod->type != type) {
@@ -138,9 +121,6 @@ void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type)
}
}
-/*
- * rsnd_mod functions
- */
char *rsnd_mod_name(struct rsnd_mod *mod)
{
if (!mod || !mod->ops)
@@ -192,19 +172,16 @@ void rsnd_mod_interrupt(struct rsnd_mod *mod,
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_dai_stream *io;
struct rsnd_dai *rdai;
- int i, j;
-
- for_each_rsnd_dai(rdai, priv, j) {
+ int i;
- for (i = 0; i < RSND_MOD_MAX; i++) {
- io = &rdai->playback;
- if (mod == io->mod[i])
- callback(mod, io);
+ for_each_rsnd_dai(rdai, priv, i) {
+ io = &rdai->playback;
+ if (mod == io->mod[mod->type])
+ callback(mod, io);
- io = &rdai->capture;
- if (mod == io->mod[i])
- callback(mod, io);
- }
+ io = &rdai->capture;
+ if (mod == io->mod[mod->type])
+ callback(mod, io);
}
}
@@ -214,6 +191,43 @@ int rsnd_io_is_working(struct rsnd_dai_stream *io)
return !!io->substream;
}
+void rsnd_set_slot(struct rsnd_dai *rdai,
+ int slots, int num)
+{
+ rdai->slots = slots;
+ rdai->slots_num = num;
+}
+
+int rsnd_get_slot(struct rsnd_dai_stream *io)
+{
+ struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+
+ return rdai->slots;
+}
+
+int rsnd_get_slot_num(struct rsnd_dai_stream *io)
+{
+ struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+
+ return rdai->slots_num;
+}
+
+int rsnd_get_slot_width(struct rsnd_dai_stream *io)
+{
+ struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+ int chan = runtime->channels;
+
+ /* Multi channel Mode */
+ if (rsnd_ssi_multi_slaves(io))
+ chan /= rsnd_get_slot_num(io);
+
+ /* TDM Extend Mode needs 8ch */
+ if (chan == 6)
+ chan = 8;
+
+ return chan;
+}
+
/*
* ADINR function
*/
@@ -222,21 +236,17 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct device *dev = rsnd_priv_to_dev(priv);
- u32 adinr = runtime->channels;
switch (runtime->sample_bits) {
case 16:
- adinr |= (8 << 16);
- break;
+ return 8 << 16;
case 32:
- adinr |= (0 << 16);
- break;
- default:
- dev_warn(dev, "not supported sample bits\n");
- return 0;
+ return 0 << 16;
}
- return adinr;
+ dev_warn(dev, "not supported sample bits\n");
+
+ return 0;
}
u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
@@ -267,13 +277,22 @@ u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
*/
u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
{
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *target = src ? src : ssi;
+ struct rsnd_mod *target;
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
u32 val = 0x76543210;
u32 mask = ~0;
+ if (rsnd_io_is_play(io)) {
+ struct rsnd_mod *src = rsnd_io_to_mod_src(io);
+
+ target = src ? src : ssi;
+ } else {
+ struct rsnd_mod *cmd = rsnd_io_to_mod_cmd(io);
+
+ target = cmd ? cmd : ssi;
+ }
+
mask <<= runtime->channels * 4;
val = val & mask;
@@ -300,20 +319,22 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
/*
* rsnd_dai functions
*/
-#define rsnd_mod_call(mod, io, func, param...) \
+#define rsnd_mod_call(idx, io, func, param...) \
({ \
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \
+ struct rsnd_mod *mod = (io)->mod[idx]; \
struct device *dev = rsnd_priv_to_dev(priv); \
+ u32 *status = (io)->mod_status + idx; \
u32 mask = 0xF << __rsnd_mod_shift_##func; \
- u8 val = (mod->status >> __rsnd_mod_shift_##func) & 0xF; \
+ u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \
u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \
int ret = 0; \
int call = (val == __rsnd_mod_call_##func) && (mod)->ops->func; \
- mod->status = (mod->status & ~mask) + \
+ *status = (*status & ~mask) + \
(add << __rsnd_mod_shift_##func); \
dev_dbg(dev, "%s[%d]\t0x%08x %s\n", \
rsnd_mod_name(mod), rsnd_mod_id(mod), \
- mod->status, call ? #func : ""); \
+ *status, call ? #func : ""); \
if (call) \
ret = (mod)->ops->func(mod, io, param); \
ret; \
@@ -327,13 +348,14 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
mod = (io)->mod[i]; \
if (!mod) \
continue; \
- ret |= rsnd_mod_call(mod, io, fn, param); \
+ ret |= rsnd_mod_call(i, io, fn, param); \
} \
ret; \
})
-static int rsnd_dai_connect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
+int rsnd_dai_connect(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ enum rsnd_mod_type type)
{
struct rsnd_priv *priv;
struct device *dev;
@@ -341,10 +363,13 @@ static int rsnd_dai_connect(struct rsnd_mod *mod,
if (!mod)
return -EIO;
+ if (io->mod[type])
+ return -EINVAL;
+
priv = rsnd_mod_to_priv(mod);
dev = rsnd_priv_to_dev(priv);
- io->mod[mod->type] = mod;
+ io->mod[type] = mod;
dev_dbg(dev, "%s[%d] is connected to io (%s)\n",
rsnd_mod_name(mod), rsnd_mod_id(mod),
@@ -354,9 +379,10 @@ static int rsnd_dai_connect(struct rsnd_mod *mod,
}
static void rsnd_dai_disconnect(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
+ struct rsnd_dai_stream *io,
+ enum rsnd_mod_type type)
{
- io->mod[mod->type] = NULL;
+ io->mod[type] = NULL;
}
struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id)
@@ -469,7 +495,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
- int ssi_id = rsnd_mod_id(rsnd_io_to_mod_ssi(io));
int ret;
unsigned long flags;
@@ -479,10 +504,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
rsnd_dai_stream_init(io, substream);
- ret = rsnd_platform_call(priv, dai, start, ssi_id);
- if (ret < 0)
- goto dai_trigger_end;
-
ret = rsnd_dai_call(init, io, priv);
if (ret < 0)
goto dai_trigger_end;
@@ -496,8 +517,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
ret |= rsnd_dai_call(quit, io, priv);
- ret |= rsnd_platform_call(priv, dai, stop, ssi_id);
-
rsnd_dai_stream_quit(io);
break;
default:
@@ -567,332 +586,157 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0;
}
-static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
- .trigger = rsnd_soc_dai_trigger,
- .set_fmt = rsnd_soc_dai_set_fmt,
-};
-
-#define rsnd_path_add(priv, io, type) \
-({ \
- struct rsnd_mod *mod; \
- int ret = 0; \
- int id = -1; \
- \
- if (rsnd_is_enable_path(io, type)) { \
- id = rsnd_info_id(priv, io, type); \
- if (id >= 0) { \
- mod = rsnd_##type##_mod_get(priv, id); \
- ret = rsnd_dai_connect(mod, io); \
- } \
- } \
- ret; \
-})
-
-#define rsnd_path_remove(priv, io, type) \
-{ \
- struct rsnd_mod *mod; \
- int id = -1; \
- \
- if (rsnd_is_enable_path(io, type)) { \
- id = rsnd_info_id(priv, io, type); \
- if (id >= 0) { \
- mod = rsnd_##type##_mod_get(priv, id); \
- rsnd_dai_disconnect(mod, io); \
- } \
- } \
-}
-
-void rsnd_path_parse(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io)
+static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
+ u32 tx_mask, u32 rx_mask,
+ int slots, int slot_width)
{
- struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
- struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
- struct rsnd_mod *src = rsnd_io_to_mod_src(io);
- struct rsnd_mod *cmd;
+ struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
+ struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct device *dev = rsnd_priv_to_dev(priv);
- u32 data;
- /* Gen1 is not supported */
- if (rsnd_is_gen1(priv))
- return;
-
- if (!mix && !dvc)
- return;
-
- if (mix) {
- struct rsnd_dai *rdai;
- int i;
- u32 path[] = {
- [0] = 0,
- [1] = 1 << 0,
- [2] = 0,
- [3] = 0,
- [4] = 0,
- [5] = 1 << 8
- };
-
- /*
- * it is assuming that integrater is well understanding about
- * data path. Here doesn't check impossible connection,
- * like src2 + src5
- */
- data = 0;
- for_each_rsnd_dai(rdai, priv, i) {
- io = &rdai->playback;
- if (mix == rsnd_io_to_mod_mix(io))
- data |= path[rsnd_mod_id(src)];
-
- io = &rdai->capture;
- if (mix == rsnd_io_to_mod_mix(io))
- data |= path[rsnd_mod_id(src)];
- }
-
- /*
- * We can't use ctu = rsnd_io_ctu() here.
- * Since, ID of dvc/mix are 0 or 1 (= same as CMD number)
- * but ctu IDs are 0 - 7 (= CTU00 - CTU13)
- */
- cmd = mix;
- } else {
- u32 path[] = {
- [0] = 0x30000,
- [1] = 0x30001,
- [2] = 0x40000,
- [3] = 0x10000,
- [4] = 0x20000,
- [5] = 0x40100
- };
-
- data = path[rsnd_mod_id(src)];
-
- cmd = dvc;
+ switch (slots) {
+ case 6:
+ /* TDM Extend Mode */
+ rsnd_set_slot(rdai, slots, 1);
+ break;
+ default:
+ dev_err(dev, "unsupported TDM slots (%d)\n", slots);
+ return -EINVAL;
}
- dev_dbg(dev, "ctu/mix path = 0x%08x", data);
-
- rsnd_mod_write(cmd, CMD_ROUTE_SLCT, data);
-
- rsnd_mod_write(cmd, CMD_CTRL, 0x10);
+ return 0;
}
-static int rsnd_path_init(struct rsnd_priv *priv,
- struct rsnd_dai *rdai,
- struct rsnd_dai_stream *io)
-{
- int ret;
-
- /*
- * Gen1 is created by SRU/SSI, and this SRU is base module of
- * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU)
- *
- * Easy image is..
- * Gen1 SRU = Gen2 SCU + SSIU + etc
- *
- * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
- * using fixed path.
- */
-
- /* SSI */
- ret = rsnd_path_add(priv, io, ssi);
- if (ret < 0)
- return ret;
-
- /* SRC */
- ret = rsnd_path_add(priv, io, src);
- if (ret < 0)
- return ret;
+static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
+ .trigger = rsnd_soc_dai_trigger,
+ .set_fmt = rsnd_soc_dai_set_fmt,
+ .set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
+};
- /* CTU */
- ret = rsnd_path_add(priv, io, ctu);
- if (ret < 0)
- return ret;
+void rsnd_parse_connect_common(struct rsnd_dai *rdai,
+ struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id),
+ struct device_node *node,
+ struct device_node *playback,
+ struct device_node *capture)
+{
+ struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
+ struct device_node *np;
+ struct rsnd_mod *mod;
+ int i;
- /* MIX */
- ret = rsnd_path_add(priv, io, mix);
- if (ret < 0)
- return ret;
+ if (!node)
+ return;
- /* DVC */
- ret = rsnd_path_add(priv, io, dvc);
- if (ret < 0)
- return ret;
+ i = 0;
+ for_each_child_of_node(node, np) {
+ mod = mod_get(priv, i);
+ if (np == playback)
+ rsnd_dai_connect(mod, &rdai->playback, mod->type);
+ if (np == capture)
+ rsnd_dai_connect(mod, &rdai->capture, mod->type);
+ i++;
+ }
- return ret;
+ of_node_put(node);
}
-static void rsnd_of_parse_dai(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+static int rsnd_dai_probe(struct rsnd_priv *priv)
{
- struct device_node *dai_node, *dai_np;
- struct device_node *ssi_node, *ssi_np;
- struct device_node *src_node, *src_np;
- struct device_node *ctu_node, *ctu_np;
- struct device_node *mix_node, *mix_np;
- struct device_node *dvc_node, *dvc_np;
+ struct device_node *dai_node;
+ struct device_node *dai_np;
struct device_node *playback, *capture;
- struct rsnd_dai_platform_info *dai_info;
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
- struct device *dev = &pdev->dev;
- int nr, i;
- int dai_i, ssi_i, src_i, ctu_i, mix_i, dvc_i;
-
- if (!of_data)
- return;
-
- dai_node = of_get_child_by_name(dev->of_node, "rcar_sound,dai");
- if (!dai_node)
- return;
+ struct rsnd_dai_stream *io_playback;
+ struct rsnd_dai_stream *io_capture;
+ struct snd_soc_dai_driver *rdrv, *drv;
+ struct rsnd_dai *rdai;
+ struct device *dev = rsnd_priv_to_dev(priv);
+ int nr, dai_i, io_i;
+ int ret;
+ dai_node = rsnd_dai_of_node(priv);
nr = of_get_child_count(dai_node);
- if (!nr)
- return;
+ if (!nr) {
+ ret = -EINVAL;
+ goto rsnd_dai_probe_done;
+ }
- dai_info = devm_kzalloc(dev,
- sizeof(struct rsnd_dai_platform_info) * nr,
- GFP_KERNEL);
- if (!dai_info) {
- dev_err(dev, "dai info allocation error\n");
- return;
+ rdrv = devm_kzalloc(dev, sizeof(*rdrv) * nr, GFP_KERNEL);
+ rdai = devm_kzalloc(dev, sizeof(*rdai) * nr, GFP_KERNEL);
+ if (!rdrv || !rdai) {
+ ret = -ENOMEM;
+ goto rsnd_dai_probe_done;
}
- info->dai_info_nr = nr;
- info->dai_info = dai_info;
-
- ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
- src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src");
- ctu_node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu");
- mix_node = of_get_child_by_name(dev->of_node, "rcar_sound,mix");
- dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc");
-
-#define mod_parse(name) \
-if (name##_node) { \
- struct rsnd_##name##_platform_info *name##_info; \
- \
- name##_i = 0; \
- for_each_child_of_node(name##_node, name##_np) { \
- name##_info = info->name##_info + name##_i; \
- \
- if (name##_np == playback) \
- dai_info->playback.name = name##_info; \
- if (name##_np == capture) \
- dai_info->capture.name = name##_info; \
- \
- name##_i++; \
- } \
-}
+ priv->rdai_nr = nr;
+ priv->daidrv = rdrv;
+ priv->rdai = rdai;
/*
* parse all dai
*/
dai_i = 0;
for_each_child_of_node(dai_node, dai_np) {
- dai_info = info->dai_info + dai_i;
-
- for (i = 0;; i++) {
-
- playback = of_parse_phandle(dai_np, "playback", i);
- capture = of_parse_phandle(dai_np, "capture", i);
+ rdai = rsnd_rdai_get(priv, dai_i);
+ drv = rdrv + dai_i;
+ io_playback = &rdai->playback;
+ io_capture = &rdai->capture;
+
+ snprintf(rdai->name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", dai_i);
+
+ rdai->priv = priv;
+ drv->name = rdai->name;
+ drv->ops = &rsnd_soc_dai_ops;
+
+ snprintf(rdai->playback.name, RSND_DAI_NAME_SIZE,
+ "DAI%d Playback", dai_i);
+ drv->playback.rates = RSND_RATES;
+ drv->playback.formats = RSND_FMTS;
+ drv->playback.channels_min = 2;
+ drv->playback.channels_max = 6;
+ drv->playback.stream_name = rdai->playback.name;
+
+ snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE,
+ "DAI%d Capture", dai_i);
+ drv->capture.rates = RSND_RATES;
+ drv->capture.formats = RSND_FMTS;
+ drv->capture.channels_min = 2;
+ drv->capture.channels_max = 6;
+ drv->capture.stream_name = rdai->capture.name;
+
+ rdai->playback.rdai = rdai;
+ rdai->capture.rdai = rdai;
+ rsnd_set_slot(rdai, 2, 1); /* default */
+
+ for (io_i = 0;; io_i++) {
+ playback = of_parse_phandle(dai_np, "playback", io_i);
+ capture = of_parse_phandle(dai_np, "capture", io_i);
if (!playback && !capture)
break;
- mod_parse(ssi);
- mod_parse(src);
- mod_parse(ctu);
- mod_parse(mix);
- mod_parse(dvc);
+ rsnd_parse_connect_ssi(rdai, playback, capture);
+ rsnd_parse_connect_src(rdai, playback, capture);
+ rsnd_parse_connect_ctu(rdai, playback, capture);
+ rsnd_parse_connect_mix(rdai, playback, capture);
+ rsnd_parse_connect_dvc(rdai, playback, capture);
of_node_put(playback);
of_node_put(capture);
}
dai_i++;
- }
-}
-
-static int rsnd_dai_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
-{
- struct snd_soc_dai_driver *drv;
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
- struct rsnd_dai *rdai;
- struct rsnd_ssi_platform_info *pmod, *cmod;
- struct device *dev = rsnd_priv_to_dev(priv);
- int dai_nr;
- int i;
-
- rsnd_of_parse_dai(pdev, of_data, priv);
- dai_nr = info->dai_info_nr;
- if (!dai_nr) {
- dev_err(dev, "no dai\n");
- return -EIO;
+ dev_dbg(dev, "%s (%s/%s)\n", rdai->name,
+ rsnd_io_to_mod_ssi(io_playback) ? "play" : " -- ",
+ rsnd_io_to_mod_ssi(io_capture) ? "capture" : " -- ");
}
- drv = devm_kzalloc(dev, sizeof(*drv) * dai_nr, GFP_KERNEL);
- rdai = devm_kzalloc(dev, sizeof(*rdai) * dai_nr, GFP_KERNEL);
- if (!drv || !rdai) {
- dev_err(dev, "dai allocate failed\n");
- return -ENOMEM;
- }
-
- priv->rdai_nr = dai_nr;
- priv->daidrv = drv;
- priv->rdai = rdai;
+ ret = 0;
- for (i = 0; i < dai_nr; i++) {
+rsnd_dai_probe_done:
+ of_node_put(dai_node);
- pmod = info->dai_info[i].playback.ssi;
- cmod = info->dai_info[i].capture.ssi;
-
- /*
- * init rsnd_dai
- */
- snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i);
- rdai[i].priv = priv;
-
- /*
- * init snd_soc_dai_driver
- */
- drv[i].name = rdai[i].name;
- drv[i].ops = &rsnd_soc_dai_ops;
- if (pmod) {
- snprintf(rdai[i].playback.name, RSND_DAI_NAME_SIZE,
- "DAI%d Playback", i);
-
- drv[i].playback.rates = RSND_RATES;
- drv[i].playback.formats = RSND_FMTS;
- drv[i].playback.channels_min = 2;
- drv[i].playback.channels_max = 2;
- drv[i].playback.stream_name = rdai[i].playback.name;
-
- rdai[i].playback.info = &info->dai_info[i].playback;
- rdai[i].playback.rdai = rdai + i;
- rsnd_path_init(priv, &rdai[i], &rdai[i].playback);
- }
- if (cmod) {
- snprintf(rdai[i].capture.name, RSND_DAI_NAME_SIZE,
- "DAI%d Capture", i);
-
- drv[i].capture.rates = RSND_RATES;
- drv[i].capture.formats = RSND_FMTS;
- drv[i].capture.channels_min = 2;
- drv[i].capture.channels_max = 2;
- drv[i].capture.stream_name = rdai[i].capture.name;
-
- rdai[i].capture.info = &info->dai_info[i].capture;
- rdai[i].capture.rdai = rdai + i;
- rsnd_path_init(priv, &rdai[i], &rdai[i].capture);
- }
-
- dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name,
- pmod ? "play" : " -- ",
- cmod ? "capture" : " -- ");
- }
-
- return 0;
+ return ret;
}
/*
@@ -1033,14 +877,13 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod))
{
- struct snd_soc_card *soc_card = rtd->card;
struct snd_card *card = rtd->card->snd_card;
struct snd_kcontrol *kctrl;
struct snd_kcontrol_new knew = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = name,
.info = rsnd_kctrl_info,
- .index = rtd - soc_card->rtd,
+ .index = rtd->num,
.get = rsnd_kctrl_get,
.put = rsnd_kctrl_put,
.private_value = (unsigned long)cfg,
@@ -1077,10 +920,14 @@ int rsnd_kctrl_new_m(struct rsnd_mod *mod,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
struct rsnd_kctrl_cfg_m *_cfg,
+ int ch_size,
u32 max)
{
+ if (ch_size > RSND_DVC_CHANNELS)
+ return -EINVAL;
+
_cfg->cfg.max = max;
- _cfg->cfg.size = RSND_DVC_CHANNELS;
+ _cfg->cfg.size = ch_size;
_cfg->cfg.val = _cfg->val;
return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update);
}
@@ -1161,6 +1008,9 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
ret = rsnd_dai_call(probe, io, priv);
if (ret == -EAGAIN) {
+ struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
+ int i;
+
/*
* Fallback to PIO mode
*/
@@ -1175,10 +1025,12 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
rsnd_dai_call(remove, io, priv);
/*
- * remove SRC/DVC from DAI,
+ * remove all mod from io
+ * and, re connect ssi
*/
- rsnd_path_remove(priv, io, src);
- rsnd_path_remove(priv, io, dvc);
+ for (i = 0; i < RSND_MOD_MAX; i++)
+ rsnd_dai_disconnect((io)->mod[i], io, i);
+ rsnd_dai_connect(ssi_mod, io, RSND_MOD_SSI);
/*
* fallback
@@ -1200,33 +1052,25 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
*/
static int rsnd_probe(struct platform_device *pdev)
{
- struct rcar_snd_info *info;
struct rsnd_priv *priv;
struct device *dev = &pdev->dev;
struct rsnd_dai *rdai;
const struct of_device_id *of_id = of_match_device(rsnd_of_match, dev);
- const struct rsnd_of_data *of_data;
- int (*probe_func[])(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv) = {
+ int (*probe_func[])(struct rsnd_priv *priv) = {
rsnd_gen_probe,
rsnd_dma_probe,
rsnd_ssi_probe,
+ rsnd_ssiu_probe,
rsnd_src_probe,
rsnd_ctu_probe,
rsnd_mix_probe,
rsnd_dvc_probe,
+ rsnd_cmd_probe,
rsnd_adg_probe,
rsnd_dai_probe,
};
int ret, i;
- info = devm_kzalloc(&pdev->dev, sizeof(struct rcar_snd_info),
- GFP_KERNEL);
- if (!info)
- return -ENOMEM;
- of_data = of_id->data;
-
/*
* init priv data
*/
@@ -1237,14 +1081,14 @@ static int rsnd_probe(struct platform_device *pdev)
}
priv->pdev = pdev;
- priv->info = info;
+ priv->flags = (unsigned long)of_id->data;
spin_lock_init(&priv->lock);
/*
* init each module
*/
for (i = 0; i < ARRAY_SIZE(probe_func); i++) {
- ret = probe_func[i](pdev, of_data, priv);
+ ret = probe_func[i](priv);
if (ret)
return ret;
}
@@ -1297,13 +1141,15 @@ static int rsnd_remove(struct platform_device *pdev)
{
struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev);
struct rsnd_dai *rdai;
- void (*remove_func[])(struct platform_device *pdev,
- struct rsnd_priv *priv) = {
+ void (*remove_func[])(struct rsnd_priv *priv) = {
rsnd_ssi_remove,
+ rsnd_ssiu_remove,
rsnd_src_remove,
rsnd_ctu_remove,
rsnd_mix_remove,
rsnd_dvc_remove,
+ rsnd_cmd_remove,
+ rsnd_adg_remove,
};
int ret = 0, i;
@@ -1315,7 +1161,7 @@ static int rsnd_remove(struct platform_device *pdev)
}
for (i = 0; i < ARRAY_SIZE(remove_func); i++)
- remove_func[i](pdev, priv);
+ remove_func[i](priv);
snd_soc_unregister_component(&pdev->dev);
snd_soc_unregister_platform(&pdev->dev);
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c
index 3cb214ab848b..d53a225d19e9 100644
--- a/sound/soc/sh/rcar/ctu.c
+++ b/sound/soc/sh/rcar/ctu.c
@@ -13,7 +13,6 @@
#define CTU_NAME "ctu"
struct rsnd_ctu {
- struct rsnd_ctu_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
};
@@ -24,6 +23,7 @@ struct rsnd_ctu {
((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \
i++)
+#define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id)
#define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1)
#define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0)
static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable)
@@ -31,6 +31,13 @@ static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable)
rsnd_mod_write(mod, CTU_CTUIR, enable);
}
+static int rsnd_ctu_probe_(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ return rsnd_cmd_attach(io, rsnd_mod_id(mod) / 4);
+}
+
static int rsnd_ctu_init(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
@@ -57,6 +64,7 @@ static int rsnd_ctu_quit(struct rsnd_mod *mod,
static struct rsnd_mod_ops rsnd_ctu_ops = {
.name = CTU_NAME,
+ .probe = rsnd_ctu_probe_,
.init = rsnd_ctu_init,
.quit = rsnd_ctu_quit,
};
@@ -66,51 +74,13 @@ struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
id = 0;
- return rsnd_mod_get((struct rsnd_ctu *)(priv->ctu) + id);
+ return rsnd_mod_get(rsnd_ctu_get(priv, id));
}
-static void rsnd_of_parse_ctu(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+int rsnd_ctu_probe(struct rsnd_priv *priv)
{
struct device_node *node;
- struct rsnd_ctu_platform_info *ctu_info;
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
- struct device *dev = &pdev->dev;
- int nr;
-
- if (!of_data)
- return;
-
- node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu");
- if (!node)
- return;
-
- nr = of_get_child_count(node);
- if (!nr)
- goto rsnd_of_parse_ctu_end;
-
- ctu_info = devm_kzalloc(dev,
- sizeof(struct rsnd_ctu_platform_info) * nr,
- GFP_KERNEL);
- if (!ctu_info) {
- dev_err(dev, "ctu info allocation error\n");
- goto rsnd_of_parse_ctu_end;
- }
-
- info->ctu_info = ctu_info;
- info->ctu_info_nr = nr;
-
-rsnd_of_parse_ctu_end:
- of_node_put(node);
-
-}
-
-int rsnd_ctu_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
-{
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
+ struct device_node *np;
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_ctu *ctu;
struct clk *clk;
@@ -121,20 +91,30 @@ int rsnd_ctu_probe(struct platform_device *pdev,
if (rsnd_is_gen1(priv))
return 0;
- rsnd_of_parse_ctu(pdev, of_data, priv);
+ node = rsnd_ctu_of_node(priv);
+ if (!node)
+ return 0; /* not used is not error */
- nr = info->ctu_info_nr;
- if (!nr)
- return 0;
+ nr = of_get_child_count(node);
+ if (!nr) {
+ ret = -EINVAL;
+ goto rsnd_ctu_probe_done;
+ }
ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL);
- if (!ctu)
- return -ENOMEM;
+ if (!ctu) {
+ ret = -ENOMEM;
+ goto rsnd_ctu_probe_done;
+ }
priv->ctu_nr = nr;
priv->ctu = ctu;
- for_each_rsnd_ctu(ctu, priv, i) {
+ i = 0;
+ ret = 0;
+ for_each_child_of_node(node, np) {
+ ctu = rsnd_ctu_get(priv, i);
+
/*
* CTU00, CTU01, CTU02, CTU03 => CTU0
* CTU10, CTU11, CTU12, CTU13 => CTU1
@@ -143,22 +123,27 @@ int rsnd_ctu_probe(struct platform_device *pdev,
CTU_NAME, i / 4);
clk = devm_clk_get(dev, name);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- ctu->info = &info->ctu_info[i];
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto rsnd_ctu_probe_done;
+ }
ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
clk, RSND_MOD_CTU, i);
if (ret)
- return ret;
+ goto rsnd_ctu_probe_done;
+
+ i++;
}
- return 0;
+
+rsnd_ctu_probe_done:
+ of_node_put(node);
+
+ return ret;
}
-void rsnd_ctu_remove(struct platform_device *pdev,
- struct rsnd_priv *priv)
+void rsnd_ctu_remove(struct rsnd_priv *priv)
{
struct rsnd_ctu *ctu;
int i;
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 5d084d040961..418e6fdd06a3 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -22,21 +22,36 @@
/* PDMACHCR */
#define PDMACHCR_DE (1 << 0)
+
+struct rsnd_dmaen {
+ struct dma_chan *chan;
+};
+
+struct rsnd_dmapp {
+ int dmapp_id;
+ u32 chcr;
+};
+
+struct rsnd_dma {
+ struct rsnd_mod mod;
+ dma_addr_t src_addr;
+ dma_addr_t dst_addr;
+ union {
+ struct rsnd_dmaen en;
+ struct rsnd_dmapp pp;
+ } dma;
+};
+
struct rsnd_dma_ctrl {
void __iomem *base;
+ int dmaen_num;
int dmapp_num;
};
-struct rsnd_dma_ops {
- char *name;
- void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
- void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
- int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id,
- struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
- void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
-};
-
#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma)
+#define rsnd_mod_to_dma(_mod) container_of((_mod), struct rsnd_dma, mod)
+#define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en)
+#define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp)
/*
* Audio DMAC
@@ -77,18 +92,24 @@ static void rsnd_dmaen_complete(void *data)
rsnd_mod_interrupt(mod, __rsnd_dmaen_complete);
}
-static void rsnd_dmaen_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
+static int rsnd_dmaen_stop(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
+ struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
dmaengine_terminate_all(dmaen->chan);
+
+ return 0;
}
-static void rsnd_dmaen_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
+static int rsnd_dmaen_start(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
+ struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct snd_pcm_substream *substream = io->substream;
struct device *dev = rsnd_priv_to_dev(priv);
struct dma_async_tx_descriptor *desc;
@@ -103,18 +124,20 @@ static void rsnd_dmaen_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
if (!desc) {
dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
- return;
+ return -EIO;
}
desc->callback = rsnd_dmaen_complete;
- desc->callback_param = mod;
+ desc->callback_param = rsnd_mod_get(dma);
if (dmaengine_submit(desc) < 0) {
dev_err(dev, "dmaengine_submit() fail\n");
- return;
+ return -EIO;
}
dma_async_issue_pending(dmaen->chan);
+
+ return 0;
}
struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
@@ -152,12 +175,29 @@ static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_dai_stream *io,
return rsnd_mod_dma_req(io, mod_to);
}
-static int rsnd_dmaen_init(struct rsnd_dai_stream *io,
+static int rsnd_dmaen_remove(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
+ struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
+
+ if (dmaen->chan)
+ dma_release_channel(dmaen->chan);
+
+ dmaen->chan = NULL;
+
+ return 0;
+}
+
+static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
struct rsnd_dma *dma, int id,
struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
{
+ struct rsnd_mod *mod = rsnd_mod_get(dma);
struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
struct rsnd_priv *priv = rsnd_io_to_priv(io);
+ struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
struct device *dev = rsnd_priv_to_dev(priv);
struct dma_slave_config cfg = {};
int is_play = rsnd_io_is_play(io);
@@ -191,18 +231,20 @@ static int rsnd_dmaen_init(struct rsnd_dai_stream *io,
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- dev_dbg(dev, "%s %pad -> %pad\n",
- dma->ops->name,
+ dev_dbg(dev, "%s[%d] %pad -> %pad\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod),
&cfg.src_addr, &cfg.dst_addr);
ret = dmaengine_slave_config(dmaen->chan, &cfg);
if (ret < 0)
- goto rsnd_dma_init_err;
+ goto rsnd_dma_attach_err;
+
+ dmac->dmaen_num++;
return 0;
-rsnd_dma_init_err:
- rsnd_dma_quit(io, dma);
+rsnd_dma_attach_err:
+ rsnd_dmaen_remove(mod, io, priv);
rsnd_dma_channel_err:
/*
@@ -214,22 +256,11 @@ rsnd_dma_channel_err:
return -EAGAIN;
}
-static void rsnd_dmaen_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
-{
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
-
- if (dmaen->chan)
- dma_release_channel(dmaen->chan);
-
- dmaen->chan = NULL;
-}
-
-static struct rsnd_dma_ops rsnd_dmaen_ops = {
+static struct rsnd_mod_ops rsnd_dmaen_ops = {
.name = "audmac",
.start = rsnd_dmaen_start,
.stop = rsnd_dmaen_stop,
- .init = rsnd_dmaen_init,
- .quit = rsnd_dmaen_quit,
+ .remove = rsnd_dmaen_remove,
};
/*
@@ -307,7 +338,7 @@ static u32 rsnd_dmapp_get_chcr(struct rsnd_dai_stream *io,
(0x10 * rsnd_dma_to_dmapp(dma)->dmapp_id))
static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg)
{
- struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
+ struct rsnd_mod *mod = rsnd_mod_get(dma);
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
struct device *dev = rsnd_priv_to_dev(priv);
@@ -319,38 +350,48 @@ static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg)
static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg)
{
- struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
+ struct rsnd_mod *mod = rsnd_mod_get(dma);
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
return ioread32(rsnd_dmapp_addr(dmac, dma, reg));
}
-static void rsnd_dmapp_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
+static int rsnd_dmapp_stop(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
+ struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
int i;
rsnd_dmapp_write(dma, 0, PDMACHCR);
for (i = 0; i < 1024; i++) {
if (0 == rsnd_dmapp_read(dma, PDMACHCR))
- return;
+ return 0;
udelay(1);
}
+
+ return -EIO;
}
-static void rsnd_dmapp_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
+static int rsnd_dmapp_start(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
+ struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
rsnd_dmapp_write(dma, dma->src_addr, PDMASAR);
rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR);
rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR);
+
+ return 0;
}
-static int rsnd_dmapp_init(struct rsnd_dai_stream *io,
- struct rsnd_dma *dma, int id,
- struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
+static int rsnd_dmapp_attach(struct rsnd_dai_stream *io,
+ struct rsnd_dma *dma, int id,
+ struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
{
struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
struct rsnd_priv *priv = rsnd_io_to_priv(io);
@@ -362,19 +403,16 @@ static int rsnd_dmapp_init(struct rsnd_dai_stream *io,
dmac->dmapp_num++;
- rsnd_dmapp_stop(io, dma);
-
dev_dbg(dev, "id/src/dst/chcr = %d/%pad/%pad/%08x\n",
dmapp->dmapp_id, &dma->src_addr, &dma->dst_addr, dmapp->chcr);
return 0;
}
-static struct rsnd_dma_ops rsnd_dmapp_ops = {
+static struct rsnd_mod_ops rsnd_dmapp_ops = {
.name = "audmac-pp",
.start = rsnd_dmapp_start,
.stop = rsnd_dmapp_stop,
- .init = rsnd_dmapp_init,
.quit = rsnd_dmapp_stop,
};
@@ -497,13 +535,12 @@ static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
}
#define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */
-static void rsnd_dma_of_path(struct rsnd_dma *dma,
+static void rsnd_dma_of_path(struct rsnd_mod *this,
struct rsnd_dai_stream *io,
int is_play,
struct rsnd_mod **mod_from,
struct rsnd_mod **mod_to)
{
- struct rsnd_mod *this = rsnd_dma_to_mod(dma);
struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
struct rsnd_mod *src = rsnd_io_to_mod_src(io);
struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io);
@@ -513,7 +550,7 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
struct rsnd_mod *mod_start, *mod_end;
struct rsnd_priv *priv = rsnd_mod_to_priv(this);
struct device *dev = rsnd_priv_to_dev(priv);
- int nr, i;
+ int nr, i, idx;
if (!ssi)
return;
@@ -542,23 +579,24 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
mod_start = (is_play) ? NULL : ssi;
mod_end = (is_play) ? ssi : NULL;
- mod[0] = mod_start;
+ idx = 0;
+ mod[idx++] = mod_start;
for (i = 1; i < nr; i++) {
if (src) {
- mod[i] = src;
+ mod[idx++] = src;
src = NULL;
} else if (ctu) {
- mod[i] = ctu;
+ mod[idx++] = ctu;
ctu = NULL;
} else if (mix) {
- mod[i] = mix;
+ mod[idx++] = mix;
mix = NULL;
} else if (dvc) {
- mod[i] = dvc;
+ mod[idx++] = dvc;
dvc = NULL;
}
}
- mod[i] = mod_end;
+ mod[idx] = mod_end;
/*
* | SSI | SRC |
@@ -567,8 +605,8 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
* !is_play | * | o |
*/
if ((this == ssi) == (is_play)) {
- *mod_from = mod[nr - 1];
- *mod_to = mod[nr];
+ *mod_from = mod[idx - 1];
+ *mod_to = mod[idx];
} else {
*mod_from = mod[0];
*mod_to = mod[1];
@@ -576,7 +614,7 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
dev_dbg(dev, "module connection (this is %s[%d])\n",
rsnd_mod_name(this), rsnd_mod_id(this));
- for (i = 0; i <= nr; i++) {
+ for (i = 0; i <= idx; i++) {
dev_dbg(dev, " %s[%d]%s\n",
rsnd_mod_name(mod[i]), rsnd_mod_id(mod[i]),
(mod[i] == *mod_from) ? " from" :
@@ -584,36 +622,22 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
}
}
-void rsnd_dma_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
-{
- dma->ops->stop(io, dma);
-}
-
-void rsnd_dma_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
-{
- dma->ops->start(io, dma);
-}
-
-void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
-{
- struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
-
- if (!dmac)
- return;
-
- dma->ops->quit(io, dma);
-}
-
-int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id)
+struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod, int id)
{
+ struct rsnd_mod *dma_mod;
struct rsnd_mod *mod_from = NULL;
struct rsnd_mod *mod_to = NULL;
struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
+ struct rsnd_dma *dma;
struct device *dev = rsnd_priv_to_dev(priv);
+ struct rsnd_mod_ops *ops;
+ enum rsnd_mod_type type;
+ int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id,
+ struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
int is_play = rsnd_io_is_play(io);
+ int ret, dma_id;
/*
* DMA failed. try to PIO mode
@@ -622,35 +646,64 @@ int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id)
* rsnd_rdai_continuance_probe()
*/
if (!dmac)
- return -EAGAIN;
+ return ERR_PTR(-EAGAIN);
- rsnd_dma_of_path(dma, io, is_play, &mod_from, &mod_to);
+ dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
+ if (!dma)
+ return ERR_PTR(-ENOMEM);
+
+ rsnd_dma_of_path(mod, io, is_play, &mod_from, &mod_to);
dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1);
dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0);
/* for Gen2 */
- if (mod_from && mod_to)
- dma->ops = &rsnd_dmapp_ops;
- else
- dma->ops = &rsnd_dmaen_ops;
+ if (mod_from && mod_to) {
+ ops = &rsnd_dmapp_ops;
+ attach = rsnd_dmapp_attach;
+ dma_id = dmac->dmapp_num;
+ type = RSND_MOD_AUDMAPP;
+ } else {
+ ops = &rsnd_dmaen_ops;
+ attach = rsnd_dmaen_attach;
+ dma_id = dmac->dmaen_num;
+ type = RSND_MOD_AUDMA;
+ }
/* for Gen1, overwrite */
- if (rsnd_is_gen1(priv))
- dma->ops = &rsnd_dmaen_ops;
+ if (rsnd_is_gen1(priv)) {
+ ops = &rsnd_dmaen_ops;
+ attach = rsnd_dmaen_attach;
+ dma_id = dmac->dmaen_num;
+ type = RSND_MOD_AUDMA;
+ }
+
+ dma_mod = rsnd_mod_get(dma);
+
+ ret = rsnd_mod_init(priv, dma_mod,
+ ops, NULL, type, dma_id);
+ if (ret < 0)
+ return ERR_PTR(ret);
- dev_dbg(dev, "%s %s[%d] -> %s[%d]\n",
- dma->ops->name,
+ dev_dbg(dev, "%s[%d] %s[%d] -> %s[%d]\n",
+ rsnd_mod_name(dma_mod), rsnd_mod_id(dma_mod),
rsnd_mod_name(mod_from), rsnd_mod_id(mod_from),
rsnd_mod_name(mod_to), rsnd_mod_id(mod_to));
- return dma->ops->init(io, dma, id, mod_from, mod_to);
+ ret = attach(io, dma, id, mod_from, mod_to);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ ret = rsnd_dai_connect(dma_mod, io, type);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ return rsnd_mod_get(dma);
}
-int rsnd_dma_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+int rsnd_dma_probe(struct rsnd_priv *priv)
{
+ struct platform_device *pdev = rsnd_priv_to_pdev(priv);
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_dma_ctrl *dmac;
struct resource *res;
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index 58f690900e6d..d45ffe496397 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -15,7 +15,6 @@
#define DVC_NAME "dvc"
struct rsnd_dvc {
- struct rsnd_dvc_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
struct rsnd_kctrl_cfg_m volume;
struct rsnd_kctrl_cfg_m mute;
@@ -24,6 +23,7 @@ struct rsnd_dvc {
struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */
};
+#define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id)
#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
#define rsnd_dvc_of_node(priv) \
of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc")
@@ -64,79 +64,142 @@ static const char * const dvc_ramp_rate[] = {
"0.125 dB/8192 steps", /* 10111 */
};
-static void rsnd_dvc_soft_reset(struct rsnd_mod *mod)
+static void rsnd_dvc_activation(struct rsnd_mod *mod)
{
rsnd_mod_write(mod, DVC_SWRSR, 0);
rsnd_mod_write(mod, DVC_SWRSR, 1);
}
-#define rsnd_dvc_initialize_lock(mod) __rsnd_dvc_initialize_lock(mod, 1)
-#define rsnd_dvc_initialize_unlock(mod) __rsnd_dvc_initialize_lock(mod, 0)
-static void __rsnd_dvc_initialize_lock(struct rsnd_mod *mod, u32 enable)
+static void rsnd_dvc_halt(struct rsnd_mod *mod)
{
- rsnd_mod_write(mod, DVC_DVUIR, enable);
+ rsnd_mod_write(mod, DVC_DVUIR, 1);
+ rsnd_mod_write(mod, DVC_SWRSR, 0);
}
-static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
+#define rsnd_dvc_get_vrpdr(dvc) (dvc->rup.val << 8 | dvc->rdown.val)
+#define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (dvc->volume.val[0] >> 13))
+
+static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
u32 val[RSND_DVC_CHANNELS];
- u32 dvucr = 0;
- u32 mute = 0;
int i;
- for (i = 0; i < dvc->mute.cfg.size; i++)
- mute |= (!!dvc->mute.cfg.val[i]) << i;
+ /* Enable Ramp */
+ if (dvc->ren.val)
+ for (i = 0; i < RSND_DVC_CHANNELS; i++)
+ val[i] = dvc->volume.cfg.max;
+ else
+ for (i = 0; i < RSND_DVC_CHANNELS; i++)
+ val[i] = dvc->volume.val[i];
- /* Disable DVC Register access */
- rsnd_mod_write(mod, DVC_DVUER, 0);
+ /* Enable Digital Volume */
+ rsnd_mod_write(mod, DVC_VOL0R, val[0]);
+ rsnd_mod_write(mod, DVC_VOL1R, val[1]);
+ rsnd_mod_write(mod, DVC_VOL2R, val[2]);
+ rsnd_mod_write(mod, DVC_VOL3R, val[3]);
+ rsnd_mod_write(mod, DVC_VOL4R, val[4]);
+ rsnd_mod_write(mod, DVC_VOL5R, val[5]);
+ rsnd_mod_write(mod, DVC_VOL6R, val[6]);
+ rsnd_mod_write(mod, DVC_VOL7R, val[7]);
+}
+
+static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod)
+{
+ struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+ u32 adinr = 0;
+ u32 dvucr = 0;
+ u32 vrctr = 0;
+ u32 vrpdr = 0;
+ u32 vrdbr = 0;
+
+ adinr = rsnd_get_adinr_bit(mod, io) |
+ rsnd_get_adinr_chan(mod, io);
+
+ /* Enable Digital Volume, Zero Cross Mute Mode */
+ dvucr |= 0x101;
/* Enable Ramp */
if (dvc->ren.val) {
dvucr |= 0x10;
- /* Digital Volume Max */
- for (i = 0; i < RSND_DVC_CHANNELS; i++)
- val[i] = dvc->volume.cfg.max;
-
- rsnd_mod_write(mod, DVC_VRCTR, 0xff);
- rsnd_mod_write(mod, DVC_VRPDR, dvc->rup.val << 8 |
- dvc->rdown.val);
/*
* FIXME !!
* use scale-downed Digital Volume
* as Volume Ramp
* 7F FFFF -> 3FF
*/
- rsnd_mod_write(mod, DVC_VRDBR,
- 0x3ff - (dvc->volume.val[0] >> 13));
-
- } else {
- for (i = 0; i < RSND_DVC_CHANNELS; i++)
- val[i] = dvc->volume.val[i];
+ vrctr = 0xff;
+ vrpdr = rsnd_dvc_get_vrpdr(dvc);
+ vrdbr = rsnd_dvc_get_vrdbr(dvc);
}
- /* Enable Digital Volume */
- dvucr |= 0x100;
- rsnd_mod_write(mod, DVC_VOL0R, val[0]);
- rsnd_mod_write(mod, DVC_VOL1R, val[1]);
+ /* Initialize operation */
+ rsnd_mod_write(mod, DVC_DVUIR, 1);
+
+ /* General Information */
+ rsnd_mod_write(mod, DVC_ADINR, adinr);
+ rsnd_mod_write(mod, DVC_DVUCR, dvucr);
+
+ /* Volume Ramp Parameter */
+ rsnd_mod_write(mod, DVC_VRCTR, vrctr);
+ rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
+ rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
+
+ /* Digital Volume Function Parameter */
+ rsnd_dvc_volume_parameter(io, mod);
+
+ /* cancel operation */
+ rsnd_mod_write(mod, DVC_DVUIR, 0);
+}
+
+static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod)
+{
+ struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+ u32 zcmcr = 0;
+ u32 vrpdr = 0;
+ u32 vrdbr = 0;
+ int i;
+
+ for (i = 0; i < dvc->mute.cfg.size; i++)
+ zcmcr |= (!!dvc->mute.cfg.val[i]) << i;
- /* Enable Mute */
- if (mute) {
- dvucr |= 0x1;
- rsnd_mod_write(mod, DVC_ZCMCR, mute);
+ if (dvc->ren.val) {
+ vrpdr = rsnd_dvc_get_vrpdr(dvc);
+ vrdbr = rsnd_dvc_get_vrdbr(dvc);
}
- rsnd_mod_write(mod, DVC_DVUCR, dvucr);
+ /* Disable DVC Register access */
+ rsnd_mod_write(mod, DVC_DVUER, 0);
+
+ /* Zero Cross Mute Function */
+ rsnd_mod_write(mod, DVC_ZCMCR, zcmcr);
+
+ /* Volume Ramp Function */
+ rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
+ rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
+ /* add DVC_VRWTR here */
+
+ /* Digital Volume Function Parameter */
+ rsnd_dvc_volume_parameter(io, mod);
/* Enable DVC Register access */
rsnd_mod_write(mod, DVC_DVUER, 1);
}
-static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
+static int rsnd_dvc_probe_(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ return rsnd_cmd_attach(io, rsnd_mod_id(mod));
+}
+
+static int rsnd_dvc_remove_(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
@@ -155,19 +218,12 @@ static int rsnd_dvc_init(struct rsnd_mod *mod,
{
rsnd_mod_power_on(mod);
- rsnd_dvc_soft_reset(mod);
-
- rsnd_dvc_initialize_lock(mod);
-
- rsnd_path_parse(priv, io);
+ rsnd_dvc_activation(mod);
- rsnd_mod_write(mod, DVC_ADINR, rsnd_get_adinr_bit(mod, io));
+ rsnd_dvc_volume_init(io, mod);
- /* ch0/ch1 Volume */
rsnd_dvc_volume_update(io, mod);
- rsnd_adg_set_cmd_timsel_gen2(mod, io);
-
return 0;
}
@@ -175,27 +231,9 @@ static int rsnd_dvc_quit(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
- rsnd_mod_power_off(mod);
+ rsnd_dvc_halt(mod);
- return 0;
-}
-
-static int rsnd_dvc_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_dvc_initialize_unlock(mod);
-
- rsnd_mod_write(mod, CMD_CTRL, 0x10);
-
- return 0;
-}
-
-static int rsnd_dvc_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_mod_write(mod, CMD_CTRL, 0);
+ rsnd_mod_power_off(mod);
return 0;
}
@@ -206,6 +244,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
int is_play = rsnd_io_is_play(io);
+ int slots = rsnd_get_slot(io);
int ret;
/* Volume */
@@ -213,7 +252,8 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
is_play ?
"DVC Out Playback Volume" : "DVC In Capture Volume",
rsnd_dvc_volume_update,
- &dvc->volume, 0x00800000 - 1);
+ &dvc->volume, slots,
+ 0x00800000 - 1);
if (ret < 0)
return ret;
@@ -222,7 +262,8 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
is_play ?
"DVC Out Mute Switch" : "DVC In Mute Switch",
rsnd_dvc_volume_update,
- &dvc->mute, 1);
+ &dvc->mute, slots,
+ 1);
if (ret < 0)
return ret;
@@ -269,11 +310,10 @@ static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io,
static struct rsnd_mod_ops rsnd_dvc_ops = {
.name = DVC_NAME,
.dma_req = rsnd_dvc_dma_req,
- .remove = rsnd_dvc_remove_gen2,
+ .probe = rsnd_dvc_probe_,
+ .remove = rsnd_dvc_remove_,
.init = rsnd_dvc_init,
.quit = rsnd_dvc_quit,
- .start = rsnd_dvc_start,
- .stop = rsnd_dvc_stop,
.pcm_new = rsnd_dvc_pcm_new,
};
@@ -282,50 +322,13 @@ struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
id = 0;
- return rsnd_mod_get((struct rsnd_dvc *)(priv->dvc) + id);
+ return rsnd_mod_get(rsnd_dvc_get(priv, id));
}
-static void rsnd_of_parse_dvc(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+int rsnd_dvc_probe(struct rsnd_priv *priv)
{
struct device_node *node;
- struct rsnd_dvc_platform_info *dvc_info;
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
- struct device *dev = &pdev->dev;
- int nr;
-
- if (!of_data)
- return;
-
- node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc");
- if (!node)
- return;
-
- nr = of_get_child_count(node);
- if (!nr)
- goto rsnd_of_parse_dvc_end;
-
- dvc_info = devm_kzalloc(dev,
- sizeof(struct rsnd_dvc_platform_info) * nr,
- GFP_KERNEL);
- if (!dvc_info) {
- dev_err(dev, "dvc info allocation error\n");
- goto rsnd_of_parse_dvc_end;
- }
-
- info->dvc_info = dvc_info;
- info->dvc_info_nr = nr;
-
-rsnd_of_parse_dvc_end:
- of_node_put(node);
-}
-
-int rsnd_dvc_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
-{
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
+ struct device_node *np;
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_dvc *dvc;
struct clk *clk;
@@ -336,40 +339,54 @@ int rsnd_dvc_probe(struct platform_device *pdev,
if (rsnd_is_gen1(priv))
return 0;
- rsnd_of_parse_dvc(pdev, of_data, priv);
+ node = rsnd_dvc_of_node(priv);
+ if (!node)
+ return 0; /* not used is not error */
- nr = info->dvc_info_nr;
- if (!nr)
- return 0;
+ nr = of_get_child_count(node);
+ if (!nr) {
+ ret = -EINVAL;
+ goto rsnd_dvc_probe_done;
+ }
dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL);
- if (!dvc)
- return -ENOMEM;
+ if (!dvc) {
+ ret = -ENOMEM;
+ goto rsnd_dvc_probe_done;
+ }
priv->dvc_nr = nr;
priv->dvc = dvc;
- for_each_rsnd_dvc(dvc, priv, i) {
+ i = 0;
+ ret = 0;
+ for_each_child_of_node(node, np) {
+ dvc = rsnd_dvc_get(priv, i);
+
snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d",
DVC_NAME, i);
clk = devm_clk_get(dev, name);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- dvc->info = &info->dvc_info[i];
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto rsnd_dvc_probe_done;
+ }
ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
clk, RSND_MOD_DVC, i);
if (ret)
- return ret;
+ goto rsnd_dvc_probe_done;
+
+ i++;
}
- return 0;
+rsnd_dvc_probe_done:
+ of_node_put(node);
+
+ return ret;
}
-void rsnd_dvc_remove(struct platform_device *pdev,
- struct rsnd_priv *priv)
+void rsnd_dvc_remove(struct rsnd_priv *priv)
{
struct rsnd_dvc *dvc;
int i;
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index edcf4cc2e84f..ea24247eba73 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -31,29 +31,33 @@ struct rsnd_gen {
/* RSND_REG_MAX base */
struct regmap_field *regs[RSND_REG_MAX];
+ const char *reg_name[RSND_REG_MAX];
};
#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
+#define rsnd_reg_name(gen, id) ((gen)->reg_name[id])
struct rsnd_regmap_field_conf {
int idx;
unsigned int reg_offset;
unsigned int id_offset;
+ const char *reg_name;
};
-#define RSND_REG_SET(id, offset, _id_offset) \
+#define RSND_REG_SET(id, offset, _id_offset, n) \
{ \
.idx = id, \
.reg_offset = offset, \
.id_offset = _id_offset, \
+ .reg_name = n, \
}
/* single address mapping */
#define RSND_GEN_S_REG(id, offset) \
- RSND_REG_SET(RSND_REG_##id, offset, 0)
+ RSND_REG_SET(RSND_REG_##id, offset, 0, #id)
/* multi address mapping */
#define RSND_GEN_M_REG(id, offset, _id_offset) \
- RSND_REG_SET(RSND_REG_##id, offset, _id_offset)
+ RSND_REG_SET(RSND_REG_##id, offset, _id_offset, #id)
/*
* basic function
@@ -83,8 +87,9 @@ u32 rsnd_read(struct rsnd_priv *priv,
regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
- dev_dbg(dev, "r %s[%d] - %4d : %08x\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod), reg, val);
+ dev_dbg(dev, "r %s[%d] - %-18s (%4d) : %08x\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod),
+ rsnd_reg_name(gen, reg), reg, val);
return val;
}
@@ -99,10 +104,11 @@ void rsnd_write(struct rsnd_priv *priv,
if (!rsnd_is_accessible_reg(priv, gen, reg))
return;
- dev_dbg(dev, "w %s[%d] - %4d : %08x\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data);
-
regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
+
+ dev_dbg(dev, "w %s[%d] - %-18s (%4d) : %08x\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod),
+ rsnd_reg_name(gen, reg), reg, data);
}
void rsnd_force_write(struct rsnd_priv *priv,
@@ -115,10 +121,11 @@ void rsnd_force_write(struct rsnd_priv *priv,
if (!rsnd_is_accessible_reg(priv, gen, reg))
return;
- dev_dbg(dev, "w %s[%d] - %4d : %08x\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data);
-
regmap_fields_force_write(gen->regs[reg], rsnd_mod_id(mod), data);
+
+ dev_dbg(dev, "w %s[%d] - %-18s (%4d) : %08x\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod),
+ rsnd_reg_name(gen, reg), reg, data);
}
void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
@@ -130,11 +137,13 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
if (!rsnd_is_accessible_reg(priv, gen, reg))
return;
- dev_dbg(dev, "b %s[%d] - %4d : %08x/%08x\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data, mask);
-
regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
mask, data);
+
+ dev_dbg(dev, "b %s[%d] - %-18s (%4d) : %08x/%08x\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod),
+ rsnd_reg_name(gen, reg), reg, data, mask);
+
}
phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id)
@@ -150,7 +159,7 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
int id_size,
int reg_id,
const char *name,
- struct rsnd_regmap_field_conf *conf,
+ const struct rsnd_regmap_field_conf *conf,
int conf_size)
{
struct platform_device *pdev = rsnd_priv_to_pdev(priv);
@@ -203,6 +212,7 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
/* RSND_REG_MAX base */
gen->regs[conf[i].idx] = regs;
+ gen->reg_name[conf[i].idx] = conf[i].reg_name;
}
return 0;
@@ -211,25 +221,31 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
/*
* Gen2
*/
-static int rsnd_gen2_probe(struct platform_device *pdev,
- struct rsnd_priv *priv)
+static int rsnd_gen2_probe(struct rsnd_priv *priv)
{
- struct rsnd_regmap_field_conf conf_ssiu[] = {
+ const static struct rsnd_regmap_field_conf conf_ssiu[] = {
RSND_GEN_S_REG(SSI_MODE0, 0x800),
RSND_GEN_S_REG(SSI_MODE1, 0x804),
+ RSND_GEN_S_REG(SSI_MODE2, 0x808),
+ RSND_GEN_S_REG(SSI_CONTROL, 0x810),
+
/* FIXME: it needs SSI_MODE2/3 in the future */
RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80),
RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80),
RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8, 0x80),
+ RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80),
RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80),
RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
};
- struct rsnd_regmap_field_conf conf_scu[] = {
- RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20),
+
+ const static struct rsnd_regmap_field_conf conf_scu[] = {
+ RSND_GEN_M_REG(SRC_I_BUSIF_MODE,0x0, 0x20),
+ RSND_GEN_M_REG(SRC_O_BUSIF_MODE,0x4, 0x20),
RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20),
RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20),
+ RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188, 0x20),
RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20),
RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20),
RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8),
@@ -266,9 +282,15 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100),
RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100),
RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100),
+ RSND_GEN_M_REG(DVC_VOL2R, 0xe30, 0x100),
+ RSND_GEN_M_REG(DVC_VOL3R, 0xe34, 0x100),
+ RSND_GEN_M_REG(DVC_VOL4R, 0xe38, 0x100),
+ RSND_GEN_M_REG(DVC_VOL5R, 0xe3c, 0x100),
+ RSND_GEN_M_REG(DVC_VOL6R, 0xe40, 0x100),
+ RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100),
RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100),
};
- struct rsnd_regmap_field_conf conf_adg[] = {
+ const static struct rsnd_regmap_field_conf conf_adg[] = {
RSND_GEN_S_REG(BRRA, 0x00),
RSND_GEN_S_REG(BRRB, 0x04),
RSND_GEN_S_REG(SSICKR, 0x08),
@@ -288,7 +310,7 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58),
RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c),
};
- struct rsnd_regmap_field_conf conf_ssi[] = {
+ const static struct rsnd_regmap_field_conf conf_ssi[] = {
RSND_GEN_M_REG(SSICR, 0x00, 0x40),
RSND_GEN_M_REG(SSISR, 0x04, 0x40),
RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
@@ -317,65 +339,30 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
* Gen1
*/
-static int rsnd_gen1_probe(struct platform_device *pdev,
- struct rsnd_priv *priv)
+static int rsnd_gen1_probe(struct rsnd_priv *priv)
{
- struct rsnd_regmap_field_conf conf_sru[] = {
- RSND_GEN_S_REG(SRC_ROUTE_SEL, 0x00),
- RSND_GEN_S_REG(SRC_TMG_SEL0, 0x08),
- RSND_GEN_S_REG(SRC_TMG_SEL1, 0x0c),
- RSND_GEN_S_REG(SRC_TMG_SEL2, 0x10),
- RSND_GEN_S_REG(SRC_ROUTE_CTRL, 0xc0),
- RSND_GEN_S_REG(SSI_MODE0, 0xD0),
- RSND_GEN_S_REG(SSI_MODE1, 0xD4),
- RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x20, 0x4),
- RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0x50, 0x8),
- RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40),
- RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40),
- RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40),
- RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40),
- RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40),
- RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
- RSND_GEN_M_REG(SRC_MNFSR, 0x228, 0x40),
- /*
- * ADD US
- *
- * SRC_STATUS
- * SRC_INT_EN
- * SCU_SYS_STATUS0
- * SCU_SYS_STATUS1
- * SCU_SYS_INT_EN0
- * SCU_SYS_INT_EN1
- */
- };
- struct rsnd_regmap_field_conf conf_adg[] = {
+ const static struct rsnd_regmap_field_conf conf_adg[] = {
RSND_GEN_S_REG(BRRA, 0x00),
RSND_GEN_S_REG(BRRB, 0x04),
RSND_GEN_S_REG(SSICKR, 0x08),
RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
- RSND_GEN_S_REG(AUDIO_CLK_SEL3, 0x18),
- RSND_GEN_S_REG(AUDIO_CLK_SEL4, 0x1c),
- RSND_GEN_S_REG(AUDIO_CLK_SEL5, 0x20),
};
- struct rsnd_regmap_field_conf conf_ssi[] = {
+ const static struct rsnd_regmap_field_conf conf_ssi[] = {
RSND_GEN_M_REG(SSICR, 0x00, 0x40),
RSND_GEN_M_REG(SSISR, 0x04, 0x40),
RSND_GEN_M_REG(SSITDR, 0x08, 0x40),
RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40),
RSND_GEN_M_REG(SSIWSR, 0x20, 0x40),
};
- int ret_sru;
int ret_adg;
int ret_ssi;
- ret_sru = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU, "sru", conf_sru);
ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, "adg", conf_adg);
ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_ssi);
- if (ret_sru < 0 ||
- ret_adg < 0 ||
+ if (ret_adg < 0 ||
ret_ssi < 0)
- return ret_sru | ret_adg | ret_ssi;
+ return ret_adg | ret_ssi;
return 0;
}
@@ -383,28 +370,12 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
/*
* Gen
*/
-static void rsnd_of_parse_gen(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
-{
- struct rcar_snd_info *info = priv->info;
-
- if (!of_data)
- return;
-
- info->flags = of_data->flags;
-}
-
-int rsnd_gen_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+int rsnd_gen_probe(struct rsnd_priv *priv)
{
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_gen *gen;
int ret;
- rsnd_of_parse_gen(pdev, of_data, priv);
-
gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
if (!gen) {
dev_err(dev, "GEN allocate failed\n");
@@ -415,9 +386,9 @@ int rsnd_gen_probe(struct platform_device *pdev,
ret = -ENODEV;
if (rsnd_is_gen1(priv))
- ret = rsnd_gen1_probe(pdev, priv);
+ ret = rsnd_gen1_probe(priv);
else if (rsnd_is_gen2(priv))
- ret = rsnd_gen2_probe(pdev, priv);
+ ret = rsnd_gen2_probe(priv);
if (ret < 0)
dev_err(dev, "unknown generation R-Car sound device\n");
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c
index 953dd0be9b60..65542b6a89e9 100644
--- a/sound/soc/sh/rcar/mix.c
+++ b/sound/soc/sh/rcar/mix.c
@@ -13,10 +13,10 @@
#define MIX_NAME "mix"
struct rsnd_mix {
- struct rsnd_mix_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
};
+#define rsnd_mix_get(priv, id) ((struct rsnd_mix *)(priv->mix) + id)
#define rsnd_mix_nr(priv) ((priv)->mix_nr)
#define for_each_rsnd_mix(pos, priv, i) \
for ((i) = 0; \
@@ -24,58 +24,77 @@ struct rsnd_mix {
((pos) = (struct rsnd_mix *)(priv)->mix + i); \
i++)
-
-static void rsnd_mix_soft_reset(struct rsnd_mod *mod)
+static void rsnd_mix_activation(struct rsnd_mod *mod)
{
rsnd_mod_write(mod, MIX_SWRSR, 0);
rsnd_mod_write(mod, MIX_SWRSR, 1);
}
-#define rsnd_mix_initialize_lock(mod) __rsnd_mix_initialize_lock(mod, 1)
-#define rsnd_mix_initialize_unlock(mod) __rsnd_mix_initialize_lock(mod, 0)
-static void __rsnd_mix_initialize_lock(struct rsnd_mod *mod, u32 enable)
+static void rsnd_mix_halt(struct rsnd_mod *mod)
+{
+ rsnd_mod_write(mod, MIX_MIXIR, 1);
+ rsnd_mod_write(mod, MIX_SWRSR, 0);
+}
+
+static void rsnd_mix_volume_parameter(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod)
{
- rsnd_mod_write(mod, MIX_MIXIR, enable);
+ rsnd_mod_write(mod, MIX_MDBAR, 0);
+ rsnd_mod_write(mod, MIX_MDBBR, 0);
+ rsnd_mod_write(mod, MIX_MDBCR, 0);
+ rsnd_mod_write(mod, MIX_MDBDR, 0);
+}
+
+static void rsnd_mix_volume_init(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod)
+{
+ rsnd_mod_write(mod, MIX_MIXIR, 1);
+
+ /* General Information */
+ rsnd_mod_write(mod, MIX_ADINR, rsnd_get_adinr_chan(mod, io));
+
+ /* volume step */
+ rsnd_mod_write(mod, MIX_MIXMR, 0);
+ rsnd_mod_write(mod, MIX_MVPDR, 0);
+
+ /* common volume parameter */
+ rsnd_mix_volume_parameter(io, mod);
+
+ rsnd_mod_write(mod, MIX_MIXIR, 0);
}
static void rsnd_mix_volume_update(struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
-
/* Disable MIX dB setting */
rsnd_mod_write(mod, MIX_MDBER, 0);
- rsnd_mod_write(mod, MIX_MDBAR, 0);
- rsnd_mod_write(mod, MIX_MDBBR, 0);
- rsnd_mod_write(mod, MIX_MDBCR, 0);
- rsnd_mod_write(mod, MIX_MDBDR, 0);
+ /* common volume parameter */
+ rsnd_mix_volume_parameter(io, mod);
/* Enable MIX dB setting */
rsnd_mod_write(mod, MIX_MDBER, 1);
}
+static int rsnd_mix_probe_(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ return rsnd_cmd_attach(io, rsnd_mod_id(mod));
+}
+
static int rsnd_mix_init(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
rsnd_mod_power_on(mod);
- rsnd_mix_soft_reset(mod);
-
- rsnd_mix_initialize_lock(mod);
-
- rsnd_mod_write(mod, MIX_ADINR, rsnd_get_adinr_chan(mod, io));
-
- rsnd_path_parse(priv, io);
+ rsnd_mix_activation(mod);
- /* volume step */
- rsnd_mod_write(mod, MIX_MIXMR, 0);
- rsnd_mod_write(mod, MIX_MVPDR, 0);
+ rsnd_mix_volume_init(io, mod);
rsnd_mix_volume_update(io, mod);
- rsnd_mix_initialize_unlock(mod);
-
return 0;
}
@@ -83,6 +102,8 @@ static int rsnd_mix_quit(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
+ rsnd_mix_halt(mod);
+
rsnd_mod_power_off(mod);
return 0;
@@ -90,6 +111,7 @@ static int rsnd_mix_quit(struct rsnd_mod *mod,
static struct rsnd_mod_ops rsnd_mix_ops = {
.name = MIX_NAME,
+ .probe = rsnd_mix_probe_,
.init = rsnd_mix_init,
.quit = rsnd_mix_quit,
};
@@ -99,51 +121,13 @@ struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id)
if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
id = 0;
- return rsnd_mod_get((struct rsnd_mix *)(priv->mix) + id);
+ return rsnd_mod_get(rsnd_mix_get(priv, id));
}
-static void rsnd_of_parse_mix(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+int rsnd_mix_probe(struct rsnd_priv *priv)
{
struct device_node *node;
- struct rsnd_mix_platform_info *mix_info;
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
- struct device *dev = &pdev->dev;
- int nr;
-
- if (!of_data)
- return;
-
- node = of_get_child_by_name(dev->of_node, "rcar_sound,mix");
- if (!node)
- return;
-
- nr = of_get_child_count(node);
- if (!nr)
- goto rsnd_of_parse_mix_end;
-
- mix_info = devm_kzalloc(dev,
- sizeof(struct rsnd_mix_platform_info) * nr,
- GFP_KERNEL);
- if (!mix_info) {
- dev_err(dev, "mix info allocation error\n");
- goto rsnd_of_parse_mix_end;
- }
-
- info->mix_info = mix_info;
- info->mix_info_nr = nr;
-
-rsnd_of_parse_mix_end:
- of_node_put(node);
-
-}
-
-int rsnd_mix_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
-{
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
+ struct device_node *np;
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_mix *mix;
struct clk *clk;
@@ -154,40 +138,54 @@ int rsnd_mix_probe(struct platform_device *pdev,
if (rsnd_is_gen1(priv))
return 0;
- rsnd_of_parse_mix(pdev, of_data, priv);
+ node = rsnd_mix_of_node(priv);
+ if (!node)
+ return 0; /* not used is not error */
- nr = info->mix_info_nr;
- if (!nr)
- return 0;
+ nr = of_get_child_count(node);
+ if (!nr) {
+ ret = -EINVAL;
+ goto rsnd_mix_probe_done;
+ }
mix = devm_kzalloc(dev, sizeof(*mix) * nr, GFP_KERNEL);
- if (!mix)
- return -ENOMEM;
+ if (!mix) {
+ ret = -ENOMEM;
+ goto rsnd_mix_probe_done;
+ }
priv->mix_nr = nr;
priv->mix = mix;
- for_each_rsnd_mix(mix, priv, i) {
+ i = 0;
+ ret = 0;
+ for_each_child_of_node(node, np) {
+ mix = rsnd_mix_get(priv, i);
+
snprintf(name, MIX_NAME_SIZE, "%s.%d",
MIX_NAME, i);
clk = devm_clk_get(dev, name);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- mix->info = &info->mix_info[i];
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto rsnd_mix_probe_done;
+ }
ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops,
clk, RSND_MOD_MIX, i);
if (ret)
- return ret;
+ goto rsnd_mix_probe_done;
+
+ i++;
}
- return 0;
+rsnd_mix_probe_done:
+ of_node_put(node);
+
+ return ret;
}
-void rsnd_mix_remove(struct platform_device *pdev,
- struct rsnd_priv *priv)
+void rsnd_mix_remove(struct rsnd_priv *priv)
{
struct rsnd_mix *mix;
int i;
diff --git a/sound/soc/sh/rcar/rcar_snd.h b/sound/soc/sh/rcar/rcar_snd.h
deleted file mode 100644
index d8e33d38da43..000000000000
--- a/sound/soc/sh/rcar/rcar_snd.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Renesas R-Car SRU/SCU/SSIU/SSI support
- *
- * Copyright (C) 2013 Renesas Solutions Corp.
- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef RCAR_SND_H
-#define RCAR_SND_H
-
-
-#define RSND_GEN1_SRU 0
-#define RSND_GEN1_ADG 1
-#define RSND_GEN1_SSI 2
-
-#define RSND_GEN2_SCU 0
-#define RSND_GEN2_ADG 1
-#define RSND_GEN2_SSIU 2
-#define RSND_GEN2_SSI 3
-
-#define RSND_BASE_MAX 4
-
-/*
- * flags
- *
- * 0xAB000000
- *
- * A : clock sharing settings
- * B : SSI direction
- */
-#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
-#define RSND_SSI_NO_BUSIF (1 << 30) /* SSI+DMA without BUSIF */
-
-#define RSND_SSI(_dma_id, _irq, _flags) \
-{ .dma_id = _dma_id, .irq = _irq, .flags = _flags }
-#define RSND_SSI_UNUSED \
-{ .dma_id = -1, .irq = -1, .flags = 0 }
-
-struct rsnd_ssi_platform_info {
- int dma_id;
- int irq;
- u32 flags;
-};
-
-#define RSND_SRC(rate, _dma_id) \
-{ .convert_rate = rate, .dma_id = _dma_id, }
-#define RSND_SRC_UNUSED \
-{ .convert_rate = 0, .dma_id = -1, }
-
-struct rsnd_src_platform_info {
- u32 convert_rate; /* sampling rate convert */
- int dma_id; /* for Gen2 SCU */
- int irq;
-};
-
-/*
- * flags
- */
-struct rsnd_ctu_platform_info {
- u32 flags;
-};
-
-struct rsnd_mix_platform_info {
- u32 flags;
-};
-
-struct rsnd_dvc_platform_info {
- u32 flags;
-};
-
-struct rsnd_dai_path_info {
- struct rsnd_ssi_platform_info *ssi;
- struct rsnd_src_platform_info *src;
- struct rsnd_ctu_platform_info *ctu;
- struct rsnd_mix_platform_info *mix;
- struct rsnd_dvc_platform_info *dvc;
-};
-
-struct rsnd_dai_platform_info {
- struct rsnd_dai_path_info playback;
- struct rsnd_dai_path_info capture;
-};
-
-/*
- * flags
- *
- * 0x0000000A
- *
- * A : generation
- */
-#define RSND_GEN_MASK (0xF << 0)
-#define RSND_GEN1 (1 << 0) /* fixme */
-#define RSND_GEN2 (2 << 0) /* fixme */
-
-struct rcar_snd_info {
- u32 flags;
- struct rsnd_ssi_platform_info *ssi_info;
- int ssi_info_nr;
- struct rsnd_src_platform_info *src_info;
- int src_info_nr;
- struct rsnd_ctu_platform_info *ctu_info;
- int ctu_info_nr;
- struct rsnd_mix_platform_info *mix_info;
- int mix_info_nr;
- struct rsnd_dvc_platform_info *dvc_info;
- int dvc_info_nr;
- struct rsnd_dai_platform_info *dai_info;
- int dai_info_nr;
- int (*start)(int id);
- int (*stop)(int id);
-};
-
-#endif
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 085329878525..317dd793149a 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -24,7 +24,16 @@
#include <sound/soc.h>
#include <sound/pcm_params.h>
-#include "rcar_snd.h"
+#define RSND_GEN1_SRU 0
+#define RSND_GEN1_ADG 1
+#define RSND_GEN1_SSI 2
+
+#define RSND_GEN2_SCU 0
+#define RSND_GEN2_ADG 1
+#define RSND_GEN2_SSIU 2
+#define RSND_GEN2_SSI 3
+
+#define RSND_BASE_MAX 4
/*
* pseudo register
@@ -34,10 +43,19 @@
* see gen1/gen2 for detail
*/
enum rsnd_reg {
- /* SRU/SCU/SSIU */
+ /* SCU (SRC/SSIU/MIX/CTU/DVC) */
+ RSND_REG_SSI_MODE, /* Gen2 only */
RSND_REG_SSI_MODE0,
RSND_REG_SSI_MODE1,
- RSND_REG_SRC_BUSIF_MODE,
+ RSND_REG_SSI_MODE2,
+ RSND_REG_SSI_CONTROL,
+ RSND_REG_SSI_CTRL, /* Gen2 only */
+ RSND_REG_SSI_BUSIF_MODE, /* Gen2 only */
+ RSND_REG_SSI_BUSIF_ADINR, /* Gen2 only */
+ RSND_REG_SSI_BUSIF_DALIGN, /* Gen2 only */
+ RSND_REG_SSI_INT_ENABLE, /* Gen2 only */
+ RSND_REG_SRC_I_BUSIF_MODE,
+ RSND_REG_SRC_O_BUSIF_MODE,
RSND_REG_SRC_ROUTE_MODE0,
RSND_REG_SRC_SWRSR,
RSND_REG_SRC_SRCIR,
@@ -45,9 +63,29 @@ enum rsnd_reg {
RSND_REG_SRC_IFSCR,
RSND_REG_SRC_IFSVR,
RSND_REG_SRC_SRCCR,
+ RSND_REG_SRC_CTRL, /* Gen2 only */
+ RSND_REG_SRC_BSDSR, /* Gen2 only */
+ RSND_REG_SRC_BSISR, /* Gen2 only */
+ RSND_REG_SRC_INT_ENABLE0, /* Gen2 only */
+ RSND_REG_SRC_BUSIF_DALIGN, /* Gen2 only */
+ RSND_REG_SRCIN_TIMSEL0, /* Gen2 only */
+ RSND_REG_SRCIN_TIMSEL1, /* Gen2 only */
+ RSND_REG_SRCIN_TIMSEL2, /* Gen2 only */
+ RSND_REG_SRCIN_TIMSEL3, /* Gen2 only */
+ RSND_REG_SRCIN_TIMSEL4, /* Gen2 only */
+ RSND_REG_SRCOUT_TIMSEL0, /* Gen2 only */
+ RSND_REG_SRCOUT_TIMSEL1, /* Gen2 only */
+ RSND_REG_SRCOUT_TIMSEL2, /* Gen2 only */
+ RSND_REG_SRCOUT_TIMSEL3, /* Gen2 only */
+ RSND_REG_SRCOUT_TIMSEL4, /* Gen2 only */
RSND_REG_SCU_SYS_STATUS0,
+ RSND_REG_SCU_SYS_STATUS1, /* Gen2 only */
RSND_REG_SCU_SYS_INT_EN0,
+ RSND_REG_SCU_SYS_INT_EN1, /* Gen2 only */
+ RSND_REG_CMD_CTRL, /* Gen2 only */
+ RSND_REG_CMD_BUSIF_DALIGN, /* Gen2 only */
RSND_REG_CMD_ROUTE_SLCT,
+ RSND_REG_CMDOUT_TIMSEL, /* Gen2 only */
RSND_REG_CTU_CTUIR,
RSND_REG_CTU_ADINR,
RSND_REG_MIX_SWRSR,
@@ -67,14 +105,25 @@ enum rsnd_reg {
RSND_REG_DVC_ZCMCR,
RSND_REG_DVC_VOL0R,
RSND_REG_DVC_VOL1R,
+ RSND_REG_DVC_VOL2R,
+ RSND_REG_DVC_VOL3R,
+ RSND_REG_DVC_VOL4R,
+ RSND_REG_DVC_VOL5R,
+ RSND_REG_DVC_VOL6R,
+ RSND_REG_DVC_VOL7R,
RSND_REG_DVC_DVUER,
+ RSND_REG_DVC_VRCTR, /* Gen2 only */
+ RSND_REG_DVC_VRPDR, /* Gen2 only */
+ RSND_REG_DVC_VRDBR, /* Gen2 only */
/* ADG */
RSND_REG_BRRA,
RSND_REG_BRRB,
RSND_REG_SSICKR,
+ RSND_REG_DIV_EN, /* Gen2 only */
RSND_REG_AUDIO_CLK_SEL0,
RSND_REG_AUDIO_CLK_SEL1,
+ RSND_REG_AUDIO_CLK_SEL2, /* Gen2 only */
/* SSI */
RSND_REG_SSICR,
@@ -83,83 +132,9 @@ enum rsnd_reg {
RSND_REG_SSIRDR,
RSND_REG_SSIWSR,
- /* SHARE see below */
- RSND_REG_SHARE01,
- RSND_REG_SHARE02,
- RSND_REG_SHARE03,
- RSND_REG_SHARE04,
- RSND_REG_SHARE05,
- RSND_REG_SHARE06,
- RSND_REG_SHARE07,
- RSND_REG_SHARE08,
- RSND_REG_SHARE09,
- RSND_REG_SHARE10,
- RSND_REG_SHARE11,
- RSND_REG_SHARE12,
- RSND_REG_SHARE13,
- RSND_REG_SHARE14,
- RSND_REG_SHARE15,
- RSND_REG_SHARE16,
- RSND_REG_SHARE17,
- RSND_REG_SHARE18,
- RSND_REG_SHARE19,
- RSND_REG_SHARE20,
- RSND_REG_SHARE21,
- RSND_REG_SHARE22,
- RSND_REG_SHARE23,
- RSND_REG_SHARE24,
- RSND_REG_SHARE25,
- RSND_REG_SHARE26,
- RSND_REG_SHARE27,
- RSND_REG_SHARE28,
- RSND_REG_SHARE29,
-
RSND_REG_MAX,
};
-/* Gen1 only */
-#define RSND_REG_SRC_ROUTE_SEL RSND_REG_SHARE01
-#define RSND_REG_SRC_TMG_SEL0 RSND_REG_SHARE02
-#define RSND_REG_SRC_TMG_SEL1 RSND_REG_SHARE03
-#define RSND_REG_SRC_TMG_SEL2 RSND_REG_SHARE04
-#define RSND_REG_SRC_ROUTE_CTRL RSND_REG_SHARE05
-#define RSND_REG_SRC_MNFSR RSND_REG_SHARE06
-#define RSND_REG_AUDIO_CLK_SEL3 RSND_REG_SHARE07
-#define RSND_REG_AUDIO_CLK_SEL4 RSND_REG_SHARE08
-#define RSND_REG_AUDIO_CLK_SEL5 RSND_REG_SHARE09
-
-/* Gen2 only */
-#define RSND_REG_SRC_CTRL RSND_REG_SHARE01
-#define RSND_REG_SSI_CTRL RSND_REG_SHARE02
-#define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03
-#define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04
-#define RSND_REG_SSI_INT_ENABLE RSND_REG_SHARE05
-#define RSND_REG_SRC_BSDSR RSND_REG_SHARE06
-#define RSND_REG_SRC_BSISR RSND_REG_SHARE07
-#define RSND_REG_DIV_EN RSND_REG_SHARE08
-#define RSND_REG_SRCIN_TIMSEL0 RSND_REG_SHARE09
-#define RSND_REG_SRCIN_TIMSEL1 RSND_REG_SHARE10
-#define RSND_REG_SRCIN_TIMSEL2 RSND_REG_SHARE11
-#define RSND_REG_SRCIN_TIMSEL3 RSND_REG_SHARE12
-#define RSND_REG_SRCIN_TIMSEL4 RSND_REG_SHARE13
-#define RSND_REG_SRCOUT_TIMSEL0 RSND_REG_SHARE14
-#define RSND_REG_SRCOUT_TIMSEL1 RSND_REG_SHARE15
-#define RSND_REG_SRCOUT_TIMSEL2 RSND_REG_SHARE16
-#define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17
-#define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18
-#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19
-#define RSND_REG_CMD_CTRL RSND_REG_SHARE20
-#define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21
-#define RSND_REG_SSI_BUSIF_DALIGN RSND_REG_SHARE22
-#define RSND_REG_DVC_VRCTR RSND_REG_SHARE23
-#define RSND_REG_DVC_VRPDR RSND_REG_SHARE24
-#define RSND_REG_DVC_VRDBR RSND_REG_SHARE25
-#define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26
-#define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27
-#define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28
-#define RSND_REG_SRC_BUSIF_DALIGN RSND_REG_SHARE29
-
-struct rsnd_of_data;
struct rsnd_priv;
struct rsnd_mod;
struct rsnd_dai;
@@ -187,43 +162,13 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
-void rsnd_path_parse(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io);
/*
* R-Car DMA
*/
-struct rsnd_dma;
-
-struct rsnd_dmaen {
- struct dma_chan *chan;
-};
-
-struct rsnd_dmapp {
- int dmapp_id;
- u32 chcr;
-};
-
-struct rsnd_dma {
- struct rsnd_dma_ops *ops;
- dma_addr_t src_addr;
- dma_addr_t dst_addr;
- union {
- struct rsnd_dmaen en;
- struct rsnd_dmapp pp;
- } dma;
-};
-#define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en)
-#define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp)
-#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
-
-void rsnd_dma_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
-void rsnd_dma_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
-int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id);
-void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
-int rsnd_dma_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv);
+struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod, int id);
+int rsnd_dma_probe(struct rsnd_priv *priv);
struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
struct rsnd_mod *mod, char *name);
@@ -231,11 +176,19 @@ struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
* R-Car sound mod
*/
enum rsnd_mod_type {
- RSND_MOD_DVC = 0,
+ RSND_MOD_AUDMAPP,
+ RSND_MOD_AUDMA,
+ RSND_MOD_DVC,
RSND_MOD_MIX,
RSND_MOD_CTU,
+ RSND_MOD_CMD,
RSND_MOD_SRC,
+ RSND_MOD_SSIM3, /* SSI multi 3 */
+ RSND_MOD_SSIM2, /* SSI multi 2 */
+ RSND_MOD_SSIM1, /* SSI multi 1 */
+ RSND_MOD_SSIP, /* SSI parent */
RSND_MOD_SSI,
+ RSND_MOD_SSIU,
RSND_MOD_MAX,
};
@@ -278,10 +231,8 @@ struct rsnd_mod {
int id;
enum rsnd_mod_type type;
struct rsnd_mod_ops *ops;
- struct rsnd_dma dma;
struct rsnd_priv *priv;
struct clk *clk;
- u32 status;
};
/*
* status
@@ -328,7 +279,6 @@ struct rsnd_mod {
#define __rsnd_mod_call_hw_params 0
#define rsnd_mod_to_priv(mod) ((mod)->priv)
-#define rsnd_mod_to_dma(mod) (&(mod)->dma)
#define rsnd_mod_id(mod) ((mod) ? (mod)->id : -1)
#define rsnd_mod_power_on(mod) clk_enable((mod)->clk)
#define rsnd_mod_power_off(mod) clk_disable((mod)->clk)
@@ -347,6 +297,17 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
void rsnd_mod_interrupt(struct rsnd_mod *mod,
void (*callback)(struct rsnd_mod *mod,
struct rsnd_dai_stream *io));
+void rsnd_parse_connect_common(struct rsnd_dai *rdai,
+ struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id),
+ struct device_node *node,
+ struct device_node *playback,
+ struct device_node *capture);
+
+void rsnd_set_slot(struct rsnd_dai *rdai,
+ int slots, int slots_total);
+int rsnd_get_slot(struct rsnd_dai_stream *io);
+int rsnd_get_slot_width(struct rsnd_dai_stream *io);
+int rsnd_get_slot_num(struct rsnd_dai_stream *io);
/*
* R-Car sound DAI
@@ -358,6 +319,7 @@ struct rsnd_dai_stream {
struct rsnd_mod *mod[RSND_MOD_MAX];
struct rsnd_dai_path_info *info; /* rcar_snd.h */
struct rsnd_dai *rdai;
+ u32 mod_status[RSND_MOD_MAX];
int byte_pos;
int period_pos;
int byte_per_period;
@@ -365,10 +327,12 @@ struct rsnd_dai_stream {
};
#define rsnd_io_to_mod(io, i) ((i) < RSND_MOD_MAX ? (io)->mod[(i)] : NULL)
#define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI)
+#define rsnd_io_to_mod_ssip(io) rsnd_io_to_mod((io), RSND_MOD_SSIP)
#define rsnd_io_to_mod_src(io) rsnd_io_to_mod((io), RSND_MOD_SRC)
#define rsnd_io_to_mod_ctu(io) rsnd_io_to_mod((io), RSND_MOD_CTU)
#define rsnd_io_to_mod_mix(io) rsnd_io_to_mod((io), RSND_MOD_MIX)
#define rsnd_io_to_mod_dvc(io) rsnd_io_to_mod((io), RSND_MOD_DVC)
+#define rsnd_io_to_mod_cmd(io) rsnd_io_to_mod((io), RSND_MOD_CMD)
#define rsnd_io_to_rdai(io) ((io)->rdai)
#define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io)))
#define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io)
@@ -382,6 +346,9 @@ struct rsnd_dai {
struct rsnd_dai_stream capture;
struct rsnd_priv *priv;
+ int slots;
+ int slots_num;
+
unsigned int clk_master:1;
unsigned int bit_clk_inv:1;
unsigned int frm_clk_inv:1;
@@ -403,33 +370,28 @@ struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id);
bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io);
int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
+int rsnd_dai_connect(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ enum rsnd_mod_type type);
+#define rsnd_dai_of_node(priv) \
+ of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dai")
/*
* R-Car Gen1/Gen2
*/
-int rsnd_gen_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv);
+int rsnd_gen_probe(struct rsnd_priv *priv);
void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
struct rsnd_mod *mod,
enum rsnd_reg reg);
phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id);
-#define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
-#define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
-
/*
* R-Car ADG
*/
int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod);
int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate);
-int rsnd_adg_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv);
-int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- unsigned int src_rate,
- unsigned int dst_rate);
+int rsnd_adg_probe(struct rsnd_priv *priv);
+void rsnd_adg_remove(struct rsnd_priv *priv);
int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
unsigned int src_rate,
@@ -442,15 +404,14 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
/*
* R-Car sound priv
*/
-struct rsnd_of_data {
- u32 flags;
-};
-
struct rsnd_priv {
struct platform_device *pdev;
- struct rcar_snd_info *info;
spinlock_t lock;
+ unsigned long flags;
+#define RSND_GEN_MASK (0xF << 0)
+#define RSND_GEN1 (1 << 0)
+#define RSND_GEN2 (2 << 0)
/*
* below value will be filled on rsnd_gen_probe()
@@ -474,6 +435,12 @@ struct rsnd_priv {
int ssi_nr;
/*
+ * below value will be filled on rsnd_ssiu_probe()
+ */
+ void *ssiu;
+ int ssiu_nr;
+
+ /*
* below value will be filled on rsnd_src_probe()
*/
void *src;
@@ -498,6 +465,12 @@ struct rsnd_priv {
int dvc_nr;
/*
+ * below value will be filled on rsnd_cmd_probe()
+ */
+ void *cmd;
+ int cmd_nr;
+
+ /*
* below value will be filled on rsnd_dai_probe()
*/
struct snd_soc_dai_driver *daidrv;
@@ -507,7 +480,9 @@ struct rsnd_priv {
#define rsnd_priv_to_pdev(priv) ((priv)->pdev)
#define rsnd_priv_to_dev(priv) (&(rsnd_priv_to_pdev(priv)->dev))
-#define rsnd_priv_to_info(priv) ((priv)->info)
+
+#define rsnd_is_gen1(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN1)
+#define rsnd_is_gen2(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN2)
/*
* rsnd_kctrl
@@ -523,7 +498,7 @@ struct rsnd_kctrl_cfg {
struct snd_kcontrol *kctrl;
};
-#define RSND_DVC_CHANNELS 2
+#define RSND_DVC_CHANNELS 8
struct rsnd_kctrl_cfg_m {
struct rsnd_kctrl_cfg cfg;
u32 val[RSND_DVC_CHANNELS];
@@ -544,6 +519,7 @@ int rsnd_kctrl_new_m(struct rsnd_mod *mod,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
struct rsnd_kctrl_cfg_m *_cfg,
+ int ch_size,
u32 max);
int rsnd_kctrl_new_s(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
@@ -566,70 +542,93 @@ int rsnd_kctrl_new_e(struct rsnd_mod *mod,
/*
* R-Car SSI
*/
-int rsnd_ssi_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv);
-void rsnd_ssi_remove(struct platform_device *pdev,
- struct rsnd_priv *priv);
+int rsnd_ssi_probe(struct rsnd_priv *priv);
+void rsnd_ssi_remove(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io);
+u32 rsnd_ssi_multi_slaves(struct rsnd_dai_stream *io);
#define rsnd_ssi_is_pin_sharing(io) \
__rsnd_ssi_is_pin_sharing(rsnd_io_to_mod_ssi(io))
int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
+#define rsnd_ssi_of_node(priv) \
+ of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ssi")
+void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
+ struct device_node *playback,
+ struct device_node *capture);
+
+/*
+ * R-Car SSIU
+ */
+int rsnd_ssiu_attach(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod);
+int rsnd_ssiu_probe(struct rsnd_priv *priv);
+void rsnd_ssiu_remove(struct rsnd_priv *priv);
+
/*
* R-Car SRC
*/
-int rsnd_src_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv);
-void rsnd_src_remove(struct platform_device *pdev,
- struct rsnd_priv *priv);
+int rsnd_src_probe(struct rsnd_priv *priv);
+void rsnd_src_remove(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
struct rsnd_dai_stream *io,
struct snd_pcm_runtime *runtime);
-int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
- struct rsnd_dai_stream *io,
- int use_busif);
-int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
- struct rsnd_dai_stream *io);
-int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod);
-int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod);
+#define rsnd_src_of_node(priv) \
+ of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src")
+#define rsnd_parse_connect_src(rdai, playback, capture) \
+ rsnd_parse_connect_common(rdai, rsnd_src_mod_get, \
+ rsnd_src_of_node(rsnd_rdai_to_priv(rdai)), \
+ playback, capture)
/*
* R-Car CTU
*/
-int rsnd_ctu_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv);
-
-void rsnd_ctu_remove(struct platform_device *pdev,
- struct rsnd_priv *priv);
+int rsnd_ctu_probe(struct rsnd_priv *priv);
+void rsnd_ctu_remove(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
+#define rsnd_ctu_of_node(priv) \
+ of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ctu")
+#define rsnd_parse_connect_ctu(rdai, playback, capture) \
+ rsnd_parse_connect_common(rdai, rsnd_ctu_mod_get, \
+ rsnd_ctu_of_node(rsnd_rdai_to_priv(rdai)), \
+ playback, capture)
/*
* R-Car MIX
*/
-int rsnd_mix_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv);
-
-void rsnd_mix_remove(struct platform_device *pdev,
- struct rsnd_priv *priv);
+int rsnd_mix_probe(struct rsnd_priv *priv);
+void rsnd_mix_remove(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
+#define rsnd_mix_of_node(priv) \
+ of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,mix")
+#define rsnd_parse_connect_mix(rdai, playback, capture) \
+ rsnd_parse_connect_common(rdai, rsnd_mix_mod_get, \
+ rsnd_mix_of_node(rsnd_rdai_to_priv(rdai)), \
+ playback, capture)
/*
* R-Car DVC
*/
-int rsnd_dvc_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv);
-void rsnd_dvc_remove(struct platform_device *pdev,
- struct rsnd_priv *priv);
+int rsnd_dvc_probe(struct rsnd_priv *priv);
+void rsnd_dvc_remove(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
+#define rsnd_dvc_of_node(priv) \
+ of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc")
+#define rsnd_parse_connect_dvc(rdai, playback, capture) \
+ rsnd_parse_connect_common(rdai, rsnd_dvc_mod_get, \
+ rsnd_dvc_of_node(rsnd_rdai_to_priv(rdai)), \
+ playback, capture)
+
+/*
+ * R-Car CMD
+ */
+int rsnd_cmd_probe(struct rsnd_priv *priv);
+void rsnd_cmd_remove(struct rsnd_priv *priv);
+int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id);
+struct rsnd_mod *rsnd_cmd_mod_get(struct rsnd_priv *priv, int id);
#ifdef DEBUG
void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type);
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c
index d61db9c385ea..8a357fdf1077 100644
--- a/sound/soc/sh/rcar/rsrc-card.c
+++ b/sound/soc/sh/rcar/rsrc-card.c
@@ -48,8 +48,11 @@ MODULE_DEVICE_TABLE(of, rsrc_card_of_match);
#define DAI_NAME_NUM 32
struct rsrc_card_dai {
- unsigned int fmt;
unsigned int sysclk;
+ unsigned int tx_slot_mask;
+ unsigned int rx_slot_mask;
+ int slots;
+ int slot_width;
struct clk *clk;
char dai_name[DAI_NAME_NUM];
};
@@ -75,7 +78,7 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct rsrc_card_dai *dai_props =
- rsrc_priv_to_props(priv, rtd - rtd->card->rtd);
+ rsrc_priv_to_props(priv, rtd->num);
return clk_prepare_enable(dai_props->clk);
}
@@ -85,7 +88,7 @@ static void rsrc_card_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct rsrc_card_dai *dai_props =
- rsrc_priv_to_props(priv, rtd - rtd->card->rtd);
+ rsrc_priv_to_props(priv, rtd->num);
clk_disable_unprepare(dai_props->clk);
}
@@ -101,7 +104,7 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dai *dai;
struct snd_soc_dai_link *dai_link;
struct rsrc_card_dai *dai_props;
- int num = rtd - rtd->card->rtd;
+ int num = rtd->num;
int ret;
dai_link = rsrc_priv_to_link(priv, num);
@@ -110,18 +113,22 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd)
rtd->cpu_dai :
rtd->codec_dai;
- if (dai_props->fmt) {
- ret = snd_soc_dai_set_fmt(dai, dai_props->fmt);
+ if (dai_props->sysclk) {
+ ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0);
if (ret && ret != -ENOTSUPP) {
- dev_err(dai->dev, "set_fmt error\n");
+ dev_err(dai->dev, "set_sysclk error\n");
goto err;
}
}
- if (dai_props->sysclk) {
- ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0);
+ if (dai_props->slots) {
+ ret = snd_soc_dai_set_tdm_slot(dai,
+ dai_props->tx_slot_mask,
+ dai_props->rx_slot_mask,
+ dai_props->slots,
+ dai_props->slot_width);
if (ret && ret != -ENOTSUPP) {
- dev_err(dai->dev, "set_sysclk error\n");
+ dev_err(dai->dev, "set_tdm_slot error\n");
goto err;
}
}
@@ -148,14 +155,13 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
}
static int rsrc_card_parse_daifmt(struct device_node *node,
- struct device_node *np,
+ struct device_node *codec,
struct rsrc_card_priv *priv,
- int idx, bool is_fe)
+ struct snd_soc_dai_link *dai_link,
+ unsigned int *retfmt)
{
- struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
struct device_node *bitclkmaster = NULL;
struct device_node *framemaster = NULL;
- struct device_node *codec = is_fe ? NULL : np;
unsigned int daifmt;
daifmt = snd_soc_of_parse_daifmt(node, NULL,
@@ -172,11 +178,11 @@ static int rsrc_card_parse_daifmt(struct device_node *node,
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
- dai_props->fmt = daifmt;
-
of_node_put(bitclkmaster);
of_node_put(framemaster);
+ *retfmt = daifmt;
+
return 0;
}
@@ -198,6 +204,15 @@ static int rsrc_card_parse_links(struct device_node *np,
if (ret)
return ret;
+ /* Parse TDM slot */
+ ret = snd_soc_of_parse_tdm_slot(np,
+ &dai_props->tx_slot_mask,
+ &dai_props->rx_slot_mask,
+ &dai_props->slots,
+ &dai_props->slot_width);
+ if (ret)
+ return ret;
+
if (is_fe) {
/* BE is dummy */
dai_link->codec_of_node = NULL;
@@ -208,7 +223,9 @@ static int rsrc_card_parse_links(struct device_node *np,
dai_link->dynamic = 1;
dai_link->dpcm_merged_format = 1;
dai_link->cpu_of_node = args.np;
- snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name);
+ ret = snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name);
+ if (ret < 0)
+ return ret;
/* set dai_name */
snprintf(dai_props->dai_name, DAI_NAME_NUM, "fe.%s",
@@ -240,7 +257,9 @@ static int rsrc_card_parse_links(struct device_node *np,
dai_link->no_pcm = 1;
dai_link->be_hw_params_fixup = rsrc_card_be_hw_params_fixup;
dai_link->codec_of_node = args.np;
- snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name);
+ ret = snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name);
+ if (ret < 0)
+ return ret;
/* additional name prefix */
if (of_data) {
@@ -305,23 +324,16 @@ static int rsrc_card_parse_clk(struct device_node *np,
return 0;
}
-static int rsrc_card_dai_link_of(struct device_node *node,
- struct device_node *np,
- struct rsrc_card_priv *priv,
- int idx)
+static int rsrc_card_dai_sub_link_of(struct device_node *node,
+ struct device_node *np,
+ struct rsrc_card_priv *priv,
+ int idx, bool is_fe)
{
struct device *dev = rsrc_priv_to_dev(priv);
+ struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
- bool is_fe = false;
int ret;
- if (0 == strcmp(np->name, "cpu"))
- is_fe = true;
-
- ret = rsrc_card_parse_daifmt(node, np, priv, idx, is_fe);
- if (ret < 0)
- return ret;
-
ret = rsrc_card_parse_links(np, priv, idx, is_fe);
if (ret < 0)
return ret;
@@ -332,12 +344,54 @@ static int rsrc_card_dai_link_of(struct device_node *node,
dev_dbg(dev, "\t%s / %04x / %d\n",
dai_props->dai_name,
- dai_props->fmt,
+ dai_link->dai_fmt,
dai_props->sysclk);
return ret;
}
+static int rsrc_card_dai_link_of(struct device_node *node,
+ struct rsrc_card_priv *priv)
+{
+ struct snd_soc_dai_link *dai_link;
+ struct device_node *np;
+ unsigned int daifmt = 0;
+ int ret, i;
+ bool is_fe;
+
+ /* find 1st codec */
+ i = 0;
+ for_each_child_of_node(node, np) {
+ dai_link = rsrc_priv_to_link(priv, i);
+
+ if (strcmp(np->name, "codec") == 0) {
+ ret = rsrc_card_parse_daifmt(node, np, priv,
+ dai_link, &daifmt);
+ if (ret < 0)
+ return ret;
+ break;
+ }
+ i++;
+ }
+
+ i = 0;
+ for_each_child_of_node(node, np) {
+ dai_link = rsrc_priv_to_link(priv, i);
+ dai_link->dai_fmt = daifmt;
+
+ is_fe = false;
+ if (strcmp(np->name, "cpu") == 0)
+ is_fe = true;
+
+ ret = rsrc_card_dai_sub_link_of(node, np, priv, i, is_fe);
+ if (ret < 0)
+ return ret;
+ i++;
+ }
+
+ return 0;
+}
+
static int rsrc_card_parse_of(struct device_node *node,
struct rsrc_card_priv *priv,
struct device *dev)
@@ -345,9 +399,8 @@ static int rsrc_card_parse_of(struct device_node *node,
const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev);
struct rsrc_card_dai *props;
struct snd_soc_dai_link *links;
- struct device_node *np;
int ret;
- int i, num;
+ int num;
if (!node)
return -EINVAL;
@@ -388,13 +441,9 @@ static int rsrc_card_parse_of(struct device_node *node,
priv->snd_card.name ? priv->snd_card.name : "",
priv->convert_rate);
- i = 0;
- for_each_child_of_node(node, np) {
- ret = rsrc_card_dai_link_of(node, np, priv, i);
- if (ret < 0)
- return ret;
- i++;
- }
+ ret = rsrc_card_dai_link_of(node, priv);
+ if (ret < 0)
+ return ret;
if (!priv->snd_card.name)
priv->snd_card.name = priv->snd_card.dai_link->name;
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 68b439ed22d7..5eda056d9f20 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -20,20 +20,21 @@
#define OUF_SRC(id) ((1 << (id + 16)) | (1 << id))
struct rsnd_src {
- struct rsnd_src_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
+ struct rsnd_mod *dma;
struct rsnd_kctrl_cfg_s sen; /* sync convert enable */
struct rsnd_kctrl_cfg_s sync; /* sync convert */
u32 convert_rate; /* sampling rate convert */
int err;
+ int irq;
};
#define RSND_SRC_NAME_SIZE 16
+#define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id)
+#define rsnd_src_to_dma(src) ((src)->dma)
#define rsnd_src_nr(priv) ((priv)->src_nr)
#define rsnd_enable_sync_convert(src) ((src)->sen.val)
-#define rsnd_src_of_node(priv) \
- of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src")
#define rsnd_mod_to_src(_mod) \
container_of((_mod), struct rsnd_src, mod)
@@ -69,67 +70,16 @@ struct rsnd_src {
* |-----------------|
*/
-/*
- * How to use SRC bypass mode for debugging
- *
- * SRC has bypass mode, and it is useful for debugging.
- * In Gen2 case,
- * SRCm_MODE controls whether SRC is used or not
- * SSI_MODE0 controls whether SSIU which receives SRC data
- * is used or not.
- * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC,
- * but SRC bypass mode needs SSI_MODE0 only.
- *
- * This driver request
- * struct rsnd_src_platform_info {
- * u32 convert_rate;
- * int dma_id;
- * }
- *
- * rsnd_src_convert_rate() indicates
- * above convert_rate, and it controls
- * whether SRC is used or not.
- *
- * ex) doesn't use SRC
- * static struct rsnd_dai_platform_info rsnd_dai = {
- * .playback = { .ssi = &rsnd_ssi[0], },
- * };
- *
- * ex) uses SRC
- * static struct rsnd_src_platform_info rsnd_src[] = {
- * RSND_SCU(48000, 0),
- * ...
- * };
- * static struct rsnd_dai_platform_info rsnd_dai = {
- * .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] },
- * };
- *
- * ex) uses SRC bypass mode
- * static struct rsnd_src_platform_info rsnd_src[] = {
- * RSND_SCU(0, 0),
- * ...
- * };
- * static struct rsnd_dai_platform_info rsnd_dai = {
- * .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] },
- * };
- *
- */
-
-/*
- * Gen1/Gen2 common functions
- */
-static void rsnd_src_soft_reset(struct rsnd_mod *mod)
+static void rsnd_src_activation(struct rsnd_mod *mod)
{
rsnd_mod_write(mod, SRC_SWRSR, 0);
rsnd_mod_write(mod, SRC_SWRSR, 1);
}
-
-#define rsnd_src_initialize_lock(mod) __rsnd_src_initialize_lock(mod, 1)
-#define rsnd_src_initialize_unlock(mod) __rsnd_src_initialize_lock(mod, 0)
-static void __rsnd_src_initialize_lock(struct rsnd_mod *mod, u32 enable)
+static void rsnd_src_halt(struct rsnd_mod *mod)
{
- rsnd_mod_write(mod, SRC_SRCIR, enable);
+ rsnd_mod_write(mod, SRC_SRCIR, 1);
+ rsnd_mod_write(mod, SRC_SWRSR, 0);
}
static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
@@ -143,99 +93,6 @@ static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
is_play ? "rx" : "tx");
}
-int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
- struct rsnd_dai_stream *io,
- int use_busif)
-{
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- int ssi_id = rsnd_mod_id(ssi_mod);
-
- /*
- * SSI_MODE0
- */
- rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id),
- !use_busif << ssi_id);
-
- /*
- * SSI_MODE1
- */
- if (rsnd_ssi_is_pin_sharing(io)) {
- int shift = -1;
- switch (ssi_id) {
- case 1:
- shift = 0;
- break;
- case 2:
- shift = 2;
- break;
- case 4:
- shift = 16;
- break;
- }
-
- if (shift >= 0)
- rsnd_mod_bset(ssi_mod, SSI_MODE1,
- 0x3 << shift,
- rsnd_rdai_is_clk_master(rdai) ?
- 0x2 << shift : 0x1 << shift);
- }
-
- /*
- * DMA settings for SSIU
- */
- if (use_busif) {
- u32 val = rsnd_get_dalign(ssi_mod, io);
-
- rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR,
- rsnd_get_adinr_bit(ssi_mod, io));
- rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1);
- rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1);
-
- rsnd_mod_write(ssi_mod, SSI_BUSIF_DALIGN, val);
- }
-
- return 0;
-}
-
-int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
- struct rsnd_dai_stream *io)
-{
- /*
- * DMA settings for SSIU
- */
- rsnd_mod_write(ssi_mod, SSI_CTRL, 0);
-
- return 0;
-}
-
-int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
-
- if (rsnd_is_gen1(priv))
- return 0;
-
- /* enable SSI interrupt if Gen2 */
- rsnd_mod_write(ssi_mod, SSI_INT_ENABLE,
- rsnd_ssi_is_dma_mode(ssi_mod) ?
- 0x0e000000 : 0x0f000000);
-
- return 0;
-}
-
-int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
-
- if (rsnd_is_gen1(priv))
- return 0;
-
- /* disable SSI interrupt if Gen2 */
- rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, 0x00000000);
-
- return 0;
-}
-
static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
struct rsnd_src *src)
{
@@ -283,34 +140,6 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
return rate;
}
-static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- u32 convert_rate = rsnd_src_convert_rate(io, src);
- u32 fsrate = 0;
-
- if (convert_rate)
- fsrate = 0x0400000 / convert_rate * runtime->rate;
-
- /* Set channel number and output bit length */
- rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr_bit(mod, io));
-
- /* Enable the initial value of IFS */
- if (fsrate) {
- rsnd_mod_write(mod, SRC_IFSCR, 1);
-
- /* Set initial value of IFS */
- rsnd_mod_write(mod, SRC_IFSVR, fsrate);
- }
-
- /* use DMA transfer */
- rsnd_mod_write(mod, SRC_BUSIF_MODE, 1);
-
- return 0;
-}
-
static int rsnd_src_hw_params(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_pcm_substream *substream,
@@ -319,9 +148,6 @@ static int rsnd_src_hw_params(struct rsnd_mod *mod,
struct rsnd_src *src = rsnd_mod_to_src(mod);
struct snd_soc_pcm_runtime *fe = substream->private_data;
- /* default value (mainly for non-DT) */
- src->convert_rate = src->info->convert_rate;
-
/*
* SRC assumes that it is used under DPCM if user want to use
* sampling rate convert. Then, SRC should be FE.
@@ -347,250 +173,112 @@ static int rsnd_src_hw_params(struct rsnd_mod *mod,
return 0;
}
-static int rsnd_src_init(struct rsnd_mod *mod,
- struct rsnd_priv *priv)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
-
- rsnd_mod_power_on(mod);
-
- rsnd_src_soft_reset(mod);
-
- rsnd_src_initialize_lock(mod);
-
- src->err = 0;
-
- /* reset sync convert_rate */
- src->sync.val = 0;
-
- return 0;
-}
-
-static int rsnd_src_quit(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
+static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod)
{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
+ struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
+ struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+ struct rsnd_src *src = rsnd_mod_to_src(mod);
+ u32 convert_rate = rsnd_src_convert_rate(io, src);
+ u32 ifscr, fsrate, adinr;
+ u32 cr, route;
+ u32 bsdsr, bsisr;
+ uint ratio;
- rsnd_mod_power_off(mod);
-
- if (src->err)
- dev_warn(dev, "%s[%d] under/over flow err = %d\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod), src->err);
-
- src->convert_rate = 0;
-
- /* reset sync convert_rate */
- src->sync.val = 0;
-
- return 0;
-}
-
-static int rsnd_src_start(struct rsnd_mod *mod)
-{
- rsnd_src_initialize_unlock(mod);
-
- return 0;
-}
-
-static int rsnd_src_stop(struct rsnd_mod *mod)
-{
- /* nothing to do */
- return 0;
-}
+ if (!runtime)
+ return;
-/*
- * Gen1 functions
- */
-static int rsnd_src_set_route_gen1(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct src_route_config {
- u32 mask;
- int shift;
- } routes[] = {
- { 0xF, 0, }, /* 0 */
- { 0xF, 4, }, /* 1 */
- { 0xF, 8, }, /* 2 */
- { 0x7, 12, }, /* 3 */
- { 0x7, 16, }, /* 4 */
- { 0x7, 20, }, /* 5 */
- { 0x7, 24, }, /* 6 */
- { 0x3, 28, }, /* 7 */
- { 0x3, 30, }, /* 8 */
- };
- u32 mask;
- u32 val;
- int id;
+ /* 6 - 1/6 are very enough ratio for SRC_BSDSR */
+ if (!convert_rate)
+ ratio = 0;
+ else if (convert_rate > runtime->rate)
+ ratio = 100 * convert_rate / runtime->rate;
+ else
+ ratio = 100 * runtime->rate / convert_rate;
- id = rsnd_mod_id(mod);
- if (id < 0 || id >= ARRAY_SIZE(routes))
- return -EIO;
+ if (ratio > 600) {
+ dev_err(dev, "FSO/FSI ratio error\n");
+ return;
+ }
/*
- * SRC_ROUTE_SELECT
+ * SRC_ADINR
*/
- val = rsnd_io_is_play(io) ? 0x1 : 0x2;
- val = val << routes[id].shift;
- mask = routes[id].mask << routes[id].shift;
-
- rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val);
-
- return 0;
-}
-
-static int rsnd_src_set_convert_timing_gen1(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- u32 convert_rate = rsnd_src_convert_rate(io, src);
- u32 mask;
- u32 val;
- int shift;
- int id = rsnd_mod_id(mod);
- int ret;
+ adinr = rsnd_get_adinr_bit(mod, io) |
+ rsnd_get_adinr_chan(mod, io);
/*
- * SRC_TIMING_SELECT
+ * SRC_IFSCR / SRC_IFSVR
*/
- shift = (id % 4) * 8;
- mask = 0x1F << shift;
+ ifscr = 0;
+ fsrate = 0;
+ if (convert_rate) {
+ ifscr = 1;
+ fsrate = 0x0400000 / convert_rate * runtime->rate;
+ }
/*
- * ADG is used as source clock if SRC was used,
- * then, SSI WS is used as destination clock.
- * SSI WS is used as source clock if SRC is not used
- * (when playback, source/destination become reverse when capture)
+ * SRC_SRCCR / SRC_ROUTE_MODE0
*/
- ret = 0;
+ cr = 0x00011110;
+ route = 0x0;
if (convert_rate) {
- /* use ADG */
- val = 0;
- ret = rsnd_adg_set_convert_clk_gen1(priv, mod,
- runtime->rate,
- convert_rate);
- } else if (8 == id) {
- /* use SSI WS, but SRU8 is special */
- val = id << shift;
- } else {
- /* use SSI WS */
- val = (id + 1) << shift;
- }
+ route = 0x1;
- if (ret < 0)
- return ret;
+ if (rsnd_enable_sync_convert(src)) {
+ cr |= 0x1;
+ route |= rsnd_io_is_play(io) ?
+ (0x1 << 24) : (0x1 << 25);
+ }
+ }
- switch (id / 4) {
- case 0:
- rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val);
- break;
- case 1:
- rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val);
+ /*
+ * SRC_BSDSR / SRC_BSISR
+ */
+ switch (rsnd_mod_id(mod)) {
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ bsdsr = 0x02400000; /* 6 - 1/6 */
+ bsisr = 0x00100060; /* 6 - 1/6 */
break;
- case 2:
- rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val);
+ default:
+ bsdsr = 0x01800000; /* 6 - 1/6 */
+ bsisr = 0x00100060 ;/* 6 - 1/6 */
break;
}
- return 0;
-}
-
-static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
-{
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- int ret;
-
- ret = rsnd_src_set_convert_rate(mod, io);
- if (ret < 0)
- return ret;
-
- /* Select SRC mode (fixed value) */
- rsnd_mod_write(mod, SRC_SRCCR, 0x00010110);
-
- /* Set the restriction value of the FS ratio (98%) */
- rsnd_mod_write(mod, SRC_MNFSR,
- rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98);
-
- /* Gen1/Gen2 are not compatible */
- if (rsnd_src_convert_rate(io, src))
- rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1);
-
- /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */
-
- return 0;
-}
-
-static int rsnd_src_init_gen1(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- ret = rsnd_src_init(mod, priv);
- if (ret < 0)
- return ret;
-
- ret = rsnd_src_set_route_gen1(io, mod);
- if (ret < 0)
- return ret;
-
- ret = rsnd_src_set_convert_rate_gen1(mod, io);
- if (ret < 0)
- return ret;
-
- ret = rsnd_src_set_convert_timing_gen1(io, mod);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int rsnd_src_start_gen1(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int id = rsnd_mod_id(mod);
-
- rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id));
-
- return rsnd_src_start(mod);
-}
-
-static int rsnd_src_stop_gen1(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int id = rsnd_mod_id(mod);
+ rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */
+ rsnd_mod_write(mod, SRC_ADINR, adinr);
+ rsnd_mod_write(mod, SRC_IFSCR, ifscr);
+ rsnd_mod_write(mod, SRC_IFSVR, fsrate);
+ rsnd_mod_write(mod, SRC_SRCCR, cr);
+ rsnd_mod_write(mod, SRC_BSDSR, bsdsr);
+ rsnd_mod_write(mod, SRC_BSISR, bsisr);
+ rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */
- rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0);
+ rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
+ rsnd_mod_write(mod, SRC_I_BUSIF_MODE, 1);
+ rsnd_mod_write(mod, SRC_O_BUSIF_MODE, 1);
+ rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
- return rsnd_src_stop(mod);
+ if (convert_rate)
+ rsnd_adg_set_convert_clk_gen2(mod, io,
+ runtime->rate,
+ convert_rate);
+ else
+ rsnd_adg_set_convert_timing_gen2(mod, io);
}
-static struct rsnd_mod_ops rsnd_src_gen1_ops = {
- .name = SRC_NAME,
- .dma_req = rsnd_src_dma_req,
- .init = rsnd_src_init_gen1,
- .quit = rsnd_src_quit,
- .start = rsnd_src_start_gen1,
- .stop = rsnd_src_stop_gen1,
- .hw_params = rsnd_src_hw_params,
-};
-
-/*
- * Gen2 functions
- */
-#define rsnd_src_irq_enable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 1)
-#define rsnd_src_irq_disable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 0)
-static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable)
+#define rsnd_src_irq_enable(mod) rsnd_src_irq_ctrol(mod, 1)
+#define rsnd_src_irq_disable(mod) rsnd_src_irq_ctrol(mod, 0)
+static void rsnd_src_irq_ctrol(struct rsnd_mod *mod, int enable)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
u32 sys_int_val, int_val, sys_int_mask;
- int irq = src->info->irq;
+ int irq = src->irq;
int id = rsnd_mod_id(mod);
sys_int_val =
@@ -600,7 +288,7 @@ static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable)
/*
* IRQ is not supported on non-DT
* see
- * rsnd_src_probe_gen2()
+ * rsnd_src_probe_()
*/
if ((irq <= 0) || !enable) {
sys_int_val = 0;
@@ -620,7 +308,7 @@ static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable)
rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
}
-static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod)
+static void rsnd_src_status_clear(struct rsnd_mod *mod)
{
u32 val = OUF_SRC(rsnd_mod_id(mod));
@@ -628,7 +316,7 @@ static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod)
rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val);
}
-static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod)
+static bool rsnd_src_record_error(struct rsnd_mod *mod)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
u32 val0, val1;
@@ -652,22 +340,16 @@ static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod)
ret = true;
}
- /* clear error static */
- rsnd_src_error_clear_gen2(mod);
-
return ret;
}
-static int _rsnd_src_start_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
+static int rsnd_src_start(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
u32 val;
- val = rsnd_get_dalign(mod, io);
-
- rsnd_mod_write(mod, SRC_BUSIF_DALIGN, val);
-
/*
* WORKAROUND
*
@@ -678,247 +360,149 @@ static int _rsnd_src_start_gen2(struct rsnd_mod *mod,
rsnd_mod_write(mod, SRC_CTRL, val);
- rsnd_src_error_clear_gen2(mod);
-
- rsnd_src_start(mod);
+ return 0;
+}
- rsnd_src_irq_enable_gen2(mod);
+static int rsnd_src_stop(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ /*
+ * stop SRC output only
+ * see rsnd_src_quit
+ */
+ rsnd_mod_write(mod, SRC_CTRL, 0x01);
return 0;
}
-static int _rsnd_src_stop_gen2(struct rsnd_mod *mod)
+static int rsnd_src_init(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
- rsnd_src_irq_disable_gen2(mod);
+ struct rsnd_src *src = rsnd_mod_to_src(mod);
- rsnd_mod_write(mod, SRC_CTRL, 0);
+ rsnd_mod_power_on(mod);
+
+ rsnd_src_activation(mod);
+
+ rsnd_src_set_convert_rate(io, mod);
- rsnd_src_error_record_gen2(mod);
+ rsnd_src_status_clear(mod);
+
+ rsnd_src_irq_enable(mod);
+
+ src->err = 0;
- return rsnd_src_stop(mod);
+ /* reset sync convert_rate */
+ src->sync.val = 0;
+
+ return 0;
}
-static void __rsnd_src_interrupt_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
+static int rsnd_src_quit(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-
- spin_lock(&priv->lock);
+ struct rsnd_src *src = rsnd_mod_to_src(mod);
+ struct device *dev = rsnd_priv_to_dev(priv);
- /* ignore all cases if not working */
- if (!rsnd_io_is_working(io))
- goto rsnd_src_interrupt_gen2_out;
+ rsnd_src_irq_disable(mod);
- if (rsnd_src_error_record_gen2(mod)) {
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
+ /* stop both out/in */
+ rsnd_mod_write(mod, SRC_CTRL, 0);
- dev_dbg(dev, "%s[%d] restart\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod));
+ rsnd_src_halt(mod);
- _rsnd_src_stop_gen2(mod);
- if (src->err < 1024)
- _rsnd_src_start_gen2(mod, io);
- else
- dev_warn(dev, "no more SRC restart\n");
- }
+ rsnd_mod_power_off(mod);
-rsnd_src_interrupt_gen2_out:
- spin_unlock(&priv->lock);
-}
+ if (src->err)
+ dev_warn(dev, "%s[%d] under/over flow err = %d\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod), src->err);
-static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data)
-{
- struct rsnd_mod *mod = data;
+ src->convert_rate = 0;
- rsnd_mod_interrupt(mod, __rsnd_src_interrupt_gen2);
+ /* reset sync convert_rate */
+ src->sync.val = 0;
- return IRQ_HANDLED;
+ return 0;
}
-static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io)
+static void __rsnd_src_interrupt(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct rsnd_src *src = rsnd_mod_to_src(mod);
- u32 convert_rate = rsnd_src_convert_rate(io, src);
- u32 cr, route;
- uint ratio;
- int ret;
+ struct device *dev = rsnd_priv_to_dev(priv);
- /* 6 - 1/6 are very enough ratio for SRC_BSDSR */
- if (!convert_rate)
- ratio = 0;
- else if (convert_rate > runtime->rate)
- ratio = 100 * convert_rate / runtime->rate;
- else
- ratio = 100 * runtime->rate / convert_rate;
+ spin_lock(&priv->lock);
- if (ratio > 600) {
- dev_err(dev, "FSO/FSI ratio error\n");
- return -EINVAL;
- }
+ /* ignore all cases if not working */
+ if (!rsnd_io_is_working(io))
+ goto rsnd_src_interrupt_out;
- ret = rsnd_src_set_convert_rate(mod, io);
- if (ret < 0)
- return ret;
+ if (rsnd_src_record_error(mod)) {
- cr = 0x00011110;
- route = 0x0;
- if (convert_rate) {
- route = 0x1;
+ dev_dbg(dev, "%s[%d] restart\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod));
- if (rsnd_enable_sync_convert(src)) {
- cr |= 0x1;
- route |= rsnd_io_is_play(io) ?
- (0x1 << 24) : (0x1 << 25);
- }
+ rsnd_src_stop(mod, io, priv);
+ rsnd_src_start(mod, io, priv);
}
- rsnd_mod_write(mod, SRC_SRCCR, cr);
- rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
+ if (src->err > 1024) {
+ rsnd_src_irq_disable(mod);
- switch (rsnd_mod_id(mod)) {
- case 5:
- case 6:
- case 7:
- case 8:
- rsnd_mod_write(mod, SRC_BSDSR, 0x02400000);
- break;
- default:
- rsnd_mod_write(mod, SRC_BSDSR, 0x01800000);
- break;
+ dev_warn(dev, "no more %s[%d] restart\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod));
}
- rsnd_mod_write(mod, SRC_BSISR, 0x00100060);
+ rsnd_src_status_clear(mod);
+rsnd_src_interrupt_out:
- return 0;
+ spin_unlock(&priv->lock);
}
-static int rsnd_src_set_convert_timing_gen2(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
+static irqreturn_t rsnd_src_interrupt(int irq, void *data)
{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- u32 convert_rate = rsnd_src_convert_rate(io, src);
- int ret;
+ struct rsnd_mod *mod = data;
- if (convert_rate)
- ret = rsnd_adg_set_convert_clk_gen2(mod, io,
- runtime->rate,
- convert_rate);
- else
- ret = rsnd_adg_set_convert_timing_gen2(mod, io);
+ rsnd_mod_interrupt(mod, __rsnd_src_interrupt);
- return ret;
+ return IRQ_HANDLED;
}
-static int rsnd_src_probe_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
+static int rsnd_src_probe_(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
struct rsnd_src *src = rsnd_mod_to_src(mod);
struct device *dev = rsnd_priv_to_dev(priv);
- int irq = src->info->irq;
+ int irq = src->irq;
int ret;
if (irq > 0) {
/*
* IRQ is not supported on non-DT
* see
- * rsnd_src_irq_enable_gen2()
+ * rsnd_src_irq_enable()
*/
ret = devm_request_irq(dev, irq,
- rsnd_src_interrupt_gen2,
+ rsnd_src_interrupt,
IRQF_SHARED,
dev_name(dev), mod);
if (ret)
return ret;
}
- ret = rsnd_dma_init(io,
- rsnd_mod_to_dma(mod),
- src->info->dma_id);
+ src->dma = rsnd_dma_attach(io, mod, 0);
+ if (IS_ERR(src->dma))
+ return PTR_ERR(src->dma);
return ret;
}
-static int rsnd_src_remove_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_dma_quit(io, rsnd_mod_to_dma(mod));
-
- return 0;
-}
-
-static int rsnd_src_init_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- ret = rsnd_src_init(mod, priv);
- if (ret < 0)
- return ret;
-
- ret = rsnd_src_set_convert_rate_gen2(mod, io);
- if (ret < 0)
- return ret;
-
- ret = rsnd_src_set_convert_timing_gen2(io, mod);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int rsnd_src_start_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- rsnd_dma_start(io, rsnd_mod_to_dma(mod));
-
- return _rsnd_src_start_gen2(mod, io);
-}
-
-static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- int ret;
-
- ret = _rsnd_src_stop_gen2(mod);
-
- rsnd_dma_stop(io, rsnd_mod_to_dma(mod));
-
- return ret;
-}
-
-static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod)
-{
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- struct rsnd_src *src = rsnd_mod_to_src(mod);
- u32 convert_rate = rsnd_src_convert_rate(io, src);
- u32 fsrate;
-
- if (!runtime)
- return;
-
- if (!convert_rate)
- convert_rate = runtime->rate;
-
- fsrate = 0x0400000 / convert_rate * runtime->rate;
-
- /* update IFS */
- rsnd_mod_write(mod, SRC_IFSVR, fsrate);
-}
-
-static int rsnd_src_pcm_new_gen2(struct rsnd_mod *mod,
+static int rsnd_src_pcm_new(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd)
{
@@ -950,7 +534,7 @@ static int rsnd_src_pcm_new_gen2(struct rsnd_mod *mod,
rsnd_io_is_play(io) ?
"SRC Out Rate Switch" :
"SRC In Rate Switch",
- rsnd_src_reconvert_update,
+ rsnd_src_set_convert_rate,
&src->sen, 1);
if (ret < 0)
return ret;
@@ -959,23 +543,22 @@ static int rsnd_src_pcm_new_gen2(struct rsnd_mod *mod,
rsnd_io_is_play(io) ?
"SRC Out Rate" :
"SRC In Rate",
- rsnd_src_reconvert_update,
+ rsnd_src_set_convert_rate,
&src->sync, 192000);
return ret;
}
-static struct rsnd_mod_ops rsnd_src_gen2_ops = {
+static struct rsnd_mod_ops rsnd_src_ops = {
.name = SRC_NAME,
.dma_req = rsnd_src_dma_req,
- .probe = rsnd_src_probe_gen2,
- .remove = rsnd_src_remove_gen2,
- .init = rsnd_src_init_gen2,
+ .probe = rsnd_src_probe_,
+ .init = rsnd_src_init,
.quit = rsnd_src_quit,
- .start = rsnd_src_start_gen2,
- .stop = rsnd_src_stop_gen2,
+ .start = rsnd_src_start,
+ .stop = rsnd_src_stop,
.hw_params = rsnd_src_hw_params,
- .pcm_new = rsnd_src_pcm_new_gen2,
+ .pcm_new = rsnd_src_pcm_new,
};
struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
@@ -983,113 +566,78 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
id = 0;
- return rsnd_mod_get((struct rsnd_src *)(priv->src) + id);
+ return rsnd_mod_get(rsnd_src_get(priv, id));
}
-static void rsnd_of_parse_src(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+int rsnd_src_probe(struct rsnd_priv *priv)
{
- struct device_node *src_node;
+ struct device_node *node;
struct device_node *np;
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
- struct rsnd_src_platform_info *src_info;
- struct device *dev = &pdev->dev;
- int nr, i;
-
- if (!of_data)
- return;
-
- src_node = rsnd_src_of_node(priv);
- if (!src_node)
- return;
-
- nr = of_get_child_count(src_node);
- if (!nr)
- goto rsnd_of_parse_src_end;
-
- src_info = devm_kzalloc(dev,
- sizeof(struct rsnd_src_platform_info) * nr,
- GFP_KERNEL);
- if (!src_info) {
- dev_err(dev, "src info allocation error\n");
- goto rsnd_of_parse_src_end;
- }
-
- info->src_info = src_info;
- info->src_info_nr = nr;
-
- i = 0;
- for_each_child_of_node(src_node, np) {
- src_info[i].irq = irq_of_parse_and_map(np, 0);
-
- i++;
- }
-
-rsnd_of_parse_src_end:
- of_node_put(src_node);
-}
-
-int rsnd_src_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
-{
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_src *src;
- struct rsnd_mod_ops *ops;
struct clk *clk;
char name[RSND_SRC_NAME_SIZE];
int i, nr, ret;
- ops = NULL;
- if (rsnd_is_gen1(priv)) {
- ops = &rsnd_src_gen1_ops;
- dev_warn(dev, "Gen1 support will be removed soon\n");
- }
- if (rsnd_is_gen2(priv))
- ops = &rsnd_src_gen2_ops;
- if (!ops) {
- dev_err(dev, "unknown Generation\n");
- return -EIO;
- }
+ /* This driver doesn't support Gen1 at this point */
+ if (rsnd_is_gen1(priv))
+ return 0;
- rsnd_of_parse_src(pdev, of_data, priv);
+ node = rsnd_src_of_node(priv);
+ if (!node)
+ return 0; /* not used is not error */
- /*
- * init SRC
- */
- nr = info->src_info_nr;
- if (!nr)
- return 0;
+ nr = of_get_child_count(node);
+ if (!nr) {
+ ret = -EINVAL;
+ goto rsnd_src_probe_done;
+ }
src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL);
- if (!src)
- return -ENOMEM;
+ if (!src) {
+ ret = -ENOMEM;
+ goto rsnd_src_probe_done;
+ }
priv->src_nr = nr;
priv->src = src;
- for_each_rsnd_src(src, priv, i) {
+ i = 0;
+ for_each_child_of_node(node, np) {
+ src = rsnd_src_get(priv, i);
+
snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
SRC_NAME, i);
- clk = devm_clk_get(dev, name);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
+ src->irq = irq_of_parse_and_map(np, 0);
+ if (!src->irq) {
+ ret = -EINVAL;
+ goto rsnd_src_probe_done;
+ }
- src->info = &info->src_info[i];
+ clk = devm_clk_get(dev, name);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto rsnd_src_probe_done;
+ }
- ret = rsnd_mod_init(priv, rsnd_mod_get(src), ops, clk, RSND_MOD_SRC, i);
+ ret = rsnd_mod_init(priv, rsnd_mod_get(src),
+ &rsnd_src_ops, clk, RSND_MOD_SRC, i);
if (ret)
- return ret;
+ goto rsnd_src_probe_done;
+
+ i++;
}
- return 0;
+ ret = 0;
+
+rsnd_src_probe_done:
+ of_node_put(node);
+
+ return ret;
}
-void rsnd_src_remove(struct platform_device *pdev,
- struct rsnd_priv *priv)
+void rsnd_src_remove(struct rsnd_priv *priv)
{
struct rsnd_src *src;
int i;
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 1427ec21bd7e..7ee89da4dd5f 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -24,7 +24,9 @@
#define OIEN (1 << 26) /* Overflow Interrupt Enable */
#define IIEN (1 << 25) /* Idle Mode Interrupt Enable */
#define DIEN (1 << 24) /* Data Interrupt Enable */
-
+#define CHNL_4 (1 << 22) /* Channels */
+#define CHNL_6 (2 << 22) /* Channels */
+#define CHNL_8 (3 << 22) /* Channels */
#define DWL_8 (0 << 19) /* Data Word Length */
#define DWL_16 (1 << 19) /* Data Word Length */
#define DWL_18 (2 << 19) /* Data Word Length */
@@ -39,6 +41,7 @@
#define SCKP (1 << 13) /* Serial Bit Clock Polarity */
#define SWSP (1 << 12) /* Serial WS Polarity */
#define SDTA (1 << 10) /* Serial Data Alignment */
+#define PDTA (1 << 9) /* Parallel Data Alignment */
#define DEL (1 << 8) /* Serial Data Delay */
#define CKDV(v) (v << 4) /* Serial Clock Division Ratio */
#define TRMD (1 << 1) /* Transmit/Receive Mode Select */
@@ -56,35 +59,44 @@
* SSIWSR
*/
#define CONT (1 << 8) /* WS Continue Function */
+#define WS_MODE (1 << 0) /* WS Mode */
#define SSI_NAME "ssi"
struct rsnd_ssi {
- struct rsnd_ssi_platform_info *info; /* rcar_snd.h */
struct rsnd_ssi *parent;
struct rsnd_mod mod;
+ struct rsnd_mod *dma;
+ u32 flags;
u32 cr_own;
u32 cr_clk;
+ u32 cr_mode;
+ u32 wsr;
int chan;
+ int rate;
int err;
+ int irq;
unsigned int usrcnt;
};
+/* flags */
+#define RSND_SSI_CLK_PIN_SHARE (1 << 0)
+#define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */
+
#define for_each_rsnd_ssi(pos, priv, i) \
for (i = 0; \
(i < rsnd_ssi_nr(priv)) && \
((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \
i++)
+#define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id)
+#define rsnd_ssi_to_dma(mod) ((ssi)->dma)
#define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
-#define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0)
-#define rsnd_ssi_parent(ssi) ((ssi)->parent)
-#define rsnd_ssi_mode_flags(p) ((p)->info->flags)
-#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
-#define rsnd_ssi_of_node(priv) \
- of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ssi")
+#define rsnd_ssi_mode_flags(p) ((p)->flags)
+#define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io))
+#define rsnd_ssi_is_multi_slave(ssi, io) ((mod) != rsnd_io_to_mod_ssi(io))
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
{
@@ -103,6 +115,16 @@ int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
return use_busif;
}
+static void rsnd_ssi_status_clear(struct rsnd_mod *mod)
+{
+ rsnd_mod_write(mod, SSISR, 0);
+}
+
+static u32 rsnd_ssi_status_get(struct rsnd_mod *mod)
+{
+ return rsnd_mod_read(mod, SSISR);
+}
+
static void rsnd_ssi_status_check(struct rsnd_mod *mod,
u32 bit)
{
@@ -112,7 +134,7 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod,
int i;
for (i = 0; i < 1024; i++) {
- status = rsnd_mod_read(mod, SSISR);
+ status = rsnd_ssi_status_get(mod);
if (status & bit)
return;
@@ -122,13 +144,79 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod,
dev_warn(dev, "status check failed\n");
}
+static int rsnd_ssi_irq_enable(struct rsnd_mod *ssi_mod)
+{
+ struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
+
+ if (rsnd_is_gen1(priv))
+ return 0;
+
+ /* enable SSI interrupt if Gen2 */
+ rsnd_mod_write(ssi_mod, SSI_INT_ENABLE,
+ rsnd_ssi_is_dma_mode(ssi_mod) ?
+ 0x0e000000 : 0x0f000000);
+
+ return 0;
+}
+
+static int rsnd_ssi_irq_disable(struct rsnd_mod *ssi_mod)
+{
+ struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
+
+ if (rsnd_is_gen1(priv))
+ return 0;
+
+ /* disable SSI interrupt if Gen2 */
+ rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, 0x00000000);
+
+ return 0;
+}
+
+u32 rsnd_ssi_multi_slaves(struct rsnd_dai_stream *io)
+{
+ struct rsnd_mod *mod;
+ struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+ struct rsnd_priv *priv = rsnd_io_to_priv(io);
+ struct device *dev = rsnd_priv_to_dev(priv);
+ enum rsnd_mod_type types[] = {
+ RSND_MOD_SSIM1,
+ RSND_MOD_SSIM2,
+ RSND_MOD_SSIM3,
+ };
+ int i, mask;
+
+ switch (runtime->channels) {
+ case 2: /* Multi channel is not needed for Stereo */
+ return 0;
+ case 6:
+ break;
+ default:
+ dev_err(dev, "unsupported channel\n");
+ return 0;
+ }
+
+ mask = 0;
+ for (i = 0; i < ARRAY_SIZE(types); i++) {
+ mod = rsnd_io_to_mod(io, types[i]);
+ if (!mod)
+ continue;
+
+ mask |= 1 << rsnd_mod_id(mod);
+ }
+
+ return mask;
+}
+
static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
struct rsnd_dai_stream *io)
{
struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct device *dev = rsnd_priv_to_dev(priv);
+ struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct rsnd_mod *mod = rsnd_mod_get(ssi);
+ struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
+ int slots = rsnd_get_slot_width(io);
int j, ret;
int ssi_clk_mul_table[] = {
1, 2, 4, 8, 16, 6, 12,
@@ -136,6 +224,24 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
unsigned int main_rate;
unsigned int rate = rsnd_src_get_ssi_rate(priv, io, runtime);
+ if (!rsnd_rdai_is_clk_master(rdai))
+ return 0;
+
+ if (ssi_parent_mod && !rsnd_ssi_is_parent(mod, io))
+ return 0;
+
+ if (rsnd_ssi_is_multi_slave(mod, io))
+ return 0;
+
+ if (ssi->usrcnt > 1) {
+ if (ssi->rate != rate) {
+ dev_err(dev, "SSI parent/child should use same rate\n");
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+
/*
* Find best clock, and try to start ADG
*/
@@ -143,15 +249,18 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
/*
* this driver is assuming that
- * system word is 64fs (= 2 x 32bit)
+ * system word is 32bit x slots
* see rsnd_ssi_init()
*/
- main_rate = rate * 32 * 2 * ssi_clk_mul_table[j];
+ main_rate = rate * 32 * slots * ssi_clk_mul_table[j];
ret = rsnd_adg_ssi_clk_try_start(mod, main_rate);
if (0 == ret) {
ssi->cr_clk = FORCE | SWL_32 |
SCKD | SWSD | CKDV(j);
+ ssi->wsr = CONT;
+
+ ssi->rate = rate;
dev_dbg(dev, "%s[%d] outputs %u Hz\n",
rsnd_mod_name(mod),
@@ -165,113 +274,91 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
return -EIO;
}
-static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi)
+static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi,
+ struct rsnd_dai_stream *io)
{
+ struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct rsnd_mod *mod = rsnd_mod_get(ssi);
+ struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
+
+ if (!rsnd_rdai_is_clk_master(rdai))
+ return;
+
+ if (ssi_parent_mod && !rsnd_ssi_is_parent(mod, io))
+ return;
+
+ if (ssi->usrcnt > 1)
+ return;
+
+ ssi->cr_clk = 0;
+ ssi->rate = 0;
- ssi->cr_clk = 0;
rsnd_adg_ssi_clk_stop(mod);
}
-static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
- struct rsnd_dai_stream *io)
+static int rsnd_ssi_config_init(struct rsnd_ssi *ssi,
+ struct rsnd_dai_stream *io)
{
- struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mod *mod = rsnd_mod_get(ssi);
+ struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+ u32 cr_own;
u32 cr_mode;
- u32 cr;
+ u32 wsr;
+ int is_tdm;
- if (0 == ssi->usrcnt) {
- rsnd_mod_power_on(mod);
+ is_tdm = (rsnd_get_slot_width(io) >= 6) ? 1 : 0;
- if (rsnd_rdai_is_clk_master(rdai)) {
- struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
+ /*
+ * always use 32bit system word.
+ * see also rsnd_ssi_master_clk_enable()
+ */
+ cr_own = FORCE | SWL_32 | PDTA;
- if (ssi_parent)
- rsnd_ssi_hw_start(ssi_parent, io);
- else
- rsnd_ssi_master_clk_start(ssi, io);
- }
+ if (rdai->bit_clk_inv)
+ cr_own |= SCKP;
+ if (rdai->frm_clk_inv ^ is_tdm)
+ cr_own |= SWSP;
+ if (rdai->data_alignment)
+ cr_own |= SDTA;
+ if (rdai->sys_delay)
+ cr_own |= DEL;
+ if (rsnd_io_is_play(io))
+ cr_own |= TRMD;
+
+ switch (runtime->sample_bits) {
+ case 16:
+ cr_own |= DWL_16;
+ break;
+ case 32:
+ cr_own |= DWL_24;
+ break;
+ default:
+ return -EINVAL;
}
- if (rsnd_ssi_is_dma_mode(mod)) {
+ if (rsnd_ssi_is_dma_mode(rsnd_mod_get(ssi))) {
cr_mode = UIEN | OIEN | /* over/under run */
DMEN; /* DMA : enable DMA */
} else {
cr_mode = DIEN; /* PIO : enable Data interrupt */
}
- cr = ssi->cr_own |
- ssi->cr_clk |
- cr_mode |
- EN;
-
- rsnd_mod_write(mod, SSICR, cr);
-
- /* enable WS continue */
- if (rsnd_rdai_is_clk_master(rdai))
- rsnd_mod_write(mod, SSIWSR, CONT);
-
- /* clear error status */
- rsnd_mod_write(mod, SSISR, 0);
-
- ssi->usrcnt++;
-
- dev_dbg(dev, "%s[%d] hw started\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod));
-}
-
-static void rsnd_ssi_hw_stop(struct rsnd_dai_stream *io, struct rsnd_ssi *ssi)
-{
- struct rsnd_mod *mod = rsnd_mod_get(ssi);
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct device *dev = rsnd_priv_to_dev(priv);
- u32 cr;
-
- if (0 == ssi->usrcnt) {
- dev_err(dev, "%s called without starting\n", __func__);
- return;
+ /*
+ * TDM Extend Mode
+ * see
+ * rsnd_ssiu_init_gen2()
+ */
+ wsr = ssi->wsr;
+ if (is_tdm) {
+ wsr |= WS_MODE;
+ cr_own |= CHNL_8;
}
- ssi->usrcnt--;
-
- if (0 == ssi->usrcnt) {
- /*
- * disable all IRQ,
- * and, wait all data was sent
- */
- cr = ssi->cr_own |
- ssi->cr_clk;
-
- rsnd_mod_write(mod, SSICR, cr | EN);
- rsnd_ssi_status_check(mod, DIRQ);
+ ssi->cr_own = cr_own;
+ ssi->cr_mode = cr_mode;
+ ssi->wsr = wsr;
- /*
- * disable SSI,
- * and, wait idle state
- */
- rsnd_mod_write(mod, SSICR, cr); /* disabled all */
- rsnd_ssi_status_check(mod, IIRQ);
-
- if (rsnd_rdai_is_clk_master(rdai)) {
- struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
-
- if (ssi_parent)
- rsnd_ssi_hw_stop(io, ssi_parent);
- else
- rsnd_ssi_master_clk_stop(ssi);
- }
-
- rsnd_mod_power_off(mod);
-
- ssi->chan = 0;
- }
-
- dev_dbg(dev, "%s[%d] hw stopped\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod));
+ return 0;
}
/*
@@ -282,49 +369,30 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
- u32 cr;
+ int ret;
+
+ ssi->usrcnt++;
- cr = FORCE;
+ rsnd_mod_power_on(mod);
- /*
- * always use 32bit system word for easy clock calculation.
- * see also rsnd_ssi_master_clk_enable()
- */
- cr |= SWL_32;
+ ret = rsnd_ssi_master_clk_start(ssi, io);
+ if (ret < 0)
+ return ret;
- /*
- * init clock settings for SSICR
- */
- switch (runtime->sample_bits) {
- case 16:
- cr |= DWL_16;
- break;
- case 32:
- cr |= DWL_24;
- break;
- default:
- return -EIO;
- }
+ if (rsnd_ssi_is_parent(mod, io))
+ return 0;
- if (rdai->bit_clk_inv)
- cr |= SCKP;
- if (rdai->frm_clk_inv)
- cr |= SWSP;
- if (rdai->data_alignment)
- cr |= SDTA;
- if (rdai->sys_delay)
- cr |= DEL;
- if (rsnd_io_is_play(io))
- cr |= TRMD;
+ ret = rsnd_ssi_config_init(ssi, io);
+ if (ret < 0)
+ return ret;
- /*
- * set ssi parameter
- */
- ssi->cr_own = cr;
ssi->err = -1; /* ignore 1st error */
+ /* clear error status */
+ rsnd_ssi_status_clear(mod);
+
+ rsnd_ssi_irq_enable(mod);
+
return 0;
}
@@ -335,12 +403,29 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct device *dev = rsnd_priv_to_dev(priv);
- if (ssi->err > 0)
- dev_warn(dev, "%s[%d] under/over flow err = %d\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod), ssi->err);
+ if (!ssi->usrcnt) {
+ dev_err(dev, "%s[%d] usrcnt error\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod));
+ return -EIO;
+ }
+
+ if (!rsnd_ssi_is_parent(mod, io)) {
+ if (ssi->err > 0)
+ dev_warn(dev, "%s[%d] under/over flow err = %d\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod),
+ ssi->err);
+
+ ssi->cr_own = 0;
+ ssi->err = 0;
+
+ rsnd_ssi_irq_disable(mod);
+ }
- ssi->cr_own = 0;
- ssi->err = 0;
+ rsnd_ssi_master_clk_stop(ssi, io);
+
+ rsnd_mod_power_off(mod);
+
+ ssi->usrcnt--;
return 0;
}
@@ -351,14 +436,13 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
struct snd_pcm_hw_params *params)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
int chan = params_channels(params);
/*
* Already working.
* It will happen if SSI has parent/child connection.
*/
- if (ssi->usrcnt) {
+ if (ssi->usrcnt > 1) {
/*
* it is error if child <-> parent SSI uses
* different channels.
@@ -367,39 +451,83 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
return -EIO;
}
- /* It will be removed on rsnd_ssi_hw_stop */
ssi->chan = chan;
- if (ssi_parent)
- return rsnd_ssi_hw_params(rsnd_mod_get(ssi_parent), io,
- substream, params);
return 0;
}
-static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
+static u32 rsnd_ssi_record_error(struct rsnd_ssi *ssi)
{
struct rsnd_mod *mod = rsnd_mod_get(ssi);
+ u32 status = rsnd_ssi_status_get(mod);
/* under/over flow error */
- if (status & (UIRQ | OIRQ)) {
+ if (status & (UIRQ | OIRQ))
ssi->err++;
- /* clear error status */
- rsnd_mod_write(mod, SSISR, 0);
- }
+ return status;
+}
+
+static int __rsnd_ssi_start(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+ u32 cr;
+
+ cr = ssi->cr_own |
+ ssi->cr_clk |
+ ssi->cr_mode;
+
+ /*
+ * EN will be set via SSIU :: SSI_CONTROL
+ * if Multi channel mode
+ */
+ if (!rsnd_ssi_multi_slaves(io))
+ cr |= EN;
+
+ rsnd_mod_write(mod, SSICR, cr);
+ rsnd_mod_write(mod, SSIWSR, ssi->wsr);
+
+ return 0;
}
static int rsnd_ssi_start(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
+ /*
+ * no limit to start
+ * see also
+ * rsnd_ssi_stop
+ * rsnd_ssi_interrupt
+ */
+ return __rsnd_ssi_start(mod, io, priv);
+}
+
+static int __rsnd_ssi_stop(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+ u32 cr;
- rsnd_src_ssiu_start(mod, io, rsnd_ssi_use_busif(io));
+ /*
+ * disable all IRQ,
+ * and, wait all data was sent
+ */
+ cr = ssi->cr_own |
+ ssi->cr_clk;
- rsnd_ssi_hw_start(ssi, io);
+ rsnd_mod_write(mod, SSICR, cr | EN);
+ rsnd_ssi_status_check(mod, DIRQ);
- rsnd_src_ssi_irq_enable(mod);
+ /*
+ * disable SSI,
+ * and, wait idle state
+ */
+ rsnd_mod_write(mod, SSICR, cr); /* disabled all */
+ rsnd_ssi_status_check(mod, IIRQ);
return 0;
}
@@ -410,15 +538,16 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- rsnd_src_ssi_irq_disable(mod);
-
- rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR));
-
- rsnd_ssi_hw_stop(io, ssi);
-
- rsnd_src_ssiu_stop(mod, io);
+ /*
+ * don't stop if not last user
+ * see also
+ * rsnd_ssi_start
+ * rsnd_ssi_interrupt
+ */
+ if (ssi->usrcnt > 1)
+ return 0;
- return 0;
+ return __rsnd_ssi_stop(mod, io, priv);
}
static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
@@ -426,6 +555,7 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+ struct device *dev = rsnd_priv_to_dev(priv);
int is_dma = rsnd_ssi_is_dma_mode(mod);
u32 status;
bool elapsed = false;
@@ -436,7 +566,7 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
if (!rsnd_io_is_working(io))
goto rsnd_ssi_interrupt_out;
- status = rsnd_mod_read(mod, SSISR);
+ status = rsnd_ssi_record_error(ssi);
/* PIO only */
if (!is_dma && (status & DIRQ)) {
@@ -459,23 +589,24 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
/* DMA only */
if (is_dma && (status & (UIRQ | OIRQ))) {
- struct device *dev = rsnd_priv_to_dev(priv);
-
/*
* restart SSI
*/
dev_dbg(dev, "%s[%d] restart\n",
rsnd_mod_name(mod), rsnd_mod_id(mod));
- rsnd_ssi_stop(mod, io, priv);
- if (ssi->err < 1024)
- rsnd_ssi_start(mod, io, priv);
- else
- dev_warn(dev, "no more SSI restart\n");
+ __rsnd_ssi_stop(mod, io, priv);
+ __rsnd_ssi_start(mod, io, priv);
}
- rsnd_ssi_record_error(ssi, status);
+ if (ssi->err > 1024) {
+ rsnd_ssi_irq_disable(mod);
+ dev_warn(dev, "no more %s[%d] restart\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod));
+ }
+
+ rsnd_ssi_status_clear(mod);
rsnd_ssi_interrupt_out:
spin_unlock(&priv->lock);
@@ -495,15 +626,49 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
/*
* SSI PIO
*/
-static int rsnd_ssi_pio_probe(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
+static void rsnd_ssi_parent_attach(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ if (!__rsnd_ssi_is_pin_sharing(mod))
+ return;
+
+ switch (rsnd_mod_id(mod)) {
+ case 1:
+ case 2:
+ rsnd_dai_connect(rsnd_ssi_mod_get(priv, 0), io, RSND_MOD_SSIP);
+ break;
+ case 4:
+ rsnd_dai_connect(rsnd_ssi_mod_get(priv, 3), io, RSND_MOD_SSIP);
+ break;
+ case 8:
+ rsnd_dai_connect(rsnd_ssi_mod_get(priv, 7), io, RSND_MOD_SSIP);
+ break;
+ }
+}
+
+static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
{
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
int ret;
- ret = devm_request_irq(dev, ssi->info->irq,
+ /*
+ * SSIP/SSIU/IRQ are not needed on
+ * SSI Multi slaves
+ */
+ if (rsnd_ssi_is_multi_slave(mod, io))
+ return 0;
+
+ rsnd_ssi_parent_attach(mod, io, priv);
+
+ ret = rsnd_ssiu_attach(io, mod);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_request_irq(dev, ssi->irq,
rsnd_ssi_interrupt,
IRQF_SHARED,
dev_name(dev), mod);
@@ -513,7 +678,7 @@ static int rsnd_ssi_pio_probe(struct rsnd_mod *mod,
static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.name = SSI_NAME,
- .probe = rsnd_ssi_pio_probe,
+ .probe = rsnd_ssi_common_probe,
.init = rsnd_ssi_init,
.quit = rsnd_ssi_quit,
.start = rsnd_ssi_start,
@@ -526,20 +691,23 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct device *dev = rsnd_priv_to_dev(priv);
- int dma_id = ssi->info->dma_id;
+ int dma_id = 0; /* not needed */
int ret;
- ret = devm_request_irq(dev, ssi->info->irq,
- rsnd_ssi_interrupt,
- IRQF_SHARED,
- dev_name(dev), mod);
+ /*
+ * SSIP/SSIU/IRQ/DMA are not needed on
+ * SSI Multi slaves
+ */
+ if (rsnd_ssi_is_multi_slave(mod, io))
+ return 0;
+
+ ret = rsnd_ssi_common_probe(mod, io, priv);
if (ret)
return ret;
- ret = rsnd_dma_init(
- io, rsnd_mod_to_dma(mod),
- dma_id);
+ ssi->dma = rsnd_dma_attach(io, mod, dma_id);
+ if (IS_ERR(ssi->dma))
+ return PTR_ERR(ssi->dma);
return ret;
}
@@ -550,9 +718,7 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct device *dev = rsnd_priv_to_dev(priv);
- int irq = ssi->info->irq;
-
- rsnd_dma_quit(io, rsnd_mod_to_dma(mod));
+ int irq = ssi->irq;
/* PIO will request IRQ again */
devm_free_irq(dev, irq, mod);
@@ -581,32 +747,6 @@ static int rsnd_ssi_fallback(struct rsnd_mod *mod,
return 0;
}
-static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
-
- rsnd_dma_start(io, dma);
-
- rsnd_ssi_start(mod, io, priv);
-
- return 0;
-}
-
-static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
-
- rsnd_ssi_stop(mod, io, priv);
-
- rsnd_dma_stop(io, dma);
-
- return 0;
-}
-
static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
@@ -630,8 +770,8 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
.remove = rsnd_ssi_dma_remove,
.init = rsnd_ssi_init,
.quit = rsnd_ssi_quit,
- .start = rsnd_ssi_dma_start,
- .stop = rsnd_ssi_dma_stop,
+ .start = rsnd_ssi_start,
+ .stop = rsnd_ssi_stop,
.fallback = rsnd_ssi_fallback,
.hw_params = rsnd_ssi_hw_params,
};
@@ -652,110 +792,76 @@ static struct rsnd_mod_ops rsnd_ssi_non_ops = {
/*
* ssi mod function
*/
-struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
+static void rsnd_ssi_connect(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io)
{
- if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
- id = 0;
-
- return rsnd_mod_get((struct rsnd_ssi *)(priv->ssi) + id);
-}
-
-int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
-{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE);
-}
-
-static void rsnd_ssi_parent_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi)
-{
- struct rsnd_mod *mod = rsnd_mod_get(ssi);
-
- if (!__rsnd_ssi_is_pin_sharing(mod))
- return;
+ struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+ enum rsnd_mod_type types[] = {
+ RSND_MOD_SSI,
+ RSND_MOD_SSIM1,
+ RSND_MOD_SSIM2,
+ RSND_MOD_SSIM3,
+ };
+ enum rsnd_mod_type type;
+ int i;
- switch (rsnd_mod_id(mod)) {
- case 1:
- case 2:
- ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0));
- break;
- case 4:
- ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 3));
- break;
- case 8:
- ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 7));
- break;
+ /* try SSI -> SSIM1 -> SSIM2 -> SSIM3 */
+ for (i = 0; i < ARRAY_SIZE(types); i++) {
+ type = types[i];
+ if (!rsnd_io_to_mod(io, type)) {
+ rsnd_dai_connect(mod, io, type);
+ rsnd_set_slot(rdai, 2 * (i + 1), (i + 1));
+ return;
+ }
}
}
-
-static void rsnd_of_parse_ssi(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
+ struct device_node *playback,
+ struct device_node *capture)
{
+ struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
struct device_node *node;
struct device_node *np;
- struct rsnd_ssi_platform_info *ssi_info;
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
- struct device *dev = &pdev->dev;
- int nr, i;
+ struct rsnd_mod *mod;
+ int i;
node = rsnd_ssi_of_node(priv);
if (!node)
return;
- nr = of_get_child_count(node);
- if (!nr)
- goto rsnd_of_parse_ssi_end;
-
- ssi_info = devm_kzalloc(dev,
- sizeof(struct rsnd_ssi_platform_info) * nr,
- GFP_KERNEL);
- if (!ssi_info) {
- dev_err(dev, "ssi info allocation error\n");
- goto rsnd_of_parse_ssi_end;
- }
-
- info->ssi_info = ssi_info;
- info->ssi_info_nr = nr;
-
- i = -1;
+ i = 0;
for_each_child_of_node(node, np) {
+ mod = rsnd_ssi_mod_get(priv, i);
+ if (np == playback)
+ rsnd_ssi_connect(mod, &rdai->playback);
+ if (np == capture)
+ rsnd_ssi_connect(mod, &rdai->capture);
i++;
+ }
- ssi_info = info->ssi_info + i;
-
- /*
- * pin settings
- */
- if (of_get_property(np, "shared-pin", NULL))
- ssi_info->flags |= RSND_SSI_CLK_PIN_SHARE;
+ of_node_put(node);
+}
- /*
- * irq
- */
- ssi_info->irq = irq_of_parse_and_map(np, 0);
+struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
+{
+ if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
+ id = 0;
- /*
- * DMA
- */
- ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ?
- 0 : 1;
+ return rsnd_mod_get(rsnd_ssi_get(priv, id));
+}
- if (of_get_property(np, "no-busif", NULL))
- ssi_info->flags |= RSND_SSI_NO_BUSIF;
- }
+int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
+{
+ struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-rsnd_of_parse_ssi_end:
- of_node_put(node);
+ return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE);
}
-int rsnd_ssi_probe(struct platform_device *pdev,
- const struct rsnd_of_data *of_data,
- struct rsnd_priv *priv)
+int rsnd_ssi_probe(struct rsnd_priv *priv)
{
- struct rcar_snd_info *info = rsnd_priv_to_info(priv);
- struct rsnd_ssi_platform_info *pinfo;
+ struct device_node *node;
+ struct device_node *np;
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_mod_ops *ops;
struct clk *clk;
@@ -763,50 +869,73 @@ int rsnd_ssi_probe(struct platform_device *pdev,
char name[RSND_SSI_NAME_SIZE];
int i, nr, ret;
- rsnd_of_parse_ssi(pdev, of_data, priv);
+ node = rsnd_ssi_of_node(priv);
+ if (!node)
+ return -EINVAL;
+
+ nr = of_get_child_count(node);
+ if (!nr) {
+ ret = -EINVAL;
+ goto rsnd_ssi_probe_done;
+ }
- /*
- * init SSI
- */
- nr = info->ssi_info_nr;
ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL);
- if (!ssi)
- return -ENOMEM;
+ if (!ssi) {
+ ret = -ENOMEM;
+ goto rsnd_ssi_probe_done;
+ }
priv->ssi = ssi;
priv->ssi_nr = nr;
- for_each_rsnd_ssi(ssi, priv, i) {
- pinfo = &info->ssi_info[i];
+ i = 0;
+ for_each_child_of_node(node, np) {
+ ssi = rsnd_ssi_get(priv, i);
snprintf(name, RSND_SSI_NAME_SIZE, "%s.%d",
SSI_NAME, i);
clk = devm_clk_get(dev, name);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto rsnd_ssi_probe_done;
+ }
- ssi->info = pinfo;
+ if (of_get_property(np, "shared-pin", NULL))
+ ssi->flags |= RSND_SSI_CLK_PIN_SHARE;
+
+ if (of_get_property(np, "no-busif", NULL))
+ ssi->flags |= RSND_SSI_NO_BUSIF;
+
+ ssi->irq = irq_of_parse_and_map(np, 0);
+ if (!ssi->irq) {
+ ret = -EINVAL;
+ goto rsnd_ssi_probe_done;
+ }
ops = &rsnd_ssi_non_ops;
- if (pinfo->dma_id > 0)
- ops = &rsnd_ssi_dma_ops;
- else if (rsnd_ssi_pio_available(ssi))
+ if (of_get_property(np, "pio-transfer", NULL))
ops = &rsnd_ssi_pio_ops;
+ else
+ ops = &rsnd_ssi_dma_ops;
ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
RSND_MOD_SSI, i);
if (ret)
- return ret;
+ goto rsnd_ssi_probe_done;
- rsnd_ssi_parent_setup(priv, ssi);
+ i++;
}
- return 0;
+ ret = 0;
+
+rsnd_ssi_probe_done:
+ of_node_put(node);
+
+ return ret;
}
-void rsnd_ssi_remove(struct platform_device *pdev,
- struct rsnd_priv *priv)
+void rsnd_ssi_remove(struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi;
int i;
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c
new file mode 100644
index 000000000000..06d72828e5bc
--- /dev/null
+++ b/sound/soc/sh/rcar/ssiu.c
@@ -0,0 +1,225 @@
+/*
+ * Renesas R-Car SSIU support
+ *
+ * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "rsnd.h"
+
+#define SSIU_NAME "ssiu"
+
+struct rsnd_ssiu {
+ struct rsnd_mod mod;
+};
+
+#define rsnd_ssiu_nr(priv) ((priv)->ssiu_nr)
+#define for_each_rsnd_ssiu(pos, priv, i) \
+ for (i = 0; \
+ (i < rsnd_ssiu_nr(priv)) && \
+ ((pos) = ((struct rsnd_ssiu *)(priv)->ssiu + i)); \
+ i++)
+
+static int rsnd_ssiu_init(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+ u32 multi_ssi_slaves = rsnd_ssi_multi_slaves(io);
+ int use_busif = rsnd_ssi_use_busif(io);
+ int id = rsnd_mod_id(mod);
+ u32 mask1, val1;
+ u32 mask2, val2;
+
+ /*
+ * SSI_MODE0
+ */
+ rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
+
+ /*
+ * SSI_MODE1
+ */
+ mask1 = (1 << 4) | (1 << 20); /* mask sync bit */
+ mask2 = (1 << 4); /* mask sync bit */
+ val1 = val2 = 0;
+ if (rsnd_ssi_is_pin_sharing(io)) {
+ int shift = -1;
+
+ switch (id) {
+ case 1:
+ shift = 0;
+ break;
+ case 2:
+ shift = 2;
+ break;
+ case 4:
+ shift = 16;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mask1 |= 0x3 << shift;
+ val1 = rsnd_rdai_is_clk_master(rdai) ?
+ 0x2 << shift : 0x1 << shift;
+
+ } else if (multi_ssi_slaves) {
+
+ mask2 |= 0x00000007;
+ mask1 |= 0x0000000f;
+
+ switch (multi_ssi_slaves) {
+ case 0x0206: /* SSI0/1/2/9 */
+ val2 = (1 << 4) | /* SSI0129 sync */
+ (rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1);
+ /* fall through */
+ case 0x0006: /* SSI0/1/2 */
+ val1 = rsnd_rdai_is_clk_master(rdai) ?
+ 0xa : 0x5;
+
+ if (!val2) /* SSI012 sync */
+ val1 |= (1 << 4);
+ }
+ }
+
+ rsnd_mod_bset(mod, SSI_MODE1, mask1, val1);
+ rsnd_mod_bset(mod, SSI_MODE2, mask2, val2);
+
+ return 0;
+}
+
+static struct rsnd_mod_ops rsnd_ssiu_ops_gen1 = {
+ .name = SSIU_NAME,
+ .init = rsnd_ssiu_init,
+};
+
+static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ int ret;
+
+ ret = rsnd_ssiu_init(mod, io, priv);
+ if (ret < 0)
+ return ret;
+
+ if (rsnd_get_slot_width(io) >= 6) {
+ /*
+ * TDM Extend Mode
+ * see
+ * rsnd_ssi_config_init()
+ */
+ rsnd_mod_write(mod, SSI_MODE, 0x1);
+ }
+
+ if (rsnd_ssi_use_busif(io)) {
+ u32 val = rsnd_get_dalign(mod, io);
+
+ rsnd_mod_write(mod, SSI_BUSIF_ADINR,
+ rsnd_get_adinr_bit(mod, io) |
+ rsnd_get_adinr_chan(mod, io));
+ rsnd_mod_write(mod, SSI_BUSIF_MODE, 1);
+ rsnd_mod_write(mod, SSI_BUSIF_DALIGN, val);
+ }
+
+ return 0;
+}
+
+static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ if (!rsnd_ssi_use_busif(io))
+ return 0;
+
+ rsnd_mod_write(mod, SSI_CTRL, 0x1);
+
+ if (rsnd_ssi_multi_slaves(io))
+ rsnd_mod_write(mod, SSI_CONTROL, 0x1);
+
+ return 0;
+}
+
+static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ struct rsnd_priv *priv)
+{
+ if (!rsnd_ssi_use_busif(io))
+ return 0;
+
+ rsnd_mod_write(mod, SSI_CTRL, 0);
+
+ if (rsnd_ssi_multi_slaves(io))
+ rsnd_mod_write(mod, SSI_CONTROL, 0);
+
+ return 0;
+}
+
+static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = {
+ .name = SSIU_NAME,
+ .init = rsnd_ssiu_init_gen2,
+ .start = rsnd_ssiu_start_gen2,
+ .stop = rsnd_ssiu_stop_gen2,
+};
+
+static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id)
+{
+ if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv)))
+ id = 0;
+
+ return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id);
+}
+
+int rsnd_ssiu_attach(struct rsnd_dai_stream *io,
+ struct rsnd_mod *ssi_mod)
+{
+ struct rsnd_priv *priv = rsnd_io_to_priv(io);
+ struct rsnd_mod *mod = rsnd_ssiu_mod_get(priv, rsnd_mod_id(ssi_mod));
+
+ rsnd_mod_confirm_ssi(ssi_mod);
+
+ return rsnd_dai_connect(mod, io, mod->type);
+}
+
+int rsnd_ssiu_probe(struct rsnd_priv *priv)
+{
+ struct device *dev = rsnd_priv_to_dev(priv);
+ struct rsnd_ssiu *ssiu;
+ static struct rsnd_mod_ops *ops;
+ int i, nr, ret;
+
+ /* same number to SSI */
+ nr = priv->ssi_nr;
+ ssiu = devm_kzalloc(dev, sizeof(*ssiu) * nr, GFP_KERNEL);
+ if (!ssiu)
+ return -ENOMEM;
+
+ priv->ssiu = ssiu;
+ priv->ssiu_nr = nr;
+
+ if (rsnd_is_gen1(priv))
+ ops = &rsnd_ssiu_ops_gen1;
+ else
+ ops = &rsnd_ssiu_ops_gen2;
+
+ for_each_rsnd_ssiu(ssiu, priv, i) {
+ ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu),
+ ops, NULL, RSND_MOD_SSIU, i);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+void rsnd_ssiu_remove(struct rsnd_priv *priv)
+{
+ struct rsnd_ssiu *ssiu;
+ int i;
+
+ for_each_rsnd_ssiu(ssiu, priv, i) {
+ rsnd_mod_quit(rsnd_mod_get(ssiu));
+ }
+}
diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c
index d40efc9fe0a9..733f5128eeff 100644
--- a/sound/soc/soc-ac97.c
+++ b/sound/soc/soc-ac97.c
@@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
@@ -38,6 +39,14 @@ struct snd_ac97_reset_cfg {
int gpio_reset;
};
+struct snd_ac97_gpio_priv {
+#ifdef CONFIG_GPIOLIB
+ struct gpio_chip gpio_chip;
+#endif
+ unsigned int gpios_set;
+ struct snd_soc_codec *codec;
+};
+
static struct snd_ac97_bus soc_ac97_bus = {
.ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */
};
@@ -47,6 +56,117 @@ static void soc_ac97_device_release(struct device *dev)
kfree(to_ac97_t(dev));
}
+#ifdef CONFIG_GPIOLIB
+static inline struct snd_soc_codec *gpio_to_codec(struct gpio_chip *chip)
+{
+ struct snd_ac97_gpio_priv *gpio_priv =
+ container_of(chip, struct snd_ac97_gpio_priv, gpio_chip);
+
+ return gpio_priv->codec;
+}
+
+static int snd_soc_ac97_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ if (offset >= AC97_NUM_GPIOS)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int snd_soc_ac97_gpio_direction_in(struct gpio_chip *chip,
+ unsigned offset)
+{
+ struct snd_soc_codec *codec = gpio_to_codec(chip);
+
+ dev_dbg(codec->dev, "set gpio %d to output\n", offset);
+ return snd_soc_update_bits(codec, AC97_GPIO_CFG,
+ 1 << offset, 1 << offset);
+}
+
+static int snd_soc_ac97_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct snd_soc_codec *codec = gpio_to_codec(chip);
+ int ret;
+
+ ret = snd_soc_read(codec, AC97_GPIO_STATUS);
+ dev_dbg(codec->dev, "get gpio %d : %d\n", offset,
+ ret < 0 ? ret : ret & (1 << offset));
+
+ return ret < 0 ? ret : !!(ret & (1 << offset));
+}
+
+static void snd_soc_ac97_gpio_set(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ struct snd_ac97_gpio_priv *gpio_priv =
+ container_of(chip, struct snd_ac97_gpio_priv, gpio_chip);
+ struct snd_soc_codec *codec = gpio_to_codec(chip);
+
+ gpio_priv->gpios_set &= ~(1 << offset);
+ gpio_priv->gpios_set |= (!!value) << offset;
+ snd_soc_write(codec, AC97_GPIO_STATUS, gpio_priv->gpios_set);
+ dev_dbg(codec->dev, "set gpio %d to %d\n", offset, !!value);
+}
+
+static int snd_soc_ac97_gpio_direction_out(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct snd_soc_codec *codec = gpio_to_codec(chip);
+
+ dev_dbg(codec->dev, "set gpio %d to output\n", offset);
+ snd_soc_ac97_gpio_set(chip, offset, value);
+ return snd_soc_update_bits(codec, AC97_GPIO_CFG, 1 << offset, 0);
+}
+
+static struct gpio_chip snd_soc_ac97_gpio_chip = {
+ .label = "snd_soc_ac97",
+ .owner = THIS_MODULE,
+ .request = snd_soc_ac97_gpio_request,
+ .direction_input = snd_soc_ac97_gpio_direction_in,
+ .get = snd_soc_ac97_gpio_get,
+ .direction_output = snd_soc_ac97_gpio_direction_out,
+ .set = snd_soc_ac97_gpio_set,
+ .can_sleep = 1,
+};
+
+static int snd_soc_ac97_init_gpio(struct snd_ac97 *ac97,
+ struct snd_soc_codec *codec)
+{
+ struct snd_ac97_gpio_priv *gpio_priv;
+ int ret;
+
+ gpio_priv = devm_kzalloc(codec->dev, sizeof(*gpio_priv), GFP_KERNEL);
+ if (!gpio_priv)
+ return -ENOMEM;
+ ac97->gpio_priv = gpio_priv;
+ gpio_priv->codec = codec;
+ gpio_priv->gpio_chip = snd_soc_ac97_gpio_chip;
+ gpio_priv->gpio_chip.ngpio = AC97_NUM_GPIOS;
+ gpio_priv->gpio_chip.dev = codec->dev;
+ gpio_priv->gpio_chip.base = -1;
+
+ ret = gpiochip_add(&gpio_priv->gpio_chip);
+ if (ret != 0)
+ dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+ return ret;
+}
+
+static void snd_soc_ac97_free_gpio(struct snd_ac97 *ac97)
+{
+ gpiochip_remove(&ac97->gpio_priv->gpio_chip);
+}
+#else
+static int snd_soc_ac97_init_gpio(struct snd_ac97 *ac97,
+ struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static void snd_soc_ac97_free_gpio(struct snd_ac97 *ac97)
+{
+}
+#endif
+
/**
* snd_soc_alloc_ac97_codec() - Allocate new a AC'97 device
* @codec: The CODEC for which to create the AC'97 device
@@ -119,6 +239,10 @@ struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
if (ret)
goto err_put_device;
+ ret = snd_soc_ac97_init_gpio(ac97, codec);
+ if (ret)
+ goto err_put_device;
+
return ac97;
err_put_device:
@@ -135,6 +259,7 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
*/
void snd_soc_free_ac97_codec(struct snd_ac97 *ac97)
{
+ snd_soc_ac97_free_gpio(ac97);
device_del(&ac97->dev);
ac97->bus = NULL;
put_device(&ac97->dev);
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 12a9820feac1..875733c52953 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -630,6 +630,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
struct snd_pcm *be_pcm;
char new_name[64];
int ret = 0, direction = 0;
+ int playback = 0, capture = 0;
if (rtd->num_codecs > 1) {
dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n");
@@ -641,11 +642,27 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
rtd->dai_link->stream_name, codec_dai->name, num);
if (codec_dai->driver->playback.channels_min)
+ playback = 1;
+ if (codec_dai->driver->capture.channels_min)
+ capture = 1;
+
+ capture = capture && cpu_dai->driver->capture.channels_min;
+ playback = playback && cpu_dai->driver->playback.channels_min;
+
+ /*
+ * Compress devices are unidirectional so only one of the directions
+ * should be set, check for that (xor)
+ */
+ if (playback + capture != 1) {
+ dev_err(rtd->card->dev, "Invalid direction for compress P %d, C %d\n",
+ playback, capture);
+ return -EINVAL;
+ }
+
+ if(playback)
direction = SND_COMPRESS_PLAYBACK;
- else if (codec_dai->driver->capture.channels_min)
- direction = SND_COMPRESS_CAPTURE;
else
- return -EINVAL;
+ direction = SND_COMPRESS_CAPTURE;
compr = kzalloc(sizeof(*compr), GFP_KERNEL);
if (compr == NULL) {
@@ -689,7 +706,13 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
compr->ops->copy = soc_compr_copy;
mutex_init(&compr->lock);
- ret = snd_compress_new(rtd->card->snd_card, num, direction, compr);
+
+ snprintf(new_name, sizeof(new_name), "%s %s-%d",
+ rtd->dai_link->stream_name,
+ rtd->codec_dai->name, num);
+
+ ret = snd_compress_new(rtd->card->snd_card, num, direction,
+ new_name, compr);
if (ret < 0) {
pr_err("compress asoc: can't create compress for codec %s\n",
codec->component.name);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a1305f827a98..790ee2bf1a47 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -537,26 +537,75 @@ static inline void snd_soc_debugfs_exit(void)
struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
const char *dai_link, int stream)
{
- int i;
+ struct snd_soc_pcm_runtime *rtd;
- for (i = 0; i < card->num_links; i++) {
- if (card->rtd[i].dai_link->no_pcm &&
- !strcmp(card->rtd[i].dai_link->name, dai_link))
- return card->rtd[i].pcm->streams[stream].substream;
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ if (rtd->dai_link->no_pcm &&
+ !strcmp(rtd->dai_link->name, dai_link))
+ return rtd->pcm->streams[stream].substream;
}
dev_dbg(card->dev, "ASoC: failed to find dai link %s\n", dai_link);
return NULL;
}
EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream);
+static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
+ struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
+{
+ struct snd_soc_pcm_runtime *rtd;
+
+ rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL);
+ if (!rtd)
+ return NULL;
+
+ rtd->card = card;
+ rtd->dai_link = dai_link;
+ rtd->codec_dais = kzalloc(sizeof(struct snd_soc_dai *) *
+ dai_link->num_codecs,
+ GFP_KERNEL);
+ if (!rtd->codec_dais) {
+ kfree(rtd);
+ return NULL;
+ }
+
+ return rtd;
+}
+
+static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd)
+{
+ if (rtd && rtd->codec_dais)
+ kfree(rtd->codec_dais);
+ kfree(rtd);
+}
+
+static void soc_add_pcm_runtime(struct snd_soc_card *card,
+ struct snd_soc_pcm_runtime *rtd)
+{
+ list_add_tail(&rtd->list, &card->rtd_list);
+ rtd->num = card->num_rtd;
+ card->num_rtd++;
+}
+
+static void soc_remove_pcm_runtimes(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd, *_rtd;
+
+ list_for_each_entry_safe(rtd, _rtd, &card->rtd_list, list) {
+ list_del(&rtd->list);
+ soc_free_pcm_runtime(rtd);
+ }
+
+ card->num_rtd = 0;
+}
+
struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
const char *dai_link)
{
- int i;
+ struct snd_soc_pcm_runtime *rtd;
- for (i = 0; i < card->num_links; i++) {
- if (!strcmp(card->rtd[i].dai_link->name, dai_link))
- return &card->rtd[i];
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ if (!strcmp(rtd->dai_link->name, dai_link))
+ return rtd;
}
dev_dbg(card->dev, "ASoC: failed to find rtd %s\n", dai_link);
return NULL;
@@ -578,7 +627,8 @@ int snd_soc_suspend(struct device *dev)
{
struct snd_soc_card *card = dev_get_drvdata(dev);
struct snd_soc_codec *codec;
- int i, j;
+ struct snd_soc_pcm_runtime *rtd;
+ int i;
/* If the card is not initialized yet there is nothing to do */
if (!card->instantiated)
@@ -595,13 +645,13 @@ int snd_soc_suspend(struct device *dev)
snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);
/* mute any active DACs */
- for (i = 0; i < card->num_rtd; i++) {
+ list_for_each_entry(rtd, &card->rtd_list, list) {
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (rtd->dai_link->ignore_suspend)
continue;
- for (j = 0; j < card->rtd[i].num_codecs; j++) {
- struct snd_soc_dai *dai = card->rtd[i].codec_dais[j];
+ for (i = 0; i < rtd->num_codecs; i++) {
+ struct snd_soc_dai *dai = rtd->codec_dais[i];
struct snd_soc_dai_driver *drv = dai->driver;
if (drv->ops->digital_mute && dai->playback_active)
@@ -610,20 +660,20 @@ int snd_soc_suspend(struct device *dev)
}
/* suspend all pcms */
- for (i = 0; i < card->num_rtd; i++) {
- if (card->rtd[i].dai_link->ignore_suspend)
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ if (rtd->dai_link->ignore_suspend)
continue;
- snd_pcm_suspend_all(card->rtd[i].pcm);
+ snd_pcm_suspend_all(rtd->pcm);
}
if (card->suspend_pre)
card->suspend_pre(card);
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (rtd->dai_link->ignore_suspend)
continue;
if (cpu_dai->driver->suspend && !cpu_dai->driver->bus_control)
@@ -631,19 +681,19 @@ int snd_soc_suspend(struct device *dev)
}
/* close any waiting streams */
- for (i = 0; i < card->num_rtd; i++)
- flush_delayed_work(&card->rtd[i].delayed_work);
+ list_for_each_entry(rtd, &card->rtd_list, list)
+ flush_delayed_work(&rtd->delayed_work);
- for (i = 0; i < card->num_rtd; i++) {
+ list_for_each_entry(rtd, &card->rtd_list, list) {
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (rtd->dai_link->ignore_suspend)
continue;
- snd_soc_dapm_stream_event(&card->rtd[i],
+ snd_soc_dapm_stream_event(rtd,
SNDRV_PCM_STREAM_PLAYBACK,
SND_SOC_DAPM_STREAM_SUSPEND);
- snd_soc_dapm_stream_event(&card->rtd[i],
+ snd_soc_dapm_stream_event(rtd,
SNDRV_PCM_STREAM_CAPTURE,
SND_SOC_DAPM_STREAM_SUSPEND);
}
@@ -690,10 +740,10 @@ int snd_soc_suspend(struct device *dev)
}
}
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (rtd->dai_link->ignore_suspend)
continue;
if (cpu_dai->driver->suspend && cpu_dai->driver->bus_control)
@@ -717,8 +767,9 @@ static void soc_resume_deferred(struct work_struct *work)
{
struct snd_soc_card *card =
container_of(work, struct snd_soc_card, deferred_resume_work);
+ struct snd_soc_pcm_runtime *rtd;
struct snd_soc_codec *codec;
- int i, j;
+ int i;
/* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
* so userspace apps are blocked from touching us
@@ -733,10 +784,10 @@ static void soc_resume_deferred(struct work_struct *work)
card->resume_pre(card);
/* resume control bus DAIs */
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (rtd->dai_link->ignore_suspend)
continue;
if (cpu_dai->driver->resume && cpu_dai->driver->bus_control)
@@ -751,28 +802,28 @@ static void soc_resume_deferred(struct work_struct *work)
}
}
- for (i = 0; i < card->num_rtd; i++) {
+ list_for_each_entry(rtd, &card->rtd_list, list) {
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (rtd->dai_link->ignore_suspend)
continue;
- snd_soc_dapm_stream_event(&card->rtd[i],
+ snd_soc_dapm_stream_event(rtd,
SNDRV_PCM_STREAM_PLAYBACK,
SND_SOC_DAPM_STREAM_RESUME);
- snd_soc_dapm_stream_event(&card->rtd[i],
+ snd_soc_dapm_stream_event(rtd,
SNDRV_PCM_STREAM_CAPTURE,
SND_SOC_DAPM_STREAM_RESUME);
}
/* unmute any active DACs */
- for (i = 0; i < card->num_rtd; i++) {
+ list_for_each_entry(rtd, &card->rtd_list, list) {
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (rtd->dai_link->ignore_suspend)
continue;
- for (j = 0; j < card->rtd[i].num_codecs; j++) {
- struct snd_soc_dai *dai = card->rtd[i].codec_dais[j];
+ for (i = 0; i < rtd->num_codecs; i++) {
+ struct snd_soc_dai *dai = rtd->codec_dais[i];
struct snd_soc_dai_driver *drv = dai->driver;
if (drv->ops->digital_mute && dai->playback_active)
@@ -780,10 +831,10 @@ static void soc_resume_deferred(struct work_struct *work)
}
}
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- if (card->rtd[i].dai_link->ignore_suspend)
+ if (rtd->dai_link->ignore_suspend)
continue;
if (cpu_dai->driver->resume && !cpu_dai->driver->bus_control)
@@ -808,15 +859,14 @@ int snd_soc_resume(struct device *dev)
{
struct snd_soc_card *card = dev_get_drvdata(dev);
bool bus_control = false;
- int i;
+ struct snd_soc_pcm_runtime *rtd;
/* If the card is not initialized yet there is nothing to do */
if (!card->instantiated)
return 0;
/* activate pins from sleep state */
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+ list_for_each_entry(rtd, &card->rtd_list, list) {
struct snd_soc_dai **codec_dais = rtd->codec_dais;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int j;
@@ -837,8 +887,8 @@ int snd_soc_resume(struct device *dev)
* have that problem and may take a substantial amount of time to resume
* due to I/O costs and anti-pop so handle them out of line.
*/
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
bus_control |= cpu_dai->driver->bus_control;
}
if (bus_control) {
@@ -910,18 +960,41 @@ static struct snd_soc_dai *snd_soc_find_dai(
return NULL;
}
-static int soc_bind_dai_link(struct snd_soc_card *card, int num)
+static bool soc_is_dai_link_bound(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_link)
{
- struct snd_soc_dai_link *dai_link = &card->dai_link[num];
- struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
+ struct snd_soc_pcm_runtime *rtd;
+
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ if (rtd->dai_link == dai_link)
+ return true;
+ }
+
+ return false;
+}
+
+static int soc_bind_dai_link(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_link)
+{
+ struct snd_soc_pcm_runtime *rtd;
struct snd_soc_dai_link_component *codecs = dai_link->codecs;
struct snd_soc_dai_link_component cpu_dai_component;
- struct snd_soc_dai **codec_dais = rtd->codec_dais;
+ struct snd_soc_dai **codec_dais;
struct snd_soc_platform *platform;
const char *platform_name;
int i;
- dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num);
+ dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name);
+
+ rtd = soc_new_pcm_runtime(card, dai_link);
+ if (!rtd)
+ return -ENOMEM;
+
+ if (soc_is_dai_link_bound(card, dai_link)) {
+ dev_dbg(card->dev, "ASoC: dai link %s already bound\n",
+ dai_link->name);
+ return 0;
+ }
cpu_dai_component.name = dai_link->cpu_name;
cpu_dai_component.of_node = dai_link->cpu_of_node;
@@ -930,18 +1003,19 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
if (!rtd->cpu_dai) {
dev_err(card->dev, "ASoC: CPU DAI %s not registered\n",
dai_link->cpu_dai_name);
- return -EPROBE_DEFER;
+ goto _err_defer;
}
rtd->num_codecs = dai_link->num_codecs;
/* Find CODEC from registered CODECs */
+ codec_dais = rtd->codec_dais;
for (i = 0; i < rtd->num_codecs; i++) {
codec_dais[i] = snd_soc_find_dai(&codecs[i]);
if (!codec_dais[i]) {
dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
codecs[i].dai_name);
- return -EPROBE_DEFER;
+ goto _err_defer;
}
}
@@ -973,9 +1047,12 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
return -EPROBE_DEFER;
}
- card->num_rtd++;
-
+ soc_add_pcm_runtime(card, rtd);
return 0;
+
+_err_defer:
+ soc_free_pcm_runtime(rtd);
+ return -EPROBE_DEFER;
}
static void soc_remove_component(struct snd_soc_component *component)
@@ -1014,9 +1091,9 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order)
}
}
-static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
+static void soc_remove_link_dais(struct snd_soc_card *card,
+ struct snd_soc_pcm_runtime *rtd, int order)
{
- struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
int i;
/* unregister the rtd device */
@@ -1032,10 +1109,9 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
soc_remove_dai(rtd->cpu_dai, order);
}
-static void soc_remove_link_components(struct snd_soc_card *card, int num,
- int order)
+static void soc_remove_link_components(struct snd_soc_card *card,
+ struct snd_soc_pcm_runtime *rtd, int order)
{
- struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_platform *platform = rtd->platform;
struct snd_soc_component *component;
@@ -1061,23 +1137,200 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num,
static void soc_remove_dai_links(struct snd_soc_card *card)
{
- int dai, order;
+ int order;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai_link *link, *_link;
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
order++) {
- for (dai = 0; dai < card->num_rtd; dai++)
- soc_remove_link_dais(card, dai, order);
+ list_for_each_entry(rtd, &card->rtd_list, list)
+ soc_remove_link_dais(card, rtd, order);
}
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
order++) {
- for (dai = 0; dai < card->num_rtd; dai++)
- soc_remove_link_components(card, dai, order);
+ list_for_each_entry(rtd, &card->rtd_list, list)
+ soc_remove_link_components(card, rtd, order);
}
- card->num_rtd = 0;
+ list_for_each_entry_safe(link, _link, &card->dai_link_list, list) {
+ if (link->dobj.type == SND_SOC_DOBJ_DAI_LINK)
+ dev_warn(card->dev, "Topology forgot to remove link %s?\n",
+ link->name);
+
+ list_del(&link->list);
+ card->num_dai_links--;
+ }
}
+static int snd_soc_init_multicodec(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_link)
+{
+ /* Legacy codec/codec_dai link is a single entry in multicodec */
+ if (dai_link->codec_name || dai_link->codec_of_node ||
+ dai_link->codec_dai_name) {
+ dai_link->num_codecs = 1;
+
+ dai_link->codecs = devm_kzalloc(card->dev,
+ sizeof(struct snd_soc_dai_link_component),
+ GFP_KERNEL);
+ if (!dai_link->codecs)
+ return -ENOMEM;
+
+ dai_link->codecs[0].name = dai_link->codec_name;
+ dai_link->codecs[0].of_node = dai_link->codec_of_node;
+ dai_link->codecs[0].dai_name = dai_link->codec_dai_name;
+ }
+
+ if (!dai_link->codecs) {
+ dev_err(card->dev, "ASoC: DAI link has no CODECs\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int soc_init_dai_link(struct snd_soc_card *card,
+ struct snd_soc_dai_link *link)
+{
+ int i, ret;
+
+ ret = snd_soc_init_multicodec(card, link);
+ if (ret) {
+ dev_err(card->dev, "ASoC: failed to init multicodec\n");
+ return ret;
+ }
+
+ for (i = 0; i < link->num_codecs; i++) {
+ /*
+ * Codec must be specified by 1 of name or OF node,
+ * not both or neither.
+ */
+ if (!!link->codecs[i].name ==
+ !!link->codecs[i].of_node) {
+ dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n",
+ link->name);
+ return -EINVAL;
+ }
+ /* Codec DAI name must be specified */
+ if (!link->codecs[i].dai_name) {
+ dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n",
+ link->name);
+ return -EINVAL;
+ }
+ }
+
+ /*
+ * Platform may be specified by either name or OF node, but
+ * can be left unspecified, and a dummy platform will be used.
+ */
+ if (link->platform_name && link->platform_of_node) {
+ dev_err(card->dev,
+ "ASoC: Both platform name/of_node are set for %s\n",
+ link->name);
+ return -EINVAL;
+ }
+
+ /*
+ * CPU device may be specified by either name or OF node, but
+ * can be left unspecified, and will be matched based on DAI
+ * name alone..
+ */
+ if (link->cpu_name && link->cpu_of_node) {
+ dev_err(card->dev,
+ "ASoC: Neither/both cpu name/of_node are set for %s\n",
+ link->name);
+ return -EINVAL;
+ }
+ /*
+ * At least one of CPU DAI name or CPU device name/node must be
+ * specified
+ */
+ if (!link->cpu_dai_name &&
+ !(link->cpu_name || link->cpu_of_node)) {
+ dev_err(card->dev,
+ "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
+ link->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * snd_soc_add_dai_link - Add a DAI link dynamically
+ * @card: The ASoC card to which the DAI link is added
+ * @dai_link: The new DAI link to add
+ *
+ * This function adds a DAI link to the ASoC card's link list.
+ *
+ * Note: Topology can use this API to add DAI links when probing the
+ * topology component. And machine drivers can still define static
+ * DAI links in dai_link array.
+ */
+int snd_soc_add_dai_link(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_link)
+{
+ if (dai_link->dobj.type
+ && dai_link->dobj.type != SND_SOC_DOBJ_DAI_LINK) {
+ dev_err(card->dev, "Invalid dai link type %d\n",
+ dai_link->dobj.type);
+ return -EINVAL;
+ }
+
+ lockdep_assert_held(&client_mutex);
+ /* Notify the machine driver for extra initialization
+ * on the link created by topology.
+ */
+ if (dai_link->dobj.type && card->add_dai_link)
+ card->add_dai_link(card, dai_link);
+
+ list_add_tail(&dai_link->list, &card->dai_link_list);
+ card->num_dai_links++;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_dai_link);
+
+/**
+ * snd_soc_remove_dai_link - Remove a DAI link from the list
+ * @card: The ASoC card that owns the link
+ * @dai_link: The DAI link to remove
+ *
+ * This function removes a DAI link from the ASoC card's link list.
+ *
+ * For DAI links previously added by topology, topology should
+ * remove them by using the dobj embedded in the link.
+ */
+void snd_soc_remove_dai_link(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_link)
+{
+ struct snd_soc_dai_link *link, *_link;
+
+ if (dai_link->dobj.type
+ && dai_link->dobj.type != SND_SOC_DOBJ_DAI_LINK) {
+ dev_err(card->dev, "Invalid dai link type %d\n",
+ dai_link->dobj.type);
+ return;
+ }
+
+ lockdep_assert_held(&client_mutex);
+ /* Notify the machine driver for extra destruction
+ * on the link created by topology.
+ */
+ if (dai_link->dobj.type && card->remove_dai_link)
+ card->remove_dai_link(card, dai_link);
+
+ list_for_each_entry_safe(link, _link, &card->dai_link_list, list) {
+ if (link == dai_link) {
+ list_del(&link->list);
+ card->num_dai_links--;
+ return;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(snd_soc_remove_dai_link);
+
static void soc_set_name_prefix(struct snd_soc_card *card,
struct snd_soc_component *component)
{
@@ -1160,6 +1413,16 @@ static int soc_probe_component(struct snd_soc_card *card,
component->name);
}
+ /* machine specific init */
+ if (component->init) {
+ ret = component->init(component);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "Failed to do machine specific init %d\n", ret);
+ goto err_probe;
+ }
+ }
+
if (component->controls)
snd_soc_add_component_controls(component, component->controls,
component->num_controls);
@@ -1220,10 +1483,10 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd,
return 0;
}
-static int soc_probe_link_components(struct snd_soc_card *card, int num,
+static int soc_probe_link_components(struct snd_soc_card *card,
+ struct snd_soc_pcm_runtime *rtd,
int order)
{
- struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
struct snd_soc_platform *platform = rtd->platform;
struct snd_soc_component *component;
int i, ret;
@@ -1283,35 +1546,35 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
{
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dapm_widget *play_w, *capture_w;
+ struct snd_soc_dapm_widget *sink, *source;
int ret;
if (rtd->num_codecs > 1)
dev_warn(card->dev, "ASoC: Multiple codecs not supported yet\n");
/* link the DAI widgets */
- play_w = codec_dai->playback_widget;
- capture_w = cpu_dai->capture_widget;
- if (play_w && capture_w) {
+ sink = codec_dai->playback_widget;
+ source = cpu_dai->capture_widget;
+ if (sink && source) {
ret = snd_soc_dapm_new_pcm(card, dai_link->params,
- dai_link->num_params, capture_w,
- play_w);
+ dai_link->num_params,
+ source, sink);
if (ret != 0) {
dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
- play_w->name, capture_w->name, ret);
+ sink->name, source->name, ret);
return ret;
}
}
- play_w = cpu_dai->playback_widget;
- capture_w = codec_dai->capture_widget;
- if (play_w && capture_w) {
+ sink = cpu_dai->playback_widget;
+ source = codec_dai->capture_widget;
+ if (sink && source) {
ret = snd_soc_dapm_new_pcm(card, dai_link->params,
- dai_link->num_params, capture_w,
- play_w);
+ dai_link->num_params,
+ source, sink);
if (ret != 0) {
dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
- play_w->name, capture_w->name, ret);
+ sink->name, source->name, ret);
return ret;
}
}
@@ -1319,15 +1582,15 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
return 0;
}
-static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
+static int soc_probe_link_dais(struct snd_soc_card *card,
+ struct snd_soc_pcm_runtime *rtd, int order)
{
- struct snd_soc_dai_link *dai_link = &card->dai_link[num];
- struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int i, ret;
dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
- card->name, num, order);
+ card->name, rtd->num, order);
/* set default power off timeout */
rtd->pmdown_time = pmdown_time;
@@ -1372,7 +1635,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
if (cpu_dai->driver->compress_new) {
/*create compress_device"*/
- ret = cpu_dai->driver->compress_new(rtd, num);
+ ret = cpu_dai->driver->compress_new(rtd, rtd->num);
if (ret < 0) {
dev_err(card->dev, "ASoC: can't create compress %s\n",
dai_link->stream_name);
@@ -1382,7 +1645,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
if (!dai_link->params) {
/* create the pcm */
- ret = soc_new_pcm(rtd, num);
+ ret = soc_new_pcm(rtd, rtd->num);
if (ret < 0) {
dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
dai_link->stream_name, ret);
@@ -1404,65 +1667,81 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
static int soc_bind_aux_dev(struct snd_soc_card *card, int num)
{
- struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
- const char *name = aux_dev->codec_name;
-
- rtd->component = soc_find_component(aux_dev->codec_of_node, name);
- if (!rtd->component) {
- if (aux_dev->codec_of_node)
- name = of_node_full_name(aux_dev->codec_of_node);
-
- dev_err(card->dev, "ASoC: %s not registered\n", name);
- return -EPROBE_DEFER;
+ struct snd_soc_component *component;
+ const char *name;
+ struct device_node *codec_of_node;
+
+ if (aux_dev->codec_of_node || aux_dev->codec_name) {
+ /* codecs, usually analog devices */
+ name = aux_dev->codec_name;
+ codec_of_node = aux_dev->codec_of_node;
+ component = soc_find_component(codec_of_node, name);
+ if (!component) {
+ if (codec_of_node)
+ name = of_node_full_name(codec_of_node);
+ goto err_defer;
+ }
+ } else if (aux_dev->name) {
+ /* generic components */
+ name = aux_dev->name;
+ component = soc_find_component(NULL, name);
+ if (!component)
+ goto err_defer;
+ } else {
+ dev_err(card->dev, "ASoC: Invalid auxiliary device\n");
+ return -EINVAL;
}
- /*
- * Some places still reference rtd->codec, so we have to keep that
- * initialized if the component is a CODEC. Once all those references
- * have been removed, this code can be removed as well.
- */
- rtd->codec = rtd->component->codec;
-
+ component->init = aux_dev->init;
+ list_add(&component->list_aux, &card->aux_comp_list);
return 0;
+
+err_defer:
+ dev_err(card->dev, "ASoC: %s not registered\n", name);
+ return -EPROBE_DEFER;
}
-static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
+static int soc_probe_aux_devices(struct snd_soc_card *card)
{
- struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
- struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
+ struct snd_soc_component *comp;
+ int order;
int ret;
- ret = soc_probe_component(card, rtd->component);
- if (ret < 0)
- return ret;
-
- /* do machine specific initialization */
- if (aux_dev->init) {
- ret = aux_dev->init(rtd->component);
- if (ret < 0) {
- dev_err(card->dev, "ASoC: failed to init %s: %d\n",
- aux_dev->name, ret);
- return ret;
+ for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
+ order++) {
+ list_for_each_entry(comp, &card->aux_comp_list, list_aux) {
+ if (comp->driver->probe_order == order) {
+ ret = soc_probe_component(card, comp);
+ if (ret < 0) {
+ dev_err(card->dev,
+ "ASoC: failed to probe aux component %s %d\n",
+ comp->name, ret);
+ return ret;
+ }
+ }
}
}
- return soc_post_component_init(rtd, aux_dev->name);
+ return 0;
}
-static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
+static void soc_remove_aux_devices(struct snd_soc_card *card)
{
- struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
- struct snd_soc_component *component = rtd->component;
+ struct snd_soc_component *comp, *_comp;
+ int order;
- /* unregister the rtd device */
- if (rtd->dev_registered) {
- device_unregister(rtd->dev);
- rtd->dev_registered = 0;
+ for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
+ order++) {
+ list_for_each_entry_safe(comp, _comp,
+ &card->aux_comp_list, list_aux) {
+ if (comp->driver->remove_order == order) {
+ soc_remove_component(comp);
+ /* remove it from the card's aux_comp_list */
+ list_del(&comp->list_aux);
+ }
+ }
}
-
- if (component)
- soc_remove_component(component);
}
static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
@@ -1552,6 +1831,8 @@ EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt);
static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai_link *dai_link;
int ret, i, order;
mutex_lock(&client_mutex);
@@ -1559,7 +1840,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
/* bind DAIs */
for (i = 0; i < card->num_links; i++) {
- ret = soc_bind_dai_link(card, i);
+ ret = soc_bind_dai_link(card, &card->dai_link[i]);
if (ret != 0)
goto base_error;
}
@@ -1571,6 +1852,10 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
goto base_error;
}
+ /* add predefined DAI links to the list */
+ for (i = 0; i < card->num_links; i++)
+ snd_soc_add_dai_link(card, card->dai_link+i);
+
/* initialize the register cache for each available codec */
list_for_each_entry(codec, &codec_list, list) {
if (codec->cache_init)
@@ -1624,8 +1909,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
/* probe all components used by DAI links on this card */
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
order++) {
- for (i = 0; i < card->num_links; i++) {
- ret = soc_probe_link_components(card, i, order);
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ ret = soc_probe_link_components(card, rtd, order);
if (ret < 0) {
dev_err(card->dev,
"ASoC: failed to instantiate card %d\n",
@@ -1635,11 +1920,31 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
+ /* probe auxiliary components */
+ ret = soc_probe_aux_devices(card);
+ if (ret < 0)
+ goto probe_dai_err;
+
+ /* Find new DAI links added during probing components and bind them.
+ * Components with topology may bring new DAIs and DAI links.
+ */
+ list_for_each_entry(dai_link, &card->dai_link_list, list) {
+ if (soc_is_dai_link_bound(card, dai_link))
+ continue;
+
+ ret = soc_init_dai_link(card, dai_link);
+ if (ret)
+ goto probe_dai_err;
+ ret = soc_bind_dai_link(card, dai_link);
+ if (ret)
+ goto probe_dai_err;
+ }
+
/* probe all DAI links on this card */
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
order++) {
- for (i = 0; i < card->num_links; i++) {
- ret = soc_probe_link_dais(card, i, order);
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ ret = soc_probe_link_dais(card, rtd, order);
if (ret < 0) {
dev_err(card->dev,
"ASoC: failed to instantiate card %d\n",
@@ -1649,16 +1954,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
- for (i = 0; i < card->num_aux_devs; i++) {
- ret = soc_probe_aux_dev(card, i);
- if (ret < 0) {
- dev_err(card->dev,
- "ASoC: failed to add auxiliary devices %d\n",
- ret);
- goto probe_aux_dev_err;
- }
- }
-
snd_soc_dapm_link_dai_widgets(card);
snd_soc_dapm_connect_dai_link_widgets(card);
@@ -1718,8 +2013,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
return 0;
probe_aux_dev_err:
- for (i = 0; i < card->num_aux_devs; i++)
- soc_remove_aux_dev(card, i);
+ soc_remove_aux_devices(card);
probe_dai_err:
soc_remove_dai_links(card);
@@ -1733,6 +2027,7 @@ card_probe_error:
snd_card_free(card->snd_card);
base_error:
+ soc_remove_pcm_runtimes(card);
mutex_unlock(&card->mutex);
mutex_unlock(&client_mutex);
@@ -1763,20 +2058,18 @@ static int soc_probe(struct platform_device *pdev)
static int soc_cleanup_card_resources(struct snd_soc_card *card)
{
- int i;
+ struct snd_soc_pcm_runtime *rtd;
/* make sure any delayed work runs */
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+ list_for_each_entry(rtd, &card->rtd_list, list)
flush_delayed_work(&rtd->delayed_work);
- }
-
- /* remove auxiliary devices */
- for (i = 0; i < card->num_aux_devs; i++)
- soc_remove_aux_dev(card, i);
/* remove and free each DAI */
soc_remove_dai_links(card);
+ soc_remove_pcm_runtimes(card);
+
+ /* remove auxiliary devices */
+ soc_remove_aux_devices(card);
soc_cleanup_card_debugfs(card);
@@ -1803,29 +2096,26 @@ static int soc_remove(struct platform_device *pdev)
int snd_soc_poweroff(struct device *dev)
{
struct snd_soc_card *card = dev_get_drvdata(dev);
- int i;
+ struct snd_soc_pcm_runtime *rtd;
if (!card->instantiated)
return 0;
/* Flush out pmdown_time work - we actually do want to run it
* now, we're shutting down so no imminent restart. */
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+ list_for_each_entry(rtd, &card->rtd_list, list)
flush_delayed_work(&rtd->delayed_work);
- }
snd_soc_dapm_shutdown(card);
/* deactivate pins to sleep state */
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+ list_for_each_entry(rtd, &card->rtd_list, list) {
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int j;
+ int i;
pinctrl_pm_select_sleep_state(cpu_dai->dev);
- for (j = 0; j < rtd->num_codecs; j++) {
- struct snd_soc_dai *codec_dai = rtd->codec_dais[j];
+ for (i = 0; i < rtd->num_codecs; i++) {
+ struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
pinctrl_pm_select_sleep_state(codec_dai->dev);
}
}
@@ -2301,33 +2591,6 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
}
EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
-static int snd_soc_init_multicodec(struct snd_soc_card *card,
- struct snd_soc_dai_link *dai_link)
-{
- /* Legacy codec/codec_dai link is a single entry in multicodec */
- if (dai_link->codec_name || dai_link->codec_of_node ||
- dai_link->codec_dai_name) {
- dai_link->num_codecs = 1;
-
- dai_link->codecs = devm_kzalloc(card->dev,
- sizeof(struct snd_soc_dai_link_component),
- GFP_KERNEL);
- if (!dai_link->codecs)
- return -ENOMEM;
-
- dai_link->codecs[0].name = dai_link->codec_name;
- dai_link->codecs[0].of_node = dai_link->codec_of_node;
- dai_link->codecs[0].dai_name = dai_link->codec_dai_name;
- }
-
- if (!dai_link->codecs) {
- dev_err(card->dev, "ASoC: DAI link has no CODECs\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
/**
* snd_soc_register_card - Register a card with the ASoC core
*
@@ -2336,7 +2599,8 @@ static int snd_soc_init_multicodec(struct snd_soc_card *card,
*/
int snd_soc_register_card(struct snd_soc_card *card)
{
- int i, j, ret;
+ int i, ret;
+ struct snd_soc_pcm_runtime *rtd;
if (!card->name || !card->dev)
return -EINVAL;
@@ -2344,63 +2608,11 @@ int snd_soc_register_card(struct snd_soc_card *card)
for (i = 0; i < card->num_links; i++) {
struct snd_soc_dai_link *link = &card->dai_link[i];
- ret = snd_soc_init_multicodec(card, link);
+ ret = soc_init_dai_link(card, link);
if (ret) {
- dev_err(card->dev, "ASoC: failed to init multicodec\n");
- return ret;
- }
-
- for (j = 0; j < link->num_codecs; j++) {
- /*
- * Codec must be specified by 1 of name or OF node,
- * not both or neither.
- */
- if (!!link->codecs[j].name ==
- !!link->codecs[j].of_node) {
- dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n",
- link->name);
- return -EINVAL;
- }
- /* Codec DAI name must be specified */
- if (!link->codecs[j].dai_name) {
- dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n",
- link->name);
- return -EINVAL;
- }
- }
-
- /*
- * Platform may be specified by either name or OF node, but
- * can be left unspecified, and a dummy platform will be used.
- */
- if (link->platform_name && link->platform_of_node) {
- dev_err(card->dev,
- "ASoC: Both platform name/of_node are set for %s\n",
+ dev_err(card->dev, "ASoC: failed to init link %s\n",
link->name);
- return -EINVAL;
- }
-
- /*
- * CPU device may be specified by either name or OF node, but
- * can be left unspecified, and will be matched based on DAI
- * name alone..
- */
- if (link->cpu_name && link->cpu_of_node) {
- dev_err(card->dev,
- "ASoC: Neither/both cpu name/of_node are set for %s\n",
- link->name);
- return -EINVAL;
- }
- /*
- * At least one of CPU DAI name or CPU device name/node must be
- * specified
- */
- if (!link->cpu_dai_name &&
- !(link->cpu_name || link->cpu_of_node)) {
- dev_err(card->dev,
- "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
- link->name);
- return -EINVAL;
+ return ret;
}
}
@@ -2408,28 +2620,11 @@ int snd_soc_register_card(struct snd_soc_card *card)
snd_soc_initialize_card_lists(card);
- card->rtd = devm_kzalloc(card->dev,
- sizeof(struct snd_soc_pcm_runtime) *
- (card->num_links + card->num_aux_devs),
- GFP_KERNEL);
- if (card->rtd == NULL)
- return -ENOMEM;
- card->num_rtd = 0;
- card->rtd_aux = &card->rtd[card->num_links];
-
- for (i = 0; i < card->num_links; i++) {
- card->rtd[i].card = card;
- card->rtd[i].dai_link = &card->dai_link[i];
- card->rtd[i].codec_dais = devm_kzalloc(card->dev,
- sizeof(struct snd_soc_dai *) *
- (card->rtd[i].dai_link->num_codecs),
- GFP_KERNEL);
- if (card->rtd[i].codec_dais == NULL)
- return -ENOMEM;
- }
+ INIT_LIST_HEAD(&card->dai_link_list);
+ card->num_dai_links = 0;
- for (i = 0; i < card->num_aux_devs; i++)
- card->rtd_aux[i].card = card;
+ INIT_LIST_HEAD(&card->rtd_list);
+ card->num_rtd = 0;
INIT_LIST_HEAD(&card->dapm_dirty);
INIT_LIST_HEAD(&card->dobj_list);
@@ -2442,8 +2637,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
return ret;
/* deactivate pins to sleep state */
- for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+ list_for_each_entry(rtd, &card->rtd_list, list) {
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int j;
@@ -2558,6 +2752,56 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component)
}
}
+/* Create a DAI and add it to the component's DAI list */
+static struct snd_soc_dai *soc_add_dai(struct snd_soc_component *component,
+ struct snd_soc_dai_driver *dai_drv,
+ bool legacy_dai_naming)
+{
+ struct device *dev = component->dev;
+ struct snd_soc_dai *dai;
+
+ dev_dbg(dev, "ASoC: dynamically register DAI %s\n", dev_name(dev));
+
+ dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
+ if (dai == NULL)
+ return NULL;
+
+ /*
+ * Back in the old days when we still had component-less DAIs,
+ * instead of having a static name, component-less DAIs would
+ * inherit the name of the parent device so it is possible to
+ * register multiple instances of the DAI. We still need to keep
+ * the same naming style even though those DAIs are not
+ * component-less anymore.
+ */
+ if (legacy_dai_naming &&
+ (dai_drv->id == 0 || dai_drv->name == NULL)) {
+ dai->name = fmt_single_name(dev, &dai->id);
+ } else {
+ dai->name = fmt_multiple_name(dev, dai_drv);
+ if (dai_drv->id)
+ dai->id = dai_drv->id;
+ else
+ dai->id = component->num_dai;
+ }
+ if (dai->name == NULL) {
+ kfree(dai);
+ return NULL;
+ }
+
+ dai->component = component;
+ dai->dev = dev;
+ dai->driver = dai_drv;
+ if (!dai->driver->ops)
+ dai->driver->ops = &null_dai_ops;
+
+ list_add(&dai->list, &component->dai_list);
+ component->num_dai++;
+
+ dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
+ return dai;
+}
+
/**
* snd_soc_register_dais - Register a DAI with the ASoC core
*
@@ -2579,58 +2823,66 @@ static int snd_soc_register_dais(struct snd_soc_component *component,
dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);
component->dai_drv = dai_drv;
- component->num_dai = count;
for (i = 0; i < count; i++) {
- dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
+ dai = soc_add_dai(component, dai_drv + i,
+ count == 1 && legacy_dai_naming);
if (dai == NULL) {
ret = -ENOMEM;
goto err;
}
+ }
- /*
- * Back in the old days when we still had component-less DAIs,
- * instead of having a static name, component-less DAIs would
- * inherit the name of the parent device so it is possible to
- * register multiple instances of the DAI. We still need to keep
- * the same naming style even though those DAIs are not
- * component-less anymore.
- */
- if (count == 1 && legacy_dai_naming &&
- (dai_drv[i].id == 0 || dai_drv[i].name == NULL)) {
- dai->name = fmt_single_name(dev, &dai->id);
- } else {
- dai->name = fmt_multiple_name(dev, &dai_drv[i]);
- if (dai_drv[i].id)
- dai->id = dai_drv[i].id;
- else
- dai->id = i;
- }
- if (dai->name == NULL) {
- kfree(dai);
- ret = -ENOMEM;
- goto err;
- }
+ return 0;
- dai->component = component;
- dai->dev = dev;
- dai->driver = &dai_drv[i];
- if (!dai->driver->ops)
- dai->driver->ops = &null_dai_ops;
+err:
+ snd_soc_unregister_dais(component);
- list_add(&dai->list, &component->dai_list);
+ return ret;
+}
+
+/**
+ * snd_soc_register_dai - Register a DAI dynamically & create its widgets
+ *
+ * @component: The component the DAIs are registered for
+ * @dai_drv: DAI driver to use for the DAI
+ *
+ * Topology can use this API to register DAIs when probing a component.
+ * These DAIs's widgets will be freed in the card cleanup and the DAIs
+ * will be freed in the component cleanup.
+ */
+int snd_soc_register_dai(struct snd_soc_component *component,
+ struct snd_soc_dai_driver *dai_drv)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(component);
+ struct snd_soc_dai *dai;
+ int ret;
- dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
+ if (dai_drv->dobj.type != SND_SOC_DOBJ_PCM) {
+ dev_err(component->dev, "Invalid dai type %d\n",
+ dai_drv->dobj.type);
+ return -EINVAL;
}
- return 0;
+ lockdep_assert_held(&client_mutex);
+ dai = soc_add_dai(component, dai_drv, false);
+ if (!dai)
+ return -ENOMEM;
-err:
- snd_soc_unregister_dais(component);
+ /* Create the DAI widgets here. After adding DAIs, topology may
+ * also add routes that need these widgets as source or sink.
+ */
+ ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
+ if (ret != 0) {
+ dev_err(component->dev,
+ "Failed to create DAI widgets %d\n", ret);
+ }
return ret;
}
+EXPORT_SYMBOL_GPL(snd_soc_register_dai);
static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm,
enum snd_soc_dapm_type type, int subseq)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 7d009428934a..5a2812fa8946 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1300,7 +1300,7 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
static int dapm_always_on_check_power(struct snd_soc_dapm_widget *w)
{
- return 1;
+ return w->connected;
}
static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
@@ -3358,6 +3358,11 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
w->is_ep = SND_SOC_DAPM_EP_SOURCE;
w->power_check = dapm_always_on_check_power;
break;
+ case snd_soc_dapm_sink:
+ w->is_ep = SND_SOC_DAPM_EP_SINK;
+ w->power_check = dapm_always_on_check_power;
+ break;
+
case snd_soc_dapm_mux:
case snd_soc_dapm_demux:
case snd_soc_dapm_switch:
@@ -3900,13 +3905,10 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
{
- struct snd_soc_pcm_runtime *rtd = card->rtd;
- int i;
+ struct snd_soc_pcm_runtime *rtd;
/* for each BE DAI link... */
- for (i = 0; i < card->num_rtd; i++) {
- rtd = &card->rtd[i];
-
+ list_for_each_entry(rtd, &card->rtd_list, list) {
/*
* dynamic FE links have no fixed DAI mapping.
* CODEC<->CODEC links have no direct connection.
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 2f67ba6d7a8f..a513a34a51d2 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -779,11 +779,11 @@ int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
switch (op_flag) {
case SNDRV_CTL_TLV_OP_READ:
if (params->get)
- ret = params->get(tlv, count);
+ ret = params->get(kcontrol, tlv, count);
break;
case SNDRV_CTL_TLV_OP_WRITE:
if (params->put)
- ret = params->put(tlv, count);
+ ret = params->put(kcontrol, tlv, count);
break;
}
return ret;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index c86dc96e8986..e898b427be7e 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -599,10 +599,15 @@ platform_err:
out:
mutex_unlock(&rtd->pcm_mutex);
- pm_runtime_put(platform->dev);
- for (i = 0; i < rtd->num_codecs; i++)
- pm_runtime_put(rtd->codec_dais[i]->dev);
- pm_runtime_put(cpu_dai->dev);
+ pm_runtime_mark_last_busy(platform->dev);
+ pm_runtime_put_autosuspend(platform->dev);
+ for (i = 0; i < rtd->num_codecs; i++) {
+ pm_runtime_mark_last_busy(rtd->codec_dais[i]->dev);
+ pm_runtime_put_autosuspend(rtd->codec_dais[i]->dev);
+ }
+
+ pm_runtime_mark_last_busy(cpu_dai->dev);
+ pm_runtime_put_autosuspend(cpu_dai->dev);
for (i = 0; i < rtd->num_codecs; i++) {
if (!rtd->codec_dais[i]->active)
pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
@@ -706,10 +711,17 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
mutex_unlock(&rtd->pcm_mutex);
- pm_runtime_put(platform->dev);
- for (i = 0; i < rtd->num_codecs; i++)
- pm_runtime_put(rtd->codec_dais[i]->dev);
- pm_runtime_put(cpu_dai->dev);
+ pm_runtime_mark_last_busy(platform->dev);
+ pm_runtime_put_autosuspend(platform->dev);
+
+ for (i = 0; i < rtd->num_codecs; i++) {
+ pm_runtime_mark_last_busy(rtd->codec_dais[i]->dev);
+ pm_runtime_put_autosuspend(rtd->codec_dais[i]->dev);
+ }
+
+ pm_runtime_mark_last_busy(cpu_dai->dev);
+ pm_runtime_put_autosuspend(cpu_dai->dev);
+
for (i = 0; i < rtd->num_codecs; i++) {
if (!rtd->codec_dais[i]->active)
pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev);
@@ -1213,11 +1225,10 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
struct snd_soc_dapm_widget *widget, int stream)
{
struct snd_soc_pcm_runtime *be;
- int i, j;
+ int i;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- for (i = 0; i < card->num_links; i++) {
- be = &card->rtd[i];
+ list_for_each_entry(be, &card->rtd_list, list) {
if (!be->dai_link->no_pcm)
continue;
@@ -1225,16 +1236,15 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
if (be->cpu_dai->playback_widget == widget)
return be;
- for (j = 0; j < be->num_codecs; j++) {
- struct snd_soc_dai *dai = be->codec_dais[j];
+ for (i = 0; i < be->num_codecs; i++) {
+ struct snd_soc_dai *dai = be->codec_dais[i];
if (dai->playback_widget == widget)
return be;
}
}
} else {
- for (i = 0; i < card->num_links; i++) {
- be = &card->rtd[i];
+ list_for_each_entry(be, &card->rtd_list, list) {
if (!be->dai_link->no_pcm)
continue;
@@ -1242,8 +1252,8 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
if (be->cpu_dai->capture_widget == widget)
return be;
- for (j = 0; j < be->num_codecs; j++) {
- struct snd_soc_dai *dai = be->codec_dais[j];
+ for (i = 0; i < be->num_codecs; i++) {
+ struct snd_soc_dai *dai = be->codec_dais[i];
if (dai->capture_widget == widget)
return be;
}
@@ -1616,6 +1626,56 @@ static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
snd_pcm_stream_unlock_irq(substream);
}
+static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
+ int stream)
+{
+ struct snd_soc_dpcm *dpcm;
+ struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
+ struct snd_soc_dai *fe_cpu_dai = fe->cpu_dai;
+ int err;
+
+ /* apply symmetry for FE */
+ if (soc_pcm_has_symmetry(fe_substream))
+ fe_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
+
+ /* Symmetry only applies if we've got an active stream. */
+ if (fe_cpu_dai->active) {
+ err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai);
+ if (err < 0)
+ return err;
+ }
+
+ /* apply symmetry for BE */
+ list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+ struct snd_pcm_substream *be_substream =
+ snd_soc_dpcm_get_substream(be, stream);
+ struct snd_soc_pcm_runtime *rtd = be_substream->private_data;
+ int i;
+
+ if (soc_pcm_has_symmetry(be_substream))
+ be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
+
+ /* Symmetry only applies if we've got an active stream. */
+ if (rtd->cpu_dai->active) {
+ err = soc_pcm_apply_symmetry(be_substream, rtd->cpu_dai);
+ if (err < 0)
+ return err;
+ }
+
+ for (i = 0; i < rtd->num_codecs; i++) {
+ if (rtd->codec_dais[i]->active) {
+ err = soc_pcm_apply_symmetry(be_substream,
+ rtd->codec_dais[i]);
+ if (err < 0)
+ return err;
+ }
+ }
+ }
+
+ return 0;
+}
+
static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
{
struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
@@ -1644,6 +1704,13 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
dpcm_set_fe_runtime(fe_substream);
snd_pcm_limit_hw_rates(runtime);
+ ret = dpcm_apply_symmetry(fe_substream, stream);
+ if (ret < 0) {
+ dev_err(fe->dev, "ASoC: failed to apply dpcm symmetry %d\n",
+ ret);
+ goto unwind;
+ }
+
dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
return 0;
@@ -2115,7 +2182,8 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
continue;
if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
- (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
continue;
dev_dbg(be->dev, "ASoC: prepare BE %s\n",
@@ -2343,12 +2411,12 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
*/
int soc_dpcm_runtime_update(struct snd_soc_card *card)
{
- int i, old, new, paths;
+ struct snd_soc_pcm_runtime *fe;
+ int old, new, paths;
mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
- for (i = 0; i < card->num_rtd; i++) {
+ list_for_each_entry(fe, &card->rtd_list, list) {
struct snd_soc_dapm_widget_list *list;
- struct snd_soc_pcm_runtime *fe = &card->rtd[i];
/* make sure link is FE */
if (!fe->dai_link->dynamic)
diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c
index 5c2bc53f0a9b..7aca6b92f718 100644
--- a/sound/soc/sti/uniperif_player.c
+++ b/sound/soc/sti/uniperif_player.c
@@ -251,8 +251,7 @@ static void uni_player_set_channel_status(struct uniperif *player,
* set one.
*/
mutex_lock(&player->ctrl_lock);
- if (runtime && (player->stream_settings.iec958.status[3]
- == IEC958_AES3_CON_FS_NOTID)) {
+ if (runtime) {
switch (runtime->rate) {
case 22050:
player->stream_settings.iec958.status[3] =
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 1bb896d78d09..44f170c73b06 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -28,6 +28,7 @@
#include <linux/of_address.h>
#include <linux/clk.h>
#include <linux/regmap.h>
+#include <linux/gpio/consumer.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -70,6 +71,7 @@
/* Codec ADC register offsets and bit fields */
#define SUN4I_CODEC_ADC_FIFOC (0x1c)
+#define SUN4I_CODEC_ADC_FIFOC_ADC_FS (29)
#define SUN4I_CODEC_ADC_FIFOC_EN_AD (28)
#define SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE (24)
#define SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL (8)
@@ -102,17 +104,14 @@ struct sun4i_codec {
struct regmap *regmap;
struct clk *clk_apb;
struct clk *clk_module;
+ struct gpio_desc *gpio_pa;
+ struct snd_dmaengine_dai_dma_data capture_dma_data;
struct snd_dmaengine_dai_dma_data playback_dma_data;
};
static void sun4i_codec_start_playback(struct sun4i_codec *scodec)
{
- /*
- * FIXME: according to the BSP, we might need to drive a PA
- * GPIO high here on some boards
- */
-
/* Flush TX FIFO */
regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH),
@@ -126,37 +125,50 @@ static void sun4i_codec_start_playback(struct sun4i_codec *scodec)
static void sun4i_codec_stop_playback(struct sun4i_codec *scodec)
{
- /*
- * FIXME: according to the BSP, we might need to drive a PA
- * GPIO low here on some boards
- */
-
/* Disable DAC DRQ */
regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN),
0);
}
+static void sun4i_codec_start_capture(struct sun4i_codec *scodec)
+{
+ /* Enable ADC DRQ */
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
+ BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN),
+ BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN));
+}
+
+static void sun4i_codec_stop_capture(struct sun4i_codec *scodec)
+{
+ /* Disable ADC DRQ */
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
+ BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN), 0);
+}
+
static int sun4i_codec_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
- if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
- return -ENOTSUPP;
-
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- sun4i_codec_start_playback(scodec);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ sun4i_codec_start_playback(scodec);
+ else
+ sun4i_codec_start_capture(scodec);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- sun4i_codec_stop_playback(scodec);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ sun4i_codec_stop_playback(scodec);
+ else
+ sun4i_codec_stop_capture(scodec);
break;
default:
@@ -166,15 +178,54 @@ static int sun4i_codec_trigger(struct snd_pcm_substream *substream, int cmd,
return 0;
}
-static int sun4i_codec_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
- u32 val;
- if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
- return -ENOTSUPP;
+
+ /* Flush RX FIFO */
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
+ BIT(SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH),
+ BIT(SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH));
+
+
+ /* Set RX FIFO trigger level */
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
+ 0xf << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL,
+ 0x7 << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL);
+
+ /*
+ * FIXME: Undocumented in the datasheet, but
+ * Allwinner's code mentions that it is related
+ * related to microphone gain
+ */
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL,
+ 0x3 << 25,
+ 0x1 << 25);
+
+ if (of_device_is_compatible(scodec->dev->of_node,
+ "allwinner,sun7i-a20-codec"))
+ /* FIXME: Undocumented bits */
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_TUNE,
+ 0x3 << 8,
+ 0x1 << 8);
+
+ /* Fill most significant bits with valid data MSB */
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
+ BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE),
+ BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE));
+
+ return 0;
+}
+
+static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
+ u32 val;
/* Flush the TX FIFO */
regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
@@ -203,6 +254,15 @@ static int sun4i_codec_prepare(struct snd_pcm_substream *substream,
0);
return 0;
+};
+
+static int sun4i_codec_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return sun4i_codec_prepare_playback(substream, dai);
+
+ return sun4i_codec_prepare_capture(substream, dai);
}
static unsigned long sun4i_codec_get_mod_freq(struct snd_pcm_hw_params *params)
@@ -277,30 +337,32 @@ static int sun4i_codec_get_hw_rate(struct snd_pcm_hw_params *params)
}
}
-static int sun4i_codec_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+static int sun4i_codec_hw_params_capture(struct sun4i_codec *scodec,
+ struct snd_pcm_hw_params *params,
+ unsigned int hwrate)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
- unsigned long clk_freq;
- int ret, hwrate;
- u32 val;
-
- if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
- return -ENOTSUPP;
+ /* Set ADC sample rate */
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
+ 7 << SUN4I_CODEC_ADC_FIFOC_ADC_FS,
+ hwrate << SUN4I_CODEC_ADC_FIFOC_ADC_FS);
- clk_freq = sun4i_codec_get_mod_freq(params);
- if (!clk_freq)
- return -EINVAL;
+ /* Set the number of channels we want to use */
+ if (params_channels(params) == 1)
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
+ BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN),
+ BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN));
+ else
+ regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
+ BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN), 0);
- ret = clk_set_rate(scodec->clk_module, clk_freq);
- if (ret)
- return ret;
+ return 0;
+}
- hwrate = sun4i_codec_get_hw_rate(params);
- if (hwrate < 0)
- return hwrate;
+static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
+ struct snd_pcm_hw_params *params,
+ unsigned int hwrate)
+{
+ u32 val;
/* Set DAC sample rate */
regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
@@ -345,6 +407,35 @@ static int sun4i_codec_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static int sun4i_codec_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
+ unsigned long clk_freq;
+ int ret, hwrate;
+
+ clk_freq = sun4i_codec_get_mod_freq(params);
+ if (!clk_freq)
+ return -EINVAL;
+
+ ret = clk_set_rate(scodec->clk_module, clk_freq);
+ if (ret)
+ return ret;
+
+ hwrate = sun4i_codec_get_hw_rate(params);
+ if (hwrate < 0)
+ return hwrate;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return sun4i_codec_hw_params_playback(scodec, params,
+ hwrate);
+
+ return sun4i_codec_hw_params_capture(scodec, params,
+ hwrate);
+}
+
static int sun4i_codec_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -395,6 +486,20 @@ static struct snd_soc_dai_driver sun4i_codec_dai = {
SNDRV_PCM_FMTBIT_S32_LE,
.sig_bits = 24,
},
+ .capture = {
+ .stream_name = "Codec Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .rates = SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000 |
+ SNDRV_PCM_RATE_KNOT,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .sig_bits = 24,
+ },
};
/*** Codec ***/
@@ -429,12 +534,23 @@ static const struct snd_kcontrol_new sun4i_codec_pa_mixer_controls[] = {
SUN4I_CODEC_DAC_ACTL_MIXPAS, 1, 0),
};
-static const struct snd_soc_dapm_widget sun4i_codec_dapm_widgets[] = {
+static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = {
+ /* Digital parts of the ADCs */
+ SND_SOC_DAPM_SUPPLY("ADC", SUN4I_CODEC_ADC_FIFOC,
+ SUN4I_CODEC_ADC_FIFOC_EN_AD, 0,
+ NULL, 0),
+
/* Digital parts of the DACs */
SND_SOC_DAPM_SUPPLY("DAC", SUN4I_CODEC_DAC_DPC,
SUN4I_CODEC_DAC_DPC_EN_DA, 0,
NULL, 0),
+ /* Analog parts of the ADCs */
+ SND_SOC_DAPM_ADC("Left ADC", "Codec Capture", SUN4I_CODEC_ADC_ACTL,
+ SUN4I_CODEC_ADC_ACTL_ADC_L_EN, 0),
+ SND_SOC_DAPM_ADC("Right ADC", "Codec Capture", SUN4I_CODEC_ADC_ACTL,
+ SUN4I_CODEC_ADC_ACTL_ADC_R_EN, 0),
+
/* Analog parts of the DACs */
SND_SOC_DAPM_DAC("Left DAC", "Codec Playback", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_DACAENL, 0),
@@ -453,6 +569,14 @@ static const struct snd_soc_dapm_widget sun4i_codec_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("Mixer Enable", SUN4I_CODEC_DAC_ACTL,
SUN4I_CODEC_DAC_ACTL_MIXEN, 0, NULL, 0),
+ /* VMIC */
+ SND_SOC_DAPM_SUPPLY("VMIC", SUN4I_CODEC_ADC_ACTL,
+ SUN4I_CODEC_ADC_ACTL_VMICEN, 0, NULL, 0),
+
+ /* Mic Pre-Amplifiers */
+ SND_SOC_DAPM_PGA("MIC1 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL,
+ SUN4I_CODEC_ADC_ACTL_PREG1EN, 0, NULL, 0),
+
/* Power Amplifier */
SND_SOC_DAPM_MIXER("Power Amplifier", SUN4I_CODEC_ADC_ACTL,
SUN4I_CODEC_ADC_ACTL_PA_EN, 0,
@@ -461,15 +585,19 @@ static const struct snd_soc_dapm_widget sun4i_codec_dapm_widgets[] = {
SND_SOC_DAPM_SWITCH("Power Amplifier Mute", SND_SOC_NOPM, 0, 0,
&sun4i_codec_pa_mute),
+ SND_SOC_DAPM_INPUT("Mic1"),
+
SND_SOC_DAPM_OUTPUT("HP Right"),
SND_SOC_DAPM_OUTPUT("HP Left"),
};
-static const struct snd_soc_dapm_route sun4i_codec_dapm_routes[] = {
- /* Left DAC Routes */
+static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = {
+ /* Left ADC / DAC Routes */
+ { "Left ADC", NULL, "ADC" },
{ "Left DAC", NULL, "DAC" },
- /* Right DAC Routes */
+ /* Right ADC / DAC Routes */
+ { "Right ADC", NULL, "ADC" },
{ "Right DAC", NULL, "DAC" },
/* Right Mixer Routes */
@@ -491,15 +619,21 @@ static const struct snd_soc_dapm_route sun4i_codec_dapm_routes[] = {
{ "Power Amplifier Mute", "Switch", "Power Amplifier" },
{ "HP Right", NULL, "Power Amplifier Mute" },
{ "HP Left", NULL, "Power Amplifier Mute" },
+
+ /* Mic1 Routes */
+ { "Left ADC", NULL, "MIC1 Pre-Amplifier" },
+ { "Right ADC", NULL, "MIC1 Pre-Amplifier" },
+ { "MIC1 Pre-Amplifier", NULL, "Mic1"},
+ { "Mic1", NULL, "VMIC" },
};
static struct snd_soc_codec_driver sun4i_codec_codec = {
.controls = sun4i_codec_widgets,
.num_controls = ARRAY_SIZE(sun4i_codec_widgets),
- .dapm_widgets = sun4i_codec_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_dapm_widgets),
- .dapm_routes = sun4i_codec_dapm_routes,
- .num_dapm_routes = ARRAY_SIZE(sun4i_codec_dapm_routes),
+ .dapm_widgets = sun4i_codec_codec_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
+ .dapm_routes = sun4i_codec_codec_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
};
static const struct snd_soc_component_driver sun4i_codec_component = {
@@ -516,7 +650,7 @@ static int sun4i_codec_dai_probe(struct snd_soc_dai *dai)
struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
snd_soc_dai_init_dma_data(dai, &scodec->playback_dma_data,
- NULL);
+ &scodec->capture_dma_data);
return 0;
}
@@ -532,6 +666,14 @@ static struct snd_soc_dai_driver dummy_cpu_dai = {
.formats = SUN4I_CODEC_FORMATS,
.sig_bits = 24,
},
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SUN4I_CODEC_RATES,
+ .formats = SUN4I_CODEC_FORMATS,
+ .sig_bits = 24,
+ },
};
static const struct regmap_config sun4i_codec_regmap_config = {
@@ -569,6 +711,27 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
return link;
};
+static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card);
+
+ if (scodec->gpio_pa)
+ gpiod_set_value_cansleep(scodec->gpio_pa,
+ !!SND_SOC_DAPM_EVENT_ON(event));
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget sun4i_codec_card_dapm_widgets[] = {
+ SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
+};
+
+static const struct snd_soc_dapm_route sun4i_codec_card_dapm_routes[] = {
+ { "Speaker", NULL, "HP Right" },
+ { "Speaker", NULL, "HP Left" },
+};
+
static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
{
struct snd_soc_card *card;
@@ -583,6 +746,10 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
card->dev = dev;
card->name = "sun4i-codec";
+ card->dapm_widgets = sun4i_codec_card_dapm_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(sun4i_codec_card_dapm_widgets);
+ card->dapm_routes = sun4i_codec_card_dapm_routes;
+ card->num_dapm_routes = ARRAY_SIZE(sun4i_codec_card_dapm_routes);
return card;
};
@@ -634,11 +801,25 @@ static int sun4i_codec_probe(struct platform_device *pdev)
return -EINVAL;
}
+ scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(scodec->gpio_pa)) {
+ ret = PTR_ERR(scodec->gpio_pa);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get pa gpio: %d\n", ret);
+ return ret;
+ }
+
/* DMA configuration for TX FIFO */
scodec->playback_dma_data.addr = res->start + SUN4I_CODEC_DAC_TXDATA;
scodec->playback_dma_data.maxburst = 4;
scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ /* DMA configuration for RX FIFO */
+ scodec->capture_dma_data.addr = res->start + SUN4I_CODEC_ADC_RXDATA;
+ scodec->capture_dma_data.maxburst = 4;
+ scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
ret = snd_soc_register_codec(&pdev->dev, &sun4i_codec_codec,
&sun4i_codec_dai, 1);
if (ret) {
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index ba272e21a6fa..deb597f7c302 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -101,12 +101,16 @@ static const struct snd_kcontrol_new tegra_alc5632_controls[] = {
static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
+ int ret;
struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(rtd->card);
- snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET,
- &tegra_alc5632_hs_jack,
- tegra_alc5632_hs_jack_pins,
- ARRAY_SIZE(tegra_alc5632_hs_jack_pins));
+ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET,
+ &tegra_alc5632_hs_jack,
+ tegra_alc5632_hs_jack_pins,
+ ARRAY_SIZE(tegra_alc5632_hs_jack_pins));
+ if (ret)
+ return ret;
if (gpio_is_valid(machine->gpio_hp_det)) {
tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 21604009bc1a..e485278e027a 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -199,7 +199,8 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
static int tegra_wm8903_remove(struct snd_soc_card *card)
{
- struct snd_soc_pcm_runtime *rtd = &(card->rtd[0]);
+ struct snd_soc_pcm_runtime *rtd =
+ snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = codec_dai->codec;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
diff --git a/sound/synth/emux/emux_nrpn.c b/sound/synth/emux/emux_nrpn.c
index 00fc005ecf6e..9729a15b6ae6 100644
--- a/sound/synth/emux/emux_nrpn.c
+++ b/sound/synth/emux/emux_nrpn.c
@@ -48,7 +48,8 @@ struct nrpn_conv_table {
* convert NRPN/control values
*/
-static int send_converted_effect(struct nrpn_conv_table *table, int num_tables,
+static int send_converted_effect(const struct nrpn_conv_table *table,
+ int num_tables,
struct snd_emux_port *port,
struct snd_midi_channel *chan,
int type, int val, int mode)
@@ -179,7 +180,7 @@ static int fx_conv_Q(int val)
}
-static struct nrpn_conv_table awe_effects[] =
+static const struct nrpn_conv_table awe_effects[] =
{
{ 0, EMUX_FX_LFO1_DELAY, fx_lfo1_delay},
{ 1, EMUX_FX_LFO1_FREQ, fx_lfo1_freq},
@@ -266,7 +267,7 @@ static int gs_vib_delay(int val)
return -(val - 64) * gs_sense[FX_VIBDELAY] / 50;
}
-static struct nrpn_conv_table gs_effects[] =
+static const struct nrpn_conv_table gs_effects[] =
{
{32, EMUX_FX_CUTOFF, gs_cutoff},
{33, EMUX_FX_FILTERQ, gs_filterQ},
@@ -350,7 +351,7 @@ static int xg_release(int val)
return -(val - 64) * xg_sense[FX_RELEASE] / 64;
}
-static struct nrpn_conv_table xg_effects[] =
+static const struct nrpn_conv_table xg_effects[] =
{
{71, EMUX_FX_CUTOFF, xg_cutoff},
{74, EMUX_FX_FILTERQ, xg_filterQ},
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 18f56646ce86..1f09d9591276 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -675,6 +675,8 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
void snd_usb_autosuspend(struct snd_usb_audio *chip)
{
+ if (atomic_read(&chip->shutdown))
+ return;
if (atomic_dec_and_test(&chip->active))
usb_autopm_put_interface(chip->pm_intf);
}
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 5b4c58c3e2c5..cc39f63299ef 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -112,7 +112,7 @@ struct snd_usb_midi {
struct usb_interface *iface;
const struct snd_usb_audio_quirk *quirk;
struct snd_rawmidi *rmidi;
- struct usb_protocol_ops *usb_protocol_ops;
+ const struct usb_protocol_ops *usb_protocol_ops;
struct list_head list;
struct timer_list error_timer;
spinlock_t disc_lock;
@@ -671,31 +671,32 @@ static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint *ep,
}
}
-static struct usb_protocol_ops snd_usbmidi_standard_ops = {
+static const struct usb_protocol_ops snd_usbmidi_standard_ops = {
.input = snd_usbmidi_standard_input,
.output = snd_usbmidi_standard_output,
.output_packet = snd_usbmidi_output_standard_packet,
};
-static struct usb_protocol_ops snd_usbmidi_midiman_ops = {
+static const struct usb_protocol_ops snd_usbmidi_midiman_ops = {
.input = snd_usbmidi_midiman_input,
.output = snd_usbmidi_standard_output,
.output_packet = snd_usbmidi_output_midiman_packet,
};
-static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = {
+static const
+struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = {
.input = snd_usbmidi_maudio_broken_running_status_input,
.output = snd_usbmidi_standard_output,
.output_packet = snd_usbmidi_output_standard_packet,
};
-static struct usb_protocol_ops snd_usbmidi_cme_ops = {
+static const struct usb_protocol_ops snd_usbmidi_cme_ops = {
.input = snd_usbmidi_cme_input,
.output = snd_usbmidi_standard_output,
.output_packet = snd_usbmidi_output_standard_packet,
};
-static struct usb_protocol_ops snd_usbmidi_ch345_broken_sysex_ops = {
+static const struct usb_protocol_ops snd_usbmidi_ch345_broken_sysex_ops = {
.input = ch345_broken_sysex_input,
.output = snd_usbmidi_standard_output,
.output_packet = snd_usbmidi_output_standard_packet,
@@ -795,7 +796,7 @@ static void snd_usbmidi_akai_output(struct snd_usb_midi_out_endpoint *ep,
}
}
-static struct usb_protocol_ops snd_usbmidi_akai_ops = {
+static const struct usb_protocol_ops snd_usbmidi_akai_ops = {
.input = snd_usbmidi_akai_input,
.output = snd_usbmidi_akai_output,
};
@@ -835,7 +836,7 @@ static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint *ep,
urb->transfer_buffer_length = 2 + count;
}
-static struct usb_protocol_ops snd_usbmidi_novation_ops = {
+static const struct usb_protocol_ops snd_usbmidi_novation_ops = {
.input = snd_usbmidi_novation_input,
.output = snd_usbmidi_novation_output,
};
@@ -867,7 +868,7 @@ static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint *ep,
urb->transfer_buffer_length = count;
}
-static struct usb_protocol_ops snd_usbmidi_raw_ops = {
+static const struct usb_protocol_ops snd_usbmidi_raw_ops = {
.input = snd_usbmidi_raw_input,
.output = snd_usbmidi_raw_output,
};
@@ -883,7 +884,7 @@ static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint *ep,
snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2);
}
-static struct usb_protocol_ops snd_usbmidi_ftdi_ops = {
+static const struct usb_protocol_ops snd_usbmidi_ftdi_ops = {
.input = snd_usbmidi_ftdi_input,
.output = snd_usbmidi_raw_output,
};
@@ -927,7 +928,7 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
urb->transfer_buffer_length = ep->max_transfer;
}
-static struct usb_protocol_ops snd_usbmidi_122l_ops = {
+static const struct usb_protocol_ops snd_usbmidi_122l_ops = {
.input = snd_usbmidi_us122l_input,
.output = snd_usbmidi_us122l_output,
};
@@ -1060,7 +1061,7 @@ static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint *ep,
urb->transfer_buffer_length = ep->max_transfer - buf_free;
}
-static struct usb_protocol_ops snd_usbmidi_emagic_ops = {
+static const struct usb_protocol_ops snd_usbmidi_emagic_ops = {
.input = snd_usbmidi_emagic_input,
.output = snd_usbmidi_emagic_output,
.init_out_endpoint = snd_usbmidi_emagic_init_out,
@@ -2206,7 +2207,7 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi *umidi,
return 0;
}
-static struct snd_rawmidi_global_ops snd_usbmidi_ops = {
+static const struct snd_rawmidi_global_ops snd_usbmidi_ops = {
.get_port_info = snd_usbmidi_get_port_info,
};
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index 9581089c28c5..c19a5dd05631 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -1037,7 +1037,7 @@ static int detect_usb_format(struct ua101 *ua)
return -ENXIO;
}
ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, usb_endpoint_num(epd));
- ua->capture.max_packet_bytes = le16_to_cpu(epd->wMaxPacketSize);
+ ua->capture.max_packet_bytes = usb_endpoint_maxp(epd);
epd = &ua->intf[INTF_PLAYBACK]->altsetting[1].endpoint[0].desc;
if (!usb_endpoint_is_isoc_out(epd)) {
@@ -1045,7 +1045,7 @@ static int detect_usb_format(struct ua101 *ua)
return -ENXIO;
}
ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, usb_endpoint_num(epd));
- ua->playback.max_packet_bytes = le16_to_cpu(epd->wMaxPacketSize);
+ ua->playback.max_packet_bytes = usb_endpoint_maxp(epd);
return 0;
}
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 0ce888dceed0..279025650568 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -793,7 +793,7 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
return 0;
kcontrol->private_value &= ~(0xff << 24);
- kcontrol->private_value |= newval;
+ kcontrol->private_value |= (unsigned int)newval << 24;
err = snd_ni_update_cur_val(list);
return err < 0 ? err : 1;
}
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index b6c0c8e3b450..23ea6d800c4c 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1269,6 +1269,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
case USB_ID(0x20b1, 0x3008): /* iFi Audio micro/nano iDSD */
case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */
case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */
+ case USB_ID(0x22d8, 0x0416): /* OPPO HA-1*/
if (fp->altsetting == 2)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 8ee14f2365e7..c4dc577ab1bd 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -125,11 +125,9 @@ static int usb_chmap_ctl_info(struct snd_kcontrol *kcontrol,
static bool have_dup_chmap(struct snd_usb_substream *subs,
struct audioformat *fp)
{
- struct list_head *p;
+ struct audioformat *prev = fp;
- for (p = fp->list.prev; p != &subs->fmt_list; p = p->prev) {
- struct audioformat *prev;
- prev = list_entry(p, struct audioformat, list);
+ list_for_each_entry_continue_reverse(prev, &subs->fmt_list, list) {
if (prev->chmap &&
!memcmp(prev->chmap, fp->chmap, sizeof(*fp->chmap)))
return true;
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 61d5dc2a3421..dd40ca9d858a 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -166,7 +166,7 @@ static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs,
/* set the buffer pointer */
urb->transfer_buffer = runtime->dma_area + subs->hwptr * usX2Y->stride;
if ((subs->hwptr += count) >= runtime->buffer_size)
- subs->hwptr -= runtime->buffer_size;
+ subs->hwptr -= runtime->buffer_size;
}
else
urb->transfer_buffer = subs->tmpbuf;