^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * intel_hdmi_audio.c - Intel HDMI audio driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2016 Intel Corp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Authors: Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Ramesh Babu K V <ramesh.babu@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Vaibhav Agarwal <vaibhav.agarwal@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Jerome Anand <jerome.anand@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * ALSA driver for Intel HDMI audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <sound/jack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <drm/drm_edid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <drm/intel_lpe_audio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "intel_hdmi_audio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define for_each_pipe(card_ctx, pipe) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) for ((pipe) = 0; (pipe) < (card_ctx)->num_pipes; (pipe)++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define for_each_port(card_ctx, port) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) for ((port) = 0; (port) < (card_ctx)->num_ports; (port)++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*standard module options for ALSA. This module supports only one card*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int hdmi_card_index = SNDRV_DEFAULT_IDX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static char *hdmi_card_id = SNDRV_DEFAULT_STR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static bool single_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) module_param_named(index, hdmi_card_index, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) MODULE_PARM_DESC(index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) "Index value for INTEL Intel HDMI Audio controller.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) module_param_named(id, hdmi_card_id, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MODULE_PARM_DESC(id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) "ID string for INTEL Intel HDMI Audio controller.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) module_param(single_port, bool, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) MODULE_PARM_DESC(single_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) "Single-port mode (for compatibility)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * ELD SA bits in the CEA Speaker Allocation data block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static const int eld_speaker_allocation_bits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) [0] = FL | FR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) [1] = LFE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) [2] = FC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) [3] = RL | RR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) [4] = RC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) [5] = FLC | FRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) [6] = RLC | RRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* the following are not defined in ELD yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) [7] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * This is an ordered list!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * The preceding ones have better chances to be selected by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * hdmi_channel_allocation().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static struct cea_channel_speaker_allocation channel_allocations[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* channel: 7 6 5 4 3 2 1 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* 2.1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Dolby Surround */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* surround40 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* surround41 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* surround50 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* surround51 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* 6.1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* surround71 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static const struct channel_map_table map_tables[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { SNDRV_CHMAP_FL, 0x00, FL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) { SNDRV_CHMAP_FR, 0x01, FR },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { SNDRV_CHMAP_RL, 0x04, RL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { SNDRV_CHMAP_RR, 0x05, RR },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { SNDRV_CHMAP_LFE, 0x02, LFE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { SNDRV_CHMAP_FC, 0x03, FC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { SNDRV_CHMAP_RLC, 0x06, RLC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { SNDRV_CHMAP_RRC, 0x07, RRC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {} /* terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* hardware capability structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static const struct snd_pcm_hardware had_pcm_hardware = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .info = (SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .formats = (SNDRV_PCM_FMTBIT_S16_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) SNDRV_PCM_FMTBIT_S24_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) SNDRV_PCM_FMTBIT_S32_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .rates = SNDRV_PCM_RATE_32000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) SNDRV_PCM_RATE_44100 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) SNDRV_PCM_RATE_48000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) SNDRV_PCM_RATE_88200 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) SNDRV_PCM_RATE_96000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) SNDRV_PCM_RATE_176400 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) SNDRV_PCM_RATE_192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .rate_min = HAD_MIN_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .rate_max = HAD_MAX_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .channels_min = HAD_MIN_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .channels_max = HAD_MAX_CHANNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .buffer_bytes_max = HAD_MAX_BUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .period_bytes_min = HAD_MIN_PERIOD_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .period_bytes_max = HAD_MAX_PERIOD_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .periods_min = HAD_MIN_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .periods_max = HAD_MAX_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .fifo_size = HAD_FIFO_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Get the active PCM substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * Call had_substream_put() for unreferecing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * Don't call this inside had_spinlock, as it takes by itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static struct snd_pcm_substream *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) had_substream_get(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) substream = intelhaddata->stream_info.substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) intelhaddata->stream_info.substream_refcount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* Unref the active PCM substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * Don't call this inside had_spinlock, as it takes by itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void had_substream_put(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) intelhaddata->stream_info.substream_refcount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static u32 had_config_offset(int pipe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) switch (pipe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return AUDIO_HDMI_CONFIG_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return AUDIO_HDMI_CONFIG_B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return AUDIO_HDMI_CONFIG_C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* Register access functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static u32 had_read_register_raw(struct snd_intelhad_card *card_ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int pipe, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return ioread32(card_ctx->mmio_start + had_config_offset(pipe) + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static void had_write_register_raw(struct snd_intelhad_card *card_ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int pipe, u32 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) iowrite32(val, card_ctx->mmio_start + had_config_offset(pipe) + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static void had_read_register(struct snd_intelhad *ctx, u32 reg, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!ctx->connected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) *val = had_read_register_raw(ctx->card_ctx, ctx->pipe, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static void had_write_register(struct snd_intelhad *ctx, u32 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (ctx->connected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) had_write_register_raw(ctx->card_ctx, ctx->pipe, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * enable / disable audio configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * The normal read/modify should not directly be used on VLV2 for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * updating AUD_CONFIG register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * This is because:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * Bit6 of AUD_CONFIG register is writeonly due to a silicon bug on VLV2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * HDMI IP. As a result a read-modify of AUD_CONFIG regiter will always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * clear bit6. AUD_CONFIG[6:4] represents the "channels" field of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * register. This field should be 1xy binary for configuration with 6 or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * more channels. Read-modify of AUD_CONFIG (Eg. for enabling audio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * causes the "channels" field to be updated as 0xy binary resulting in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * bad audio. The fix is to always write the AUD_CONFIG[6:4] with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * appropriate value when doing read-modify of AUD_CONFIG register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static void had_enable_audio(struct snd_intelhad *intelhaddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* update the cached value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) intelhaddata->aud_config.regx.aud_en = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) had_write_register(intelhaddata, AUD_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) intelhaddata->aud_config.regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* forcibly ACKs to both BUFFER_DONE and BUFFER_UNDERRUN interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static void had_ack_irqs(struct snd_intelhad *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) u32 status_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (!ctx->connected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) had_read_register(ctx, AUD_HDMI_STATUS, &status_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) status_reg |= HDMI_AUDIO_BUFFER_DONE | HDMI_AUDIO_UNDERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) had_write_register(ctx, AUD_HDMI_STATUS, status_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) had_read_register(ctx, AUD_HDMI_STATUS, &status_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Reset buffer pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static void had_reset_audio(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) had_write_register(intelhaddata, AUD_HDMI_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) AUD_HDMI_STATUSG_MASK_FUNCRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) had_write_register(intelhaddata, AUD_HDMI_STATUS, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * initialize audio channel status registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * This function is called in the prepare callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int had_prog_status_reg(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) union aud_ch_status_0 ch_stat0 = {.regval = 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) union aud_ch_status_1 ch_stat1 = {.regval = 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ch_stat0.regx.lpcm_id = (intelhaddata->aes_bits &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) IEC958_AES0_NONAUDIO) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ch_stat0.regx.clk_acc = (intelhaddata->aes_bits &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) IEC958_AES3_CON_CLOCK) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) switch (substream->runtime->rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) case AUD_SAMPLE_RATE_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ch_stat0.regx.samp_freq = CH_STATUS_MAP_32KHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) case AUD_SAMPLE_RATE_44_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ch_stat0.regx.samp_freq = CH_STATUS_MAP_44KHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case AUD_SAMPLE_RATE_48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ch_stat0.regx.samp_freq = CH_STATUS_MAP_48KHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case AUD_SAMPLE_RATE_88_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ch_stat0.regx.samp_freq = CH_STATUS_MAP_88KHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) case AUD_SAMPLE_RATE_96:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ch_stat0.regx.samp_freq = CH_STATUS_MAP_96KHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case AUD_SAMPLE_RATE_176_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ch_stat0.regx.samp_freq = CH_STATUS_MAP_176KHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case AUD_SAMPLE_RATE_192:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ch_stat0.regx.samp_freq = CH_STATUS_MAP_192KHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* control should never come here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) had_write_register(intelhaddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) AUD_CH_STATUS_0, ch_stat0.regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) switch (substream->runtime->format) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case SNDRV_PCM_FORMAT_S16_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) ch_stat1.regx.max_wrd_len = MAX_SMPL_WIDTH_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ch_stat1.regx.wrd_len = SMPL_WIDTH_16BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) case SNDRV_PCM_FORMAT_S24_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) case SNDRV_PCM_FORMAT_S32_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ch_stat1.regx.max_wrd_len = MAX_SMPL_WIDTH_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ch_stat1.regx.wrd_len = SMPL_WIDTH_24BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) had_write_register(intelhaddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) AUD_CH_STATUS_1, ch_stat1.regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * function to initialize audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * registers and buffer confgiuration registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * This function is called in the prepare callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static int had_init_audio_ctrl(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) union aud_cfg cfg_val = {.regval = 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) union aud_buf_config buf_cfg = {.regval = 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) u8 channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) had_prog_status_reg(substream, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) buf_cfg.regx.audio_fifo_watermark = FIFO_THRESHOLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) buf_cfg.regx.dma_fifo_watermark = DMA_FIFO_THRESHOLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) buf_cfg.regx.aud_delay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) had_write_register(intelhaddata, AUD_BUF_CONFIG, buf_cfg.regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) channels = substream->runtime->channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) cfg_val.regx.num_ch = channels - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (channels <= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) cfg_val.regx.layout = LAYOUT0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) cfg_val.regx.layout = LAYOUT1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) cfg_val.regx.packet_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (substream->runtime->format == SNDRV_PCM_FORMAT_S32_LE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) cfg_val.regx.left_align = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) cfg_val.regx.val_bit = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* fix up the DP bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (intelhaddata->dp_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) cfg_val.regx.dp_modei = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) cfg_val.regx.set = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) had_write_register(intelhaddata, AUD_CONFIG, cfg_val.regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) intelhaddata->aud_config = cfg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * Compute derived values in channel_allocations[].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static void init_channel_allocations(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct cea_channel_speaker_allocation *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) p = channel_allocations + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) p->channels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) p->spk_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (p->speakers[j]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) p->channels++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) p->spk_mask |= p->speakers[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * The transformation takes two steps:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * spk_mask => (channel_allocations[]) => ai->CA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * TODO: it could select the wrong CA from multiple candidates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static int had_channel_allocation(struct snd_intelhad *intelhaddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int ca = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int spk_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * CA defaults to 0 for basic stereo audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (channels <= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * expand ELD's speaker allocation mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * ELD tells the speaker mask in a compact(paired) form,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * expand ELD's notions to match the ones used by Audio InfoFrame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (intelhaddata->eld[DRM_ELD_SPEAKER] & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) spk_mask |= eld_speaker_allocation_bits[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* search for the first working match in the CA table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (channels == channel_allocations[i].channels &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) (spk_mask & channel_allocations[i].spk_mask) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) channel_allocations[i].spk_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ca = channel_allocations[i].ca_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) dev_dbg(intelhaddata->dev, "select CA 0x%x for %d\n", ca, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return ca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* from speaker bit mask to ALSA API channel position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static int spk_to_chmap(int spk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) const struct channel_map_table *t = map_tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) for (; t->map; t++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (t->spk_mask == spk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return t->map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static void had_build_channel_allocation_map(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int i, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int spk_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct snd_pcm_chmap_elem *chmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) u8 eld_high, eld_high_mask = 0xF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) u8 high_msb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) kfree(intelhaddata->chmap->chmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) intelhaddata->chmap->chmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (!chmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) dev_dbg(intelhaddata->dev, "eld speaker = %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) intelhaddata->eld[DRM_ELD_SPEAKER]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* WA: Fix the max channel supported to 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * Sink may support more than 8 channels, if eld_high has more than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * one bit set. SOC supports max 8 channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * Refer eld_speaker_allocation_bits, for sink speaker allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* if 0x2F < eld < 0x4F fall back to 0x2f, else fall back to 0x4F */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) eld_high = intelhaddata->eld[DRM_ELD_SPEAKER] & eld_high_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if ((eld_high & (eld_high-1)) && (eld_high > 0x1F)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* eld_high & (eld_high-1): if more than 1 bit set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* 0x1F: 7 channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) for (i = 1; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) high_msb = eld_high & (0x80 >> i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (high_msb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) intelhaddata->eld[DRM_ELD_SPEAKER] &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) high_msb | 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (intelhaddata->eld[DRM_ELD_SPEAKER] & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) spk_mask |= eld_speaker_allocation_bits[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (spk_mask == channel_allocations[i].spk_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) for (c = 0; c < channel_allocations[i].channels; c++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) chmap->map[c] = spk_to_chmap(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) channel_allocations[i].speakers[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) (MAX_SPEAKERS - 1) - c]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) chmap->channels = channel_allocations[i].channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) intelhaddata->chmap->chmap = chmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (i >= ARRAY_SIZE(channel_allocations))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) kfree(chmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * ALSA API channel-map control callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static int had_chmap_ctl_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) uinfo->count = HAD_MAX_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) uinfo->value.integer.max = SNDRV_CHMAP_LAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static int had_chmap_ctl_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct snd_intelhad *intelhaddata = info->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) const struct snd_pcm_chmap_elem *chmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) memset(ucontrol->value.integer.value, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) sizeof(long) * HAD_MAX_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) mutex_lock(&intelhaddata->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (!intelhaddata->chmap->chmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) mutex_unlock(&intelhaddata->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) chmap = intelhaddata->chmap->chmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) for (i = 0; i < chmap->channels; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ucontrol->value.integer.value[i] = chmap->map[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) mutex_unlock(&intelhaddata->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static int had_register_chmap_ctls(struct snd_intelhad *intelhaddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct snd_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) NULL, 0, (unsigned long)intelhaddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) &intelhaddata->chmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) intelhaddata->chmap->private_data = intelhaddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) intelhaddata->chmap->kctl->info = had_chmap_ctl_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) intelhaddata->chmap->kctl->get = had_chmap_ctl_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) intelhaddata->chmap->chmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * Initialize Data Island Packets registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * This function is called in the prepare callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static void had_prog_dip(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) union aud_ctrl_st ctrl_state = {.regval = 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) union aud_info_frame2 frame2 = {.regval = 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) union aud_info_frame3 frame3 = {.regval = 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) u8 checksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) u32 info_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) int channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) int ca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) channels = substream->runtime->channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) had_write_register(intelhaddata, AUD_CNTL_ST, ctrl_state.regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) ca = had_channel_allocation(intelhaddata, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (intelhaddata->dp_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) info_frame = DP_INFO_FRAME_WORD1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) frame2.regval = (substream->runtime->channels - 1) | (ca << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) info_frame = HDMI_INFO_FRAME_WORD1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) frame2.regx.chnl_cnt = substream->runtime->channels - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) frame3.regx.chnl_alloc = ca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* Calculte the byte wide checksum for all valid DIP words */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) for (i = 0; i < BYTES_PER_WORD; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) checksum += (info_frame >> (i * 8)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) for (i = 0; i < BYTES_PER_WORD; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) checksum += (frame2.regval >> (i * 8)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) for (i = 0; i < BYTES_PER_WORD; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) checksum += (frame3.regval >> (i * 8)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) frame2.regx.chksum = -(checksum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) had_write_register(intelhaddata, AUD_HDMIW_INFOFR, info_frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) had_write_register(intelhaddata, AUD_HDMIW_INFOFR, frame2.regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) had_write_register(intelhaddata, AUD_HDMIW_INFOFR, frame3.regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* program remaining DIP words with zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) for (i = 0; i < HAD_MAX_DIP_WORDS-VALID_DIP_WORDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) had_write_register(intelhaddata, AUD_HDMIW_INFOFR, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ctrl_state.regx.dip_freq = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) ctrl_state.regx.dip_en_sta = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) had_write_register(intelhaddata, AUD_CNTL_ST, ctrl_state.regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static int had_calculate_maud_value(u32 aud_samp_freq, u32 link_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) u32 maud_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* Select maud according to DP 1.2 spec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (link_rate == DP_2_7_GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) switch (aud_samp_freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) case AUD_SAMPLE_RATE_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) maud_val = AUD_SAMPLE_RATE_32_DP_2_7_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) case AUD_SAMPLE_RATE_44_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) maud_val = AUD_SAMPLE_RATE_44_1_DP_2_7_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) case AUD_SAMPLE_RATE_48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) maud_val = AUD_SAMPLE_RATE_48_DP_2_7_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) case AUD_SAMPLE_RATE_88_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) maud_val = AUD_SAMPLE_RATE_88_2_DP_2_7_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) case AUD_SAMPLE_RATE_96:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) maud_val = AUD_SAMPLE_RATE_96_DP_2_7_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) case AUD_SAMPLE_RATE_176_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) maud_val = AUD_SAMPLE_RATE_176_4_DP_2_7_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) case HAD_MAX_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) maud_val = HAD_MAX_RATE_DP_2_7_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) maud_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) } else if (link_rate == DP_1_62_GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) switch (aud_samp_freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) case AUD_SAMPLE_RATE_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) maud_val = AUD_SAMPLE_RATE_32_DP_1_62_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) case AUD_SAMPLE_RATE_44_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) maud_val = AUD_SAMPLE_RATE_44_1_DP_1_62_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) case AUD_SAMPLE_RATE_48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) maud_val = AUD_SAMPLE_RATE_48_DP_1_62_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) case AUD_SAMPLE_RATE_88_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) maud_val = AUD_SAMPLE_RATE_88_2_DP_1_62_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) case AUD_SAMPLE_RATE_96:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) maud_val = AUD_SAMPLE_RATE_96_DP_1_62_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) case AUD_SAMPLE_RATE_176_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) maud_val = AUD_SAMPLE_RATE_176_4_DP_1_62_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) case HAD_MAX_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) maud_val = HAD_MAX_RATE_DP_1_62_MAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) maud_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) maud_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return maud_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * Program HDMI audio CTS value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * @aud_samp_freq: sampling frequency of audio data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * @tmds: sampling frequency of the display data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * @link_rate: DP link rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * @n_param: N value, depends on aud_samp_freq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * @intelhaddata: substream private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * Program CTS register based on the audio and display sampling frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static void had_prog_cts(u32 aud_samp_freq, u32 tmds, u32 link_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) u32 n_param, struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) u32 cts_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) u64 dividend, divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (intelhaddata->dp_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) /* Substitute cts_val with Maud according to DP 1.2 spec*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) cts_val = had_calculate_maud_value(aud_samp_freq, link_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /* Calculate CTS according to HDMI 1.3a spec*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) dividend = (u64)tmds * n_param*1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) divisor = 128 * aud_samp_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) cts_val = div64_u64(dividend, divisor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) dev_dbg(intelhaddata->dev, "TMDS value=%d, N value=%d, CTS Value=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) tmds, n_param, cts_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) had_write_register(intelhaddata, AUD_HDMI_CTS, (BIT(24) | cts_val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static int had_calculate_n_value(u32 aud_samp_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) int n_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) /* Select N according to HDMI 1.3a spec*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) switch (aud_samp_freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) case AUD_SAMPLE_RATE_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) n_val = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) case AUD_SAMPLE_RATE_44_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) n_val = 6272;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) case AUD_SAMPLE_RATE_48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) n_val = 6144;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) case AUD_SAMPLE_RATE_88_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) n_val = 12544;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) case AUD_SAMPLE_RATE_96:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) n_val = 12288;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) case AUD_SAMPLE_RATE_176_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) n_val = 25088;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case HAD_MAX_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) n_val = 24576;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) n_val = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return n_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * Program HDMI audio N value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * @aud_samp_freq: sampling frequency of audio data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * @n_param: N value, depends on aud_samp_freq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * @intelhaddata: substream private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * This function is called in the prepare callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * It programs based on the audio and display sampling frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) static int had_prog_n(u32 aud_samp_freq, u32 *n_param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) int n_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (intelhaddata->dp_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * According to DP specs, Maud and Naud values hold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * a relationship, which is stated as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * Maud/Naud = 512 * fs / f_LS_Clk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * where, fs is the sampling frequency of the audio stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * and Naud is 32768 for Async clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) n_val = DP_NAUD_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) n_val = had_calculate_n_value(aud_samp_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (n_val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) return n_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) had_write_register(intelhaddata, AUD_N_ENABLE, (BIT(24) | n_val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) *n_param = n_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * PCM ring buffer handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * The hardware provides a ring buffer with the fixed 4 buffer descriptors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * (BDs). The driver maps these 4 BDs onto the PCM ring buffer. The mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * moves at each period elapsed. The below illustrates how it works:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * At time=0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * BD | 0 | 1 | 2 | 3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) * At time=1 (period elapsed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * BD | 1 | 2 | 3 | 0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * At time=2 (second period elapsed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * BD | 2 | 3 | 0 | 1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * The bd_head field points to the index of the BD to be read. It's also the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * position to be filled at next. The pcm_head and the pcm_filled fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * point to the indices of the current position and of the next position to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * be filled, respectively. For PCM buffer there are both _head and _filled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * because they may be difference when nperiods > 4. For example, in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * example above at t=1, bd_head=1 and pcm_head=1 while pcm_filled=5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * pcm_head (=1) --v v-- pcm_filled (=5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * BD | 1 | 2 | 3 | 0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * bd_head (=1) --^ ^-- next to fill (= bd_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * For nperiods < 4, the remaining BDs out of 4 are marked as invalid, so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * the hardware skips those BDs in the loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) * An exceptional setup is the case with nperiods=1. Since we have to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * BDs after finishing one BD processing, we'd need at least two BDs, where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * both BDs point to the same content, the same address, the same size of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * whole PCM buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) #define AUD_BUF_ADDR(x) (AUD_BUF_A_ADDR + (x) * HAD_REG_WIDTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) #define AUD_BUF_LEN(x) (AUD_BUF_A_LENGTH + (x) * HAD_REG_WIDTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /* Set up a buffer descriptor at the "filled" position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static void had_prog_bd(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) int idx = intelhaddata->bd_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) int ofs = intelhaddata->pcmbuf_filled * intelhaddata->period_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) u32 addr = substream->runtime->dma_addr + ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) addr |= AUD_BUF_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if (!substream->runtime->no_period_wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) addr |= AUD_BUF_INTR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) had_write_register(intelhaddata, AUD_BUF_ADDR(idx), addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) had_write_register(intelhaddata, AUD_BUF_LEN(idx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) intelhaddata->period_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /* advance the indices to the next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) intelhaddata->bd_head++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) intelhaddata->bd_head %= intelhaddata->num_bds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) intelhaddata->pcmbuf_filled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) intelhaddata->pcmbuf_filled %= substream->runtime->periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /* invalidate a buffer descriptor with the given index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static void had_invalidate_bd(struct snd_intelhad *intelhaddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) had_write_register(intelhaddata, AUD_BUF_ADDR(idx), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) had_write_register(intelhaddata, AUD_BUF_LEN(idx), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* Initial programming of ring buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) static void had_init_ringbuf(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) int i, num_periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) num_periods = runtime->periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) intelhaddata->num_bds = min(num_periods, HAD_NUM_OF_RING_BUFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /* set the minimum 2 BDs for num_periods=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) intelhaddata->num_bds = max(intelhaddata->num_bds, 2U);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) intelhaddata->period_bytes =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) frames_to_bytes(runtime, runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) WARN_ON(intelhaddata->period_bytes & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) intelhaddata->bd_head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) intelhaddata->pcmbuf_head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) intelhaddata->pcmbuf_filled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) for (i = 0; i < HAD_NUM_OF_RING_BUFS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (i < intelhaddata->num_bds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) had_prog_bd(substream, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) else /* invalidate the rest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) had_invalidate_bd(intelhaddata, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) intelhaddata->bd_head = 0; /* reset at head again before starting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* process a bd, advance to the next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) static void had_advance_ringbuf(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) int num_periods = substream->runtime->periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) /* reprogram the next buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) had_prog_bd(substream, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /* proceed to next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) intelhaddata->pcmbuf_head++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) intelhaddata->pcmbuf_head %= num_periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /* process the current BD(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * returns the current PCM buffer byte position, or -EPIPE for underrun.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) static int had_process_ringbuf(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) int len, processed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) processed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) spin_lock_irqsave(&intelhaddata->had_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /* get the remaining bytes on the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) had_read_register(intelhaddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) AUD_BUF_LEN(intelhaddata->bd_head),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (len < 0 || len > intelhaddata->period_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) dev_dbg(intelhaddata->dev, "Invalid buf length %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) len = -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (len > 0) /* OK, this is the current buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /* len=0 => already empty, check the next buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (++processed >= intelhaddata->num_bds) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) len = -EPIPE; /* all empty? - report underrun */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) had_advance_ringbuf(substream, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) len = intelhaddata->period_bytes - len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) len += intelhaddata->period_bytes * intelhaddata->pcmbuf_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) /* called from irq handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) static void had_process_buffer_done(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) substream = had_substream_get(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (!substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return; /* no stream? - bail out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (!intelhaddata->connected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) snd_pcm_stop_xrun(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) goto out; /* disconnected? - bail out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) /* process or stop the stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (had_process_ringbuf(substream, intelhaddata) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) snd_pcm_stop_xrun(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) snd_pcm_period_elapsed(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) had_substream_put(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * The interrupt status 'sticky' bits might not be cleared by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * setting '1' to that bit once...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) static void wait_clear_underrun_bit(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) for (i = 0; i < 100; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) /* clear bit30, 31 AUD_HDMI_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) had_read_register(intelhaddata, AUD_HDMI_STATUS, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (!(val & AUD_HDMI_STATUS_MASK_UNDERRUN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) had_write_register(intelhaddata, AUD_HDMI_STATUS, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) dev_err(intelhaddata->dev, "Unable to clear UNDERRUN bits\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /* Perform some reset procedure but only when need_reset is set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) * this is called from prepare or hw_free callbacks once after trigger STOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * or underrun has been processed in order to settle down the h/w state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) static void had_do_reset(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if (!intelhaddata->need_reset || !intelhaddata->connected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /* Reset buffer pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) had_reset_audio(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) wait_clear_underrun_bit(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) intelhaddata->need_reset = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /* called from irq handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) static void had_process_buffer_underrun(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) /* Report UNDERRUN error to above layers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) substream = had_substream_get(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) snd_pcm_stop_xrun(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) had_substream_put(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) intelhaddata->need_reset = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * ALSA PCM open callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) static int had_pcm_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) struct snd_intelhad *intelhaddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) struct snd_pcm_runtime *runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) intelhaddata = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) pm_runtime_get_sync(intelhaddata->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) /* set the runtime hw parameter with local snd_pcm_hardware struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) runtime->hw = had_pcm_hardware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) retval = snd_pcm_hw_constraint_integer(runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) SNDRV_PCM_HW_PARAM_PERIODS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /* Make sure, that the period size is always aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) * 64byte boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) retval = snd_pcm_hw_constraint_step(substream->runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) retval = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) /* expose PCM substream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) spin_lock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) intelhaddata->stream_info.substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) intelhaddata->stream_info.substream_refcount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) spin_unlock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) pm_runtime_mark_last_busy(intelhaddata->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) pm_runtime_put_autosuspend(intelhaddata->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * ALSA PCM close callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) static int had_pcm_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) struct snd_intelhad *intelhaddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) intelhaddata = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /* unreference and sync with the pending PCM accesses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) spin_lock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) intelhaddata->stream_info.substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) intelhaddata->stream_info.substream_refcount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) while (intelhaddata->stream_info.substream_refcount > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) spin_unlock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) spin_lock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) spin_unlock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) pm_runtime_mark_last_busy(intelhaddata->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) pm_runtime_put_autosuspend(intelhaddata->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) * ALSA PCM hw_params callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static int had_pcm_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct snd_intelhad *intelhaddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) int buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) intelhaddata = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) buf_size = params_buffer_bytes(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) dev_dbg(intelhaddata->dev, "%s:allocated memory = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) __func__, buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * ALSA PCM hw_free callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) static int had_pcm_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) struct snd_intelhad *intelhaddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) intelhaddata = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) had_do_reset(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) * ALSA PCM trigger callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) struct snd_intelhad *intelhaddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) intelhaddata = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) spin_lock(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) /* Enable Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) had_ack_irqs(intelhaddata); /* FIXME: do we need this? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) had_enable_audio(intelhaddata, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) /* Disable Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) had_enable_audio(intelhaddata, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) intelhaddata->need_reset = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) spin_unlock(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) * ALSA PCM prepare callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static int had_pcm_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) u32 disp_samp_freq, n_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) u32 link_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) struct snd_intelhad *intelhaddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) struct snd_pcm_runtime *runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) intelhaddata = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) dev_dbg(intelhaddata->dev, "period_size=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) (int)frames_to_bytes(runtime, runtime->period_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) dev_dbg(intelhaddata->dev, "periods=%d\n", runtime->periods);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) dev_dbg(intelhaddata->dev, "buffer_size=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) (int)snd_pcm_lib_buffer_bytes(substream));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) dev_dbg(intelhaddata->dev, "rate=%d\n", runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) dev_dbg(intelhaddata->dev, "channels=%d\n", runtime->channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) had_do_reset(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) /* Get N value in KHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) disp_samp_freq = intelhaddata->tmds_clock_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) retval = had_prog_n(substream->runtime->rate, &n_param, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) dev_err(intelhaddata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) "programming N value failed %#x\n", retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) goto prep_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (intelhaddata->dp_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) link_rate = intelhaddata->link_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) had_prog_cts(substream->runtime->rate, disp_samp_freq, link_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) n_param, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) had_prog_dip(substream, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) retval = had_init_audio_ctrl(substream, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) /* Prog buffer address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) had_init_ringbuf(substream, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * Program channel mapping in following order:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) * FL, FR, C, LFE, RL, RR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) had_write_register(intelhaddata, AUD_BUF_CH_SWAP, SWAP_LFE_CENTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) prep_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) * ALSA PCM pointer callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) static snd_pcm_uframes_t had_pcm_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) struct snd_intelhad *intelhaddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) intelhaddata = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (!intelhaddata->connected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) return SNDRV_PCM_POS_XRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) len = had_process_ringbuf(substream, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return SNDRV_PCM_POS_XRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) len = bytes_to_frames(substream->runtime, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) /* wrapping may happen when periods=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) len %= substream->runtime->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) * ALSA PCM mmap callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) static int had_pcm_mmap(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return remap_pfn_range(vma, vma->vm_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) substream->runtime->dma_addr >> PAGE_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) vma->vm_end - vma->vm_start, vma->vm_page_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * ALSA PCM ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) static const struct snd_pcm_ops had_pcm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) .open = had_pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) .close = had_pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) .hw_params = had_pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) .hw_free = had_pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) .prepare = had_pcm_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) .trigger = had_pcm_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) .pointer = had_pcm_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) .mmap = had_pcm_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) /* process mode change of the running stream; called in mutex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) static int had_process_mode_change(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) u32 disp_samp_freq, n_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) u32 link_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) substream = had_substream_get(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (!substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) /* Disable Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) had_enable_audio(intelhaddata, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) /* Update CTS value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) disp_samp_freq = intelhaddata->tmds_clock_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) retval = had_prog_n(substream->runtime->rate, &n_param, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) dev_err(intelhaddata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) "programming N value failed %#x\n", retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (intelhaddata->dp_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) link_rate = intelhaddata->link_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) had_prog_cts(substream->runtime->rate, disp_samp_freq, link_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) n_param, intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) /* Enable Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) had_enable_audio(intelhaddata, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) had_substream_put(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) /* process hot plug, called from wq with mutex locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) static void had_process_hot_plug(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) spin_lock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (intelhaddata->connected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) dev_dbg(intelhaddata->dev, "Device already connected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) spin_unlock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) /* Disable Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) had_enable_audio(intelhaddata, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) intelhaddata->connected = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) dev_dbg(intelhaddata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) spin_unlock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) had_build_channel_allocation_map(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) /* Report to above ALSA layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) substream = had_substream_get(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) snd_pcm_stop_xrun(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) had_substream_put(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) snd_jack_report(intelhaddata->jack, SND_JACK_AVOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /* process hot unplug, called from wq with mutex locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) static void had_process_hot_unplug(struct snd_intelhad *intelhaddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) spin_lock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (!intelhaddata->connected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) dev_dbg(intelhaddata->dev, "Device already disconnected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) spin_unlock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) /* Disable Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) had_enable_audio(intelhaddata, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) intelhaddata->connected = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) dev_dbg(intelhaddata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_DISCONNECTED\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) spin_unlock_irq(&intelhaddata->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) kfree(intelhaddata->chmap->chmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) intelhaddata->chmap->chmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) /* Report to above ALSA layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) substream = had_substream_get(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if (substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) snd_pcm_stop_xrun(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) had_substream_put(intelhaddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) snd_jack_report(intelhaddata->jack, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) * ALSA iec958 and ELD controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) static int had_iec958_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) static int had_iec958_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) mutex_lock(&intelhaddata->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) ucontrol->value.iec958.status[0] = (intelhaddata->aes_bits >> 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) ucontrol->value.iec958.status[1] = (intelhaddata->aes_bits >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) ucontrol->value.iec958.status[2] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) (intelhaddata->aes_bits >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) ucontrol->value.iec958.status[3] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) (intelhaddata->aes_bits >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) mutex_unlock(&intelhaddata->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) static int had_iec958_mask_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) ucontrol->value.iec958.status[0] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) ucontrol->value.iec958.status[1] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) ucontrol->value.iec958.status[2] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) ucontrol->value.iec958.status[3] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) static int had_iec958_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) val = (ucontrol->value.iec958.status[0] << 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) (ucontrol->value.iec958.status[1] << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) (ucontrol->value.iec958.status[2] << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) (ucontrol->value.iec958.status[3] << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) mutex_lock(&intelhaddata->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (intelhaddata->aes_bits != val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) intelhaddata->aes_bits = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) mutex_unlock(&intelhaddata->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) static int had_ctl_eld_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) uinfo->count = HDMI_MAX_ELD_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) static int had_ctl_eld_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) mutex_lock(&intelhaddata->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) memcpy(ucontrol->value.bytes.data, intelhaddata->eld,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) HDMI_MAX_ELD_BYTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) mutex_unlock(&intelhaddata->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) static const struct snd_kcontrol_new had_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) .access = SNDRV_CTL_ELEM_ACCESS_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) .info = had_iec958_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) .get = had_iec958_mask_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) .info = had_iec958_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) .get = had_iec958_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) .put = had_iec958_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) .access = (SNDRV_CTL_ELEM_ACCESS_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) SNDRV_CTL_ELEM_ACCESS_VOLATILE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) .name = "ELD",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) .info = had_ctl_eld_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) .get = had_ctl_eld_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) * audio interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) struct snd_intelhad_card *card_ctx = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) u32 audio_stat[3] = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) int pipe, port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) for_each_pipe(card_ctx, pipe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) /* use raw register access to ack IRQs even while disconnected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) audio_stat[pipe] = had_read_register_raw(card_ctx, pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) AUD_HDMI_STATUS) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) (HDMI_AUDIO_UNDERRUN | HDMI_AUDIO_BUFFER_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) if (audio_stat[pipe])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) had_write_register_raw(card_ctx, pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) AUD_HDMI_STATUS, audio_stat[pipe]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) for_each_port(card_ctx, port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) int pipe = ctx->pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) if (pipe < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) if (audio_stat[pipe] & HDMI_AUDIO_BUFFER_DONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) had_process_buffer_done(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) if (audio_stat[pipe] & HDMI_AUDIO_UNDERRUN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) had_process_buffer_underrun(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) * monitor plug/unplug notification from i915; just kick off the work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) static void notify_audio_lpe(struct platform_device *pdev, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) struct snd_intelhad *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) ctx = &card_ctx->pcm_ctx[single_port ? 0 : port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (single_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) ctx->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) schedule_work(&ctx->hdmi_audio_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) /* the work to handle monitor hot plug/unplug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) static void had_audio_wq(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) struct snd_intelhad *ctx =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) container_of(work, struct snd_intelhad, hdmi_audio_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) struct intel_hdmi_lpe_audio_port_pdata *ppdata = &pdata->port[ctx->port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) pm_runtime_get_sync(ctx->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) mutex_lock(&ctx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) if (ppdata->pipe < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG : port = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) __func__, ctx->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) memset(ctx->eld, 0, sizeof(ctx->eld)); /* clear the old ELD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) ctx->dp_output = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) ctx->tmds_clock_speed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) ctx->link_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) /* Shut down the stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) had_process_hot_unplug(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) ctx->pipe = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) dev_dbg(ctx->dev, "%s: HAD_NOTIFY_ELD : port = %d, tmds = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) __func__, ctx->port, ppdata->ls_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) memcpy(ctx->eld, ppdata->eld, sizeof(ctx->eld));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) ctx->dp_output = ppdata->dp_output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) if (ctx->dp_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) ctx->tmds_clock_speed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) ctx->link_rate = ppdata->ls_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) ctx->tmds_clock_speed = ppdata->ls_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) ctx->link_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * Shut down the stream before we change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) * the pipe assignment for this pcm device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) had_process_hot_plug(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) ctx->pipe = ppdata->pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) /* Restart the stream if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) had_process_mode_change(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) mutex_unlock(&ctx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) pm_runtime_mark_last_busy(ctx->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) pm_runtime_put_autosuspend(ctx->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) * Jack interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) static int had_create_jack(struct snd_intelhad *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) struct snd_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) char hdmi_str[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) snprintf(hdmi_str, sizeof(hdmi_str),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) "HDMI/DP,pcm=%d", pcm->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) err = snd_jack_new(ctx->card_ctx->card, hdmi_str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) SND_JACK_AVOUT, &ctx->jack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) true, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) ctx->jack->private_data = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) * PM callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) static int __maybe_unused hdmi_lpe_audio_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) static int __maybe_unused hdmi_lpe_audio_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) /* release resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) static void hdmi_lpe_audio_free(struct snd_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) struct snd_intelhad_card *card_ctx = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) struct intel_hdmi_lpe_audio_pdata *pdata = card_ctx->dev->platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) spin_lock_irq(&pdata->lpe_audio_slock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) pdata->notify_audio_lpe = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) spin_unlock_irq(&pdata->lpe_audio_slock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) for_each_port(card_ctx, port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) cancel_work_sync(&ctx->hdmi_audio_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (card_ctx->mmio_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) iounmap(card_ctx->mmio_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (card_ctx->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) free_irq(card_ctx->irq, card_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) * hdmi_lpe_audio_probe - start bridge with i915
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) * This function is called when the i915 driver creates the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) * hdmi-lpe-audio platform device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) static int hdmi_lpe_audio_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) struct snd_intelhad_card *card_ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) struct snd_intelhad *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) struct intel_hdmi_lpe_audio_pdata *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) struct resource *res_mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) int port, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) dev_err(&pdev->dev, "%s: quit: pdata not allocated by i915!!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) /* get resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) res_mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) if (!res_mmio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) dev_err(&pdev->dev, "Could not get IO_MEM resources\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) /* create a card instance with ALSA framework */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) ret = snd_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) THIS_MODULE, sizeof(*card_ctx), &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) card_ctx = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) card_ctx->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) card_ctx->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) strcpy(card->driver, INTEL_HAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) strcpy(card->shortname, "Intel HDMI/DP LPE Audio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) strcpy(card->longname, "Intel HDMI/DP LPE Audio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) card_ctx->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) card->private_free = hdmi_lpe_audio_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) platform_set_drvdata(pdev, card_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) card_ctx->num_pipes = pdata->num_pipes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) card_ctx->num_ports = single_port ? 1 : pdata->num_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) for_each_port(card_ctx, port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) ctx = &card_ctx->pcm_ctx[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) ctx->card_ctx = card_ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) ctx->dev = card_ctx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) ctx->port = single_port ? -1 : port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) ctx->pipe = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) spin_lock_init(&ctx->had_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) mutex_init(&ctx->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) __func__, (unsigned int)res_mmio->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) (unsigned int)res_mmio->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) card_ctx->mmio_start = ioremap(res_mmio->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) (size_t)(resource_size(res_mmio)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) if (!card_ctx->mmio_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) dev_err(&pdev->dev, "Could not get ioremap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) ret = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) /* setup interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) ret = request_irq(irq, display_pipe_interrupt_handler, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) pdev->name, card_ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) dev_err(&pdev->dev, "request_irq failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) card_ctx->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) /* only 32bit addressable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) init_channel_allocations();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) card_ctx->num_pipes = pdata->num_pipes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) card_ctx->num_ports = single_port ? 1 : pdata->num_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) for_each_port(card_ctx, port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) ctx = &card_ctx->pcm_ctx[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) MAX_CAP_STREAMS, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) /* setup private data which can be retrieved when required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) pcm->private_data = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) strlcpy(pcm->name, card->shortname, strlen(card->shortname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) /* setup the ops for playabck */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) /* allocate dma pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) * try to allocate 600k buffer as default which is large enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_UC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) card->dev, HAD_DEFAULT_BUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) HAD_MAX_BUFFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) /* create controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) for (i = 0; i < ARRAY_SIZE(had_controls); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) struct snd_kcontrol *kctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) kctl = snd_ctl_new1(&had_controls[i], ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) if (!kctl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) kctl->id.device = pcm->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) ret = snd_ctl_add(card, kctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) /* Register channel map controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) ret = had_register_chmap_ctls(ctx, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) ret = had_create_jack(ctx, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) ret = snd_card_register(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) spin_lock_irq(&pdata->lpe_audio_slock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) pdata->notify_audio_lpe = notify_audio_lpe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) spin_unlock_irq(&pdata->lpe_audio_slock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) pm_runtime_use_autosuspend(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) pm_runtime_mark_last_busy(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) dev_dbg(&pdev->dev, "%s: handle pending notification\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) for_each_port(card_ctx, port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) schedule_work(&ctx->hdmi_audio_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) * hdmi_lpe_audio_remove - stop bridge with i915
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) * This function is called when the platform device is destroyed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) static int hdmi_lpe_audio_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) snd_card_free(card_ctx->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) static const struct dev_pm_ops hdmi_lpe_audio_pm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) SET_SYSTEM_SLEEP_PM_OPS(hdmi_lpe_audio_suspend, hdmi_lpe_audio_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) static struct platform_driver hdmi_lpe_audio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) .name = "hdmi-lpe-audio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) .pm = &hdmi_lpe_audio_pm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) .probe = hdmi_lpe_audio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) .remove = hdmi_lpe_audio_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) module_platform_driver(hdmi_lpe_audio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) MODULE_ALIAS("platform:hdmi_lpe_audio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) MODULE_AUTHOR("Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) MODULE_AUTHOR("Ramesh Babu K V <ramesh.babu@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) MODULE_AUTHOR("Vaibhav Agarwal <vaibhav.agarwal@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) MODULE_AUTHOR("Jerome Anand <jerome.anand@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) MODULE_DESCRIPTION("Intel HDMI Audio driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) MODULE_SUPPORTED_DEVICE("{Intel,Intel_HAD}");