Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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}");