/*
 * Allwinner SoCs hdmi2.0 driver.
 *
 * Copyright (C) 2016 Allwinner.
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */


#ifndef AUDIO_H_
#define AUDIO_H_

#include "../hdmitx_dev.h"
#include "main_controller.h"
#include "../log.h"
#include "../general_ops.h"
#include "packets.h"
#include "frame_composer_reg.h"

#include "../access.h"

/*****************************************************************************
 *                                                                           *
 *                        Audio Sample SPDIF Registers                       *
 *                                                                           *
 *****************************************************************************/

/* Audio SPDIF Software FIFO Reset Control Register 0 This register allows the system processor to reset audio FIFOs upon underflow/overflow error detection */
#define AUD_SPDIF0  0x0000CC00
#define AUD_SPDIF0_SPARE_MASK  0x0000007F /* This field is a "spare" bit with no associated functionality */
#define AUD_SPDIF0_SW_AUDIO_FIFO_RST_MASK  0x00000080 /* Audio FIFOs software reset Writing 0b: no action taken Writing 1b: Resets all audio FIFOs Reading from this register always returns 0b */

/* Audio SPDIF NLPCM and Width Configuration Register 1 This register configures the SPDIF data width */
#define AUD_SPDIF1  0x0000CC04
#define AUD_SPDIF1_SPDIF_WIDTH_MASK  0x0000001F /* SPDIF input data width SPDIF_width[4:0] | Action 00000b-01111b | Not used 10000b | 16-bit data samples at input 10001b | 17-bit data samples at input 10010b | 18-bit data samples at input 10011b | 19-bit data samples at input 10100b | 20-bit data samples at input 10101b | 21-bit data samples at input 10110b | 22-bit data samples at input 10111b | 23-bit data samples at input 11000b | 24-bit data samples at input 11001b-11111b | Not Used */
#define AUD_SPDIF1_SPARE_MASK  0x00000020 /* This field is a "spare" bit with no associated functionality */
#define AUD_SPDIF1_SPDIF_HBR_MODE_MASK  0x00000040 /* When set to 1'b1, this bit field indicates that the input stream has a High Bit Rate (HBR) to be transmitted in HDMI HBR packets */
#define AUD_SPDIF1_SETNLPCM_MASK  0x00000080 /* Select Non-Linear (1b) / Linear (0b) PCM mode */

/* Audio SPDIF FIFO Empty/Full Mask Register */
#define AUD_SPDIFINT  0x0000CC08
#define AUD_SPDIFINT_SPDIF_FIFO_FULL_MASK_MASK  0x00000004 /* SPDIF FIFO full mask */
#define AUD_SPDIFINT_SPDIF_FIFO_EMPTY_MASK_MASK  0x00000008 /* SPDIF FIFO empty mask */

/* Audio SPDIF Mask Interrupt Register 1 This register masks interrupts present in the SPDIF module */
#define AUD_SPDIFINT1  0x0000CC0C
#define AUD_SPDIFINT1_FIFO_OVERRUN_MASK_MASK  0x00000010 /* FIFO overrun mask */

/* Audio SPDIF Enable Configuration Register 2 */
#define AUD_SPDIF2  0x0000CC10
#define AUD_SPDIF2_IN_EN_MASK 0x0000000F

/*****************************************************************************
 *                                                                           *
 *                         Audio Packetizer Registers                        *
 *                                                                           *
 *****************************************************************************/

/* Audio Clock Regenerator N Value Register 1 For N expected values, refer to the HDMI 1 */
#define AUD_N1  0x0000C800
#define AUD_N1_AUDN_MASK  0x000000FF /* HDMI Audio Clock Regenerator N value */

/* Audio Clock Regenerator N Value Register 2 For N expected values, refer to the HDMI 1 */
#define AUD_N2  0x0000C804
#define AUD_N2_AUDN_MASK  0x000000FF /* HDMI Audio Clock Regenerator N value */

/* Audio Clock Regenerator N Value Register 3 For N expected values, refer to the HDMI 1 */
#define AUD_N3  0x0000C808
#define AUD_N3_AUDN_MASK  0x0000000F /* HDMI Audio Clock Regenerator N value */
#define AUD_N3_NCTS_ATOMIC_WRITE_MASK  0x00000080 /* When set, the new N and CTS values are only used when aud_n1 register is written */

/* Audio Clock Regenerator CTS Value Register 1 For CTS expected values, refer to the HDMI 1 */
#define AUD_CTS1  0x0000C80C
#define AUD_CTS1_AUDCTS_MASK  0x000000FF /* HDMI Audio Clock Regenerator CTS calculated value */

/* Audio Clock Regenerator CTS Register 2 For CTS expected values, refer to the HDMI 1 */
#define AUD_CTS2  0x0000C810
#define AUD_CTS2_AUDCTS_MASK  0x000000FF /* HDMI Audio Clock Regenerator CTS calculated value */

/* Audio Clock Regenerator CTS value Register 3 */
#define AUD_CTS3  0x0000C814
#define AUD_CTS3_AUDCTS_MASK  0x0000000F /* HDMI Audio Clock Regenerator CTS calculated value */
#define AUD_CTS3_CTS_MANUAL_MASK  0x00000010 /* If the CTS_manual bit equals 0b, this registers contains audCTS[19:0] generated by the Cycle time counter according to the specified timing */
#define AUD_CTS3_N_SHIFT_MASK  0x000000E0 /* N_shift factor configuration: N_shift | Shift Factor | Action 0 | 1 | This is the N shift factor used for the case that N' ="audN[19:0]" */

/* Audio Input Clock FS Factor Register */
#define AUD_INPUTCLKFS  0x0000C818
#define AUD_INPUTCLKFS_IFSFACTOR_MASK  0x00000007 /* Fs factor configuration: ifsfactor[2:0] | Audio Clock | Action 0 | 128xFs | If you select the Bypass SPDIF DRU unit in coreConsultant, the input audio clock (either I2S or SPDIF according to configuration) is used at the audio packetizer to calculate the CTS value and ACR packet insertion rate */



/*****************************************************************************
 *                                                                           *
 *                           Audio Sample Registers                          *
 *                                                                           *
 *****************************************************************************/

/* Audio I2S Software FIFO Reset, Select, and Enable Control Register 0 This register configures the I2S input enable that indicates which input I2S channels have valid data */
#define AUD_CONF0  0x0000C400
#define AUD_CONF0_I2S_IN_EN_MASK  0x0000000F /* Action I2S_in_en[0] - I2Sdata[0] enable I2S_in_en[1] - I2Sdata[1] enable I2S_in_en[2] - I2Sdata[2] enable I2S_in_en[3] - I2Sdata[3] enable */
#define AUD_CONF0_SPARE_1_MASK  0x00000010 /* This field is a "spare" bit with no associated functionality */
#define AUD_CONF0_I2S_SELECT_MASK  0x00000020 /* 1b: Selects I2S Audio Interface 0b: Selects the second (SPDIF/GPA) interface, in configurations with more that one audio interface (DOUBLE/GDOUBLE) */
#define AUD_CONF0_SPARE_2_MASK  0x00000040 /* This field is a "spare" bit with no associated functionality */
#define AUD_CONF0_SW_AUDIO_FIFO_RST_MASK  0x00000080 /* Audio FIFOs software reset - Writing 0b: no action taken - Writing 1b: Resets all audio FIFOs Reading from this register always returns 0b */

/* Audio I2S Width and Mode Configuration Register 1 This register configures the I2S mode and data width of the input data */
#define AUD_CONF1  0x0000C404
#define AUD_CONF1_I2S_WIDTH_MASK  0x0000001F /* I2S input data width I2S_width[4:0] | Action 00000b-01111b | Not used 10000b | 16 bit data samples at input 10001b | 17 bit data samples at input 10010b | 18 bit data samples at input 10011b | 19 bit data samples at input 10100b | 20 bit data samples at input 10101b | 21 bit data samples at input 10110b | 22 bit data samples at input 10111b | 23 bit data samples at input 11000b | 24 bit data samples at input 11001b-11111b | Not Used */
/* I2S input data mode I2S_mode[4:0] | Action */
/* 000b | Standard I2S mode */
/* 001b | Right-justified I2S mode */
/* 010b | Left-justified I2S mode */
/* 011b | Burst 1 mode */
/* 100b | Burst 2 mode */
#define AUD_CONF1_I2S_MODE_MASK  0x000000E0
/* I2S FIFO status and interrupts */
#define AUD_INT  0x0000C408
#define AUD_INT_FIFO_FULL_MASK_MASK  0x00000004 /* FIFO full mask */
#define AUD_INT_FIFO_EMPTY_MASK_MASK  0x00000008 /* FIFO empty mask */

/* Audio I2S NLPCM and HBR configuration Register 2 This register configures the I2S Audio Data mapping */
#define AUD_CONF2  0x0000C40C
#define AUD_CONF2_HBR_MASK  0x00000001 /* I2S HBR Mode Enable */
#define AUD_CONF2_NLPCM_MASK  0x00000002 /* I2S NLPCM Mode Enable */
#define AUD_CONF2_INSERT_PCUV_MASK 0x00000004

/* I2S Mask Interrupt Register This register masks the interrupts present in the I2S module */
#define AUD_INT1  0x0000C410
#define AUD_INT1_FIFO_OVERRUN_MASK_MASK  0x00000010 /* FIFO overrun mask */

/**
 * @param params pointer to the audio parameters structure
 * @return number of audio channels transmitted -1
 */
u8 audio_channel_count(hdmi_tx_dev_t *dev, audioParams_t *params);

/**
 * @param params pointer to the audio parameters structure
 */
u8 audio_iec_original_sampling_freq(hdmi_tx_dev_t *dev, audioParams_t *params);

/**
 * @param params pointer to the audio parameters structure
 */
u8 audio_iec_sampling_freq(hdmi_tx_dev_t *dev, audioParams_t *params);

/**
 * @param params pointer to the audio parameters structure
 */
u8 audio_iec_word_length(hdmi_tx_dev_t *dev, audioParams_t *params);

/**
 * return if channel is enabled or not using the user's channel allocation
 * code
 * @param params pointer to the audio parameters structure
 * @param channel in question -1
 * @return 1 if channel is to be enabled, 0 otherwise
 */
u8 audio_is_channel_en(hdmi_tx_dev_t *dev, audioParams_t *params, u8 channel);

void halAudioMultistream_MetaDataPacket_Header(hdmi_tx_dev_t *dev,
				audioMetaDataPacket_t *mAudioMetaDataPckt);
void halAudioMultistream_MetaDataPacketBody(hdmi_tx_dev_t *dev,
				audioMetaDataPacket_t *mAudioMetaDataPacket);

int audio_mute(hdmi_tx_dev_t *dev, u8 state);
int audio_Initialize(hdmi_tx_dev_t *dev);

/**
 * Configure hardware modules corresponding to user requirements to start transmitting audio packets.
 * @param baseAddr base Address of controller
 * @param params: audio parameters
 * @param pixelClk: pixel clock [0.01 MHz]
 * @param ratioClk: ratio clock (TMDS / Pixel) [0.01]
 * @return TRUE if successful
 */
int audio_Configure(hdmi_tx_dev_t *dev, audioParams_t *params);

extern void fc_audio_info_config(hdmi_tx_dev_t *dev, audioParams_t *audio);
u32 audio_iec_sampling_freq_get(hdmi_tx_dev_t *dev);

u8 audio_iec_word_length_get(hdmi_tx_dev_t *dev);
u32 _audio_clock_n_get(hdmi_tx_dev_t *dev);


#endif				/* AUDIO_H_ */
