Exemplo n.º 1
0
/*used for low bit rate compacted data,  SPDIF-->HDMI*/
static int hi3620_digital_tx2_enable(unsigned int aformat,unsigned int dataformat, unsigned int infreq_index,unsigned int outfreq_index, struct hi3620_tx_runtime_data* tx)
{
    unsigned int value = 0;

    IN_FUNCTION;

    //HDMI use SPDIF, SPDIF also enabled
    tx->dmaa = TX2_DMA_A;
    tx->dmab = TX2_DMA_B;
    tx->dmas = TX2_DMAS;

    //choose SPDIF
    hi3620_reg_write(1, ASP_SPDIFSELR);

    //ASP_TX2
    /* set  output rate */
    hi3620_set_tx123_outfreq(outfreq_index);

    value = TX2_EN_BIT | HIGHBIT_IS_LEFT |TX2_TSEN_BIT |dataformat;//enable TX2 and transparent
    hi3620_reg_write(value, ASP_TX2);

    /* ENABLE TX2 DMA INTERRUPT */
    wait_dma_stop(TX2_DMAS);
    hi3620_reg_write(TX2_DMAS, ASP_ICR);
    hi3620_set_bits(TX2_DMAS | ASP_BUS_ERROR, ASP_IER);

    //SPDIF
    hi3620_reg_write(0x0, SPDIF_CTRL); //Reset SPDIF, for the Left and Right channel's data might abnormal exchange when audio paused and restarted
    hi3620_reg_write(1, SPDIF_CONFIG);//not line-pcm
    hi3620_reg_write(0x7, SPDIF_IRQ_MASK);//interrupt mask

    hi3620_reg_write(0x606, SPDIF_CH_STATUS1);//not line-pcm
    hi3620_reg_write(0x0, SPDIF_CH_STATUS2); // DVD
    hi3620_reg_write(0x2010, SPDIF_CH_STATUS3);//left-->left,right-->right
    switch(outfreq_index) {
    case HI3620_RATE_INDEX_32000:
        value = 0x303;
        break;
    case HI3620_RATE_INDEX_44100:
        value = 0x0;
        break;
    case HI3620_RATE_INDEX_96000:
        value = 0xA0A;
        break;
    case HI3620_RATE_INDEX_176400:
        value = 0xC0C;
        break;
    case HI3620_RATE_INDEX_192000:
        value = 0xE0E;
        break;
    case HI3620_RATE_INDEX_48000:
    default:
        value = 0x202;
        break;
    }
    hi3620_reg_write(value, SPDIF_CH_STATUS4);

    switch(infreq_index) {
    case HI3620_RATE_INDEX_32000:
        value = 0xC0C0;
        break;
    case HI3620_RATE_INDEX_44100:
        value = 0xF0F0;
        break;
    case HI3620_RATE_INDEX_96000:
        value = 0x5050;
        break;
    case HI3620_RATE_INDEX_176400:
        value = 0x3030;
        break;
    case HI3620_RATE_INDEX_192000:
        value = 0x1010;
        break;
    case HI3620_RATE_INDEX_48000:
    default:
        value = 0xD0D0;
        break;
    }
    value |= 0x202; // 16bits
    hi3620_reg_write(value,SPDIF_CH_STATUS5);

    hi3620_reg_write(0x5, SPDIF_CTRL); //FIFO 16,enable

#ifdef HDMI_DISPLAY
    /*if use SPDIF for passthrough, HDMI needn't power on*/
    if (g_digitaloutStatus != 0) {
        //init HDMI start
        k3_hdmi_audio_set_param(freq[outfreq_index], HDMI_SAMPLE_16BITS, false, 0, aformat );
    }
#endif

    OUT_FUNCTION;

    return 0;
}
Exemplo n.º 2
0
/*used for low bit rate compacted data,  SIO1-->HDMI*/
static int hi3620_digital_tx3_enable(unsigned int aformat, unsigned int dataformat, unsigned int infreq_index,unsigned int outfreq_index, struct hi3620_tx_runtime_data* tx)
{
    unsigned int value = 0;

    IN_FUNCTION;

    //HDMI use I2S1, SPDIF diaabled
    tx->dmaa = TX3_DMA_A;
    tx->dmab = TX3_DMA_B;
    tx->dmas = TX3_DMAS;

    /* Set resample rate */
    hi3620_reg_write(infreq_index, ASP_TX3RSRR);

    /* set  output rate */
    hi3620_set_tx123_outfreq(outfreq_index);
    //HDMI choose SIO1
    hi3620_reg_write(0, ASP_SPDIFSELR);

    /* CONFIG SIO1 INTERFACE FOR PB */
    hi3620_reg_write(1, SIO1_ASPIF_SEL);//enable SIO1
    hi3620_reg_write(SIO_TX_ENABLE | SIO_TX_FIFO, SIO1_I2S_CLR);//bits same as SIO0
    hi3620_set_bits(SIO_TX_ENABLE | SIO_TX_FIFO, SIO1_I2S_SET);

    //ASP_TX3
    if (aformat <= AFORMAT_PCM) {
        // 5.1/7.1 PCM
        value = TX3_EN_BIT;//enable TX3
    } else {
        //compressed
        value = TX3_EN_BIT |TX3_TSEN_BIT;//enable TX3 and transparent
    }

    switch(dataformat&0x7) {
    case STEREO_18BIT:
        value |= 0x1;
        break;
    case STEREO_20BIT:
        value |= 0x2;
        break;
    case STEREO_24BIT:
        value |= 0x3;
        break;
    case STEREO_16BIT:
    default:
        break;
    }
    hi3620_reg_write(value, ASP_TX3);

    /* ENABLE TX3 DMA INTERRUPT */
    wait_dma_stop(TX3_DMAS);
    hi3620_reg_write(TX3_DMAS, ASP_ICR);
    hi3620_set_bits(TX3_DMAS | ASP_BUS_ERROR, ASP_IER);

#ifdef HDMI_DISPLAY
    //init HDMI start
    k3_hdmi_audio_set_param(freq[outfreq_index], HDMI_SAMPLE_16BITS, true, 1, aformat );
#endif

    OUT_FUNCTION;

    return 0;
}
static int hi3630_pcm_hdmi_hw_params(struct snd_pcm_substream *substream,
					 struct snd_pcm_hw_params *params)
{
	struct hi3630_hdmi_runtime_data *prtd = substream->runtime->private_data;
	struct hi3630_hdmi_data *pdata = prtd->pdata;
	unsigned long bytes = params_buffer_bytes(params);
	unsigned int params_value = 0;
	unsigned int channels = 0;
	unsigned int infreq_index = 0;
	unsigned int outfreq_index = 0;
	unsigned int width = 0;
	unsigned int format = 0;
	int txValue = 0;
	int ret = 0;

	if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
		ret = snd_pcm_lib_malloc_pages(substream, bytes);
		if (0 > ret) {
			loge("snd_pcm_lib_malloc_pages ret is %d", ret);
			return ret;
		}

		/* CHECK SUPPORT CHANNELS : mono or stereo */
		params_value = params_channels(params);
		if (2 == params_value || 1 == params_value) {
			channels = params_value;
		} else {
			loge("DAC not support %d channels\n", params_value);
			ret = -EINVAL;
			goto err_out;
		}
		params_value = params_rate(params);
		logd("set rate = %d \n", params_value);
		for (infreq_index = 0; infreq_index < ARRAY_SIZE(freq); infreq_index++) {
			if(params_value == freq[infreq_index])
				break;
		}
		if ( ARRAY_SIZE(freq) <= infreq_index) {
			loge("set rate = %d error\n", params_value);
			return -EINVAL;
		}
		hi3630_get_afrequency(infreq_index, &outfreq_index, channels);

		params_value = params_format(params);
		/* check formats */
		switch (params_value) {
		case SNDRV_PCM_FORMAT_S16_BE :
			format = HDMI_BIG_DIAN_BIT;
			/* fallthrough */
		case SNDRV_PCM_FORMAT_S16_LE :
			if (2 == channels)
				width = STEREO_16BIT;
			break;
		default :
			loge("format err : %d, not support\n", params_value);
			ret = -EINVAL;
			goto err_out;
		}

		mutex_lock(&prtd->mutex);
		prtd->period_size = params_period_bytes(params);
		mutex_unlock(&prtd->mutex);

		txValue = hi3630_hdmi_reg_read(pdata, HI3630_ASP_TX3);
		txValue |= (width << 3) | (1 << 6) | ((channels-1) << 7) |format;
		hi3630_hdmi_reg_write(pdata, HI3630_ASP_TX3, txValue);
		logi("hdmi params.freq:%d, channel:%d\n", freq[outfreq_index], channels);
		k3_hdmi_audio_set_param(freq[outfreq_index], HDMI_SAMPLE_16BITS, true, 0, 1, channels);

err_out:
		if (0 > ret) {
			loge("hw params error, ret : %d\n", ret);
			snd_pcm_lib_free_pages(substream);
		}
	}

	return ret;
}