mirror of
https://gitee.com/open-loongarch/linux-5.10.git
synced 2026-10-29 06:27:13 +08:00
694 lines
31 KiB
C
694 lines
31 KiB
C
/*
|
||
* wm8988.c -- WM8988 ALSA SoC audio driver
|
||
*
|
||
* Copyright 2009 Wolfson Microelectronics plc
|
||
* Copyright 2005 Openedhand Ltd.
|
||
*
|
||
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License version 2 as
|
||
* published by the Free Software Foundation.
|
||
*/
|
||
|
||
#include <linux/module.h>
|
||
#include <linux/moduleparam.h>
|
||
#include <linux/init.h>
|
||
#include <linux/clk.h>
|
||
#include <linux/delay.h>
|
||
#include <linux/pm.h>
|
||
#include <linux/i2c.h>
|
||
#include <linux/slab.h>
|
||
#include <sound/core.h>
|
||
#include <sound/pcm.h>
|
||
#include <sound/pcm_params.h>
|
||
#include <sound/tlv.h>
|
||
#include <sound/soc.h>
|
||
#include <sound/initval.h>
|
||
|
||
#include "cjc8988.h"
|
||
|
||
//*************************************************************************
|
||
// LINE Input 1 to ADC mode, slave mode, I2S format output, MCLK=12.288MHz, BCLK =3.072MHz, Fs=48KHz;
|
||
//
|
||
//static struct CJC8988_reg LINPUT1_TO_ADC[] = {
|
||
// {CJC8988_R0_LEFT_INPUT_VOLUME, 0x17}, // Audio input left channel volume; R/W
|
||
// {CJC8988_R1_RIGHT_INPUT_VOLUME, 0x17}, // Audio input right channel volume; R/W
|
||
// {CJC8988_R2_LOUT1_VOLUME, 0x79}, // Audio output letf channel1 volume; R/W
|
||
// {CJC8988_R3_ROUT1_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R5_ADC_DAC_CONTROL, 0x00}, // ADC and DAC CONTROL; R/W
|
||
// {CJC8988_R7_AUDIO_INTERFACE, 0x0A}, // Digital Audio interface format; R/W
|
||
// {CJC8988_R8_SAMPLE_RATE, 0x00}, // Clock and Sample rate control; R/W
|
||
// {CJC8988_R10_LEFT_DAC_VOLUME, 0xff}, // Left channel DAC digital volume; R/W
|
||
// {CJC8988_R11_RIGHT_DAC_VOLUME, 0xff}, // Right channel DAC digital volume; R/W
|
||
//
|
||
// {CJC8988_R12_BASS_CONTROL, 0x0f}, // BASS control; R/W
|
||
// {CJC8988_R13_TREBLE_CONTROL, 0x0f}, // Treble control; R/W
|
||
// {CJC8988_R16_3D_CONTROL, 0x00}, // 3D control; R/W
|
||
//
|
||
// {CJC8988_R21_LEFT_ADC_VOLUME, 0xc3}, // Left ADC digital volume; R/W
|
||
// {CJC8988_R22_RIGHT_ADC_VOLUME, 0xc3}, // Right ADC digital volume; R/W
|
||
//
|
||
// {CJC8988_R23_ADDITIONAL_CONTROL1, 0xc0}, // Additional control 1; R/W
|
||
// {CJC8988_R24_ADDITIONAL_CONTROL2, 0x04}, // Additional control 2; R/W
|
||
// {CJC8988_R27_ADDITIONAL_CONTROL3, 0x00}, // Additional control 3; R/W
|
||
//
|
||
// {CJC8988_R31_ADC_INPUT_MODE, 0x00}, // ADC input mode; R/W
|
||
//
|
||
// {CJC8988_R32_ADCL_SIGNAL_PATH, 0x00}, // Left ADC signal path control; R/W
|
||
// {CJC8988_R33_ADCR_SIGNAL_PATH, 0x00}, // Right ADC signal path control; R/W
|
||
//
|
||
// {CJC8988_R34_LEFT_OUT_MIX1_L, 0x52}, // Left DAC to left mixer disable; R/W
|
||
// {CJC8988_R35_LEFT_OUT_MIX2_L, 0x50}, // Right DAC to left mixer disable; R/W
|
||
// {CJC8988_R36_RIGHT_OUT_MIX1_L, 0x52}, // Left DAC to right mixer disable; R/W
|
||
// {CJC8988_R37_RIGHT_OUT_MIX2_L, 0x50}, // Right DAC to right mixer disable; R/W
|
||
//
|
||
// {CJC8988_R40_LOUT2_VOLUME, 0x79}, // Audio output left channel1 volume; R/W
|
||
// {CJC8988_R41_ROUT2_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R43_LOW_POWER_PLAYBACK, 0x00}, // Low power playback; R/W
|
||
//
|
||
// {CJC8988_R25_PWR_MGMT1_H, 0x7c}, // Power management1 and VMIDSEL; R/W
|
||
// {CJC8988_R26_PWR_MGMT2_L, 0x00}, // Power management2 and DAC left power down; R/W;
|
||
//};
|
||
//
|
||
//#define CJC8988_LINPUT1_TO_ADC_REG_NUM ARRAY_SIZE(LINPUT1_TO_ADC)
|
||
//
|
||
////*************************************************************************
|
||
//// DAC to LOUT1 mode, slave mode, I2S format input, MCLK=12.288MHz, BCLK =?MHz, Fs=48KHz;
|
||
////
|
||
//static struct CJC8988_reg DAC_TO_LOUT1_TEST[] = {
|
||
// {CJC8988_R0_LEFT_INPUT_VOLUME, 0x17}, // Audio input left channel volume; R/W
|
||
// {CJC8988_R1_RIGHT_INPUT_VOLUME, 0x17}, // Audio input right channel volume; R/W
|
||
// {CJC8988_R2_LOUT1_VOLUME, 0x30}, // Audio output letf channel1 volume; R/W
|
||
// {CJC8988_R3_ROUT1_VOLUME, 0x30}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R5_ADC_DAC_CONTROL, 0x00}, // ADC and DAC CONTROL; R/W
|
||
// {CJC8988_R7_AUDIO_INTERFACE, 0x0D}, // Digital Audio interface format; R/W
|
||
// //{CJC8988_R7_AUDIO_INTERFACE, 0x01}, // Digital Audio interface format; R/W
|
||
// {CJC8988_R8_SAMPLE_RATE, 0x00}, // Clock and Sample rate control; R/W
|
||
// {CJC8988_R10_LEFT_DAC_VOLUME, 0xff}, // Left channel DAC digital volume; R/W
|
||
// {CJC8988_R11_RIGHT_DAC_VOLUME, 0xff}, // Right channel DAC digital volume; R/W
|
||
//
|
||
// {CJC8988_R12_BASS_CONTROL, 0x0f}, // BASS control; R/W
|
||
// {CJC8988_R13_TREBLE_CONTROL, 0x0f}, // Treble control; R/W
|
||
// {CJC8988_R16_3D_CONTROL, 0x00}, // 3D control; R/W
|
||
//
|
||
// {CJC8988_R21_LEFT_ADC_VOLUME, 0xc3}, // Left ADC digital volume; R/W
|
||
// {CJC8988_R22_RIGHT_ADC_VOLUME, 0xc3}, // Right ADC digital volume; R/W
|
||
//
|
||
// {CJC8988_R23_ADDITIONAL_CONTROL1, 0xc0}, // Additional control 1; R/W
|
||
// {CJC8988_R24_ADDITIONAL_CONTROL2, 0x04}, // Additional control 2; R/W
|
||
// {CJC8988_R27_ADDITIONAL_CONTROL3, 0x00}, // Additional control 3; R/W
|
||
//
|
||
// {CJC8988_R31_ADC_INPUT_MODE, 0x00}, // ADC input mode; R/W
|
||
//
|
||
// {CJC8988_R32_ADCL_SIGNAL_PATH, 0x00}, // Left ADC signal path control; R/W
|
||
// {CJC8988_R33_ADCR_SIGNAL_PATH, 0x00}, // Right ADC signal path control; R/W
|
||
//
|
||
// {CJC8988_R34_LEFT_OUT_MIX1_H, 0x52}, // Left DAC to left mixer enable; R/W
|
||
// {CJC8988_R35_LEFT_OUT_MIX2_L, 0x50}, // Right DAC to left mixer disable; R/W
|
||
// {CJC8988_R36_RIGHT_OUT_MIX1_L, 0x52}, // Left DAC to right mixer disable; R/W
|
||
// {CJC8988_R37_RIGHT_OUT_MIX2_H, 0x50}, // Right DAC to right mixer enable; R/W
|
||
//
|
||
// {CJC8988_R40_LOUT2_VOLUME, 0x79}, // Audio output left channel1 volume; R/W
|
||
// {CJC8988_R41_ROUT2_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R43_LOW_POWER_PLAYBACK, 0x08}, // Low power playback; R/W
|
||
//
|
||
// {CJC8988_R25_PWR_MGMT1_H, 0x40}, // Power management1 and VMIDSEL; R/W
|
||
// {CJC8988_R26_PWR_MGMT2_H, 0xf8}, // Power management2 and DAC left power up; R/W;
|
||
//};
|
||
//
|
||
//#define CJC8988_DAC_TO_LOUT1_REG_NUM_TEST ARRAY_SIZE(DAC_TO_LOUT1_TEST)
|
||
//
|
||
////*************************************************************************
|
||
//// DAC to LOUT1 mode, slave mode, I2S format input, MCLK=12.288MHz, BCLK =3.072MHz, Fs=48KHz;
|
||
////
|
||
//static struct CJC8988_reg DAC_TO_LOUT1[] = {
|
||
// {CJC8988_R0_LEFT_INPUT_VOLUME, 0x17}, // Audio input left channel volume; R/W
|
||
// {CJC8988_R1_RIGHT_INPUT_VOLUME, 0x17}, // Audio input right channel volume; R/W
|
||
// {CJC8988_R2_LOUT1_VOLUME, 0x79}, // Audio output letf channel1 volume; R/W
|
||
// {CJC8988_R3_ROUT1_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R5_ADC_DAC_CONTROL, 0x00}, // ADC and DAC CONTROL; R/W
|
||
// {CJC8988_R7_AUDIO_INTERFACE, 0x0A}, // Digital Audio interface format; R/W
|
||
// {CJC8988_R8_SAMPLE_RATE, 0x00}, // Clock and Sample rate control; R/W
|
||
// {CJC8988_R10_LEFT_DAC_VOLUME, 0xff}, // Left channel DAC digital volume; R/W
|
||
// {CJC8988_R11_RIGHT_DAC_VOLUME, 0xff}, // Right channel DAC digital volume; R/W
|
||
//
|
||
// {CJC8988_R12_BASS_CONTROL, 0x0f}, // BASS control; R/W
|
||
// {CJC8988_R13_TREBLE_CONTROL, 0x0f}, // Treble control; R/W
|
||
// {CJC8988_R16_3D_CONTROL, 0x00}, // 3D control; R/W
|
||
//
|
||
// {CJC8988_R21_LEFT_ADC_VOLUME, 0xc3}, // Left ADC digital volume; R/W
|
||
// {CJC8988_R22_RIGHT_ADC_VOLUME, 0xc3}, // Right ADC digital volume; R/W
|
||
//
|
||
// {CJC8988_R23_ADDITIONAL_CONTROL1, 0xc0}, // Additional control 1; R/W
|
||
// {CJC8988_R24_ADDITIONAL_CONTROL2, 0x00}, // Additional control 2; R/W
|
||
// {CJC8988_R27_ADDITIONAL_CONTROL3, 0x00}, // Additional control 3; R/W
|
||
//
|
||
// {CJC8988_R31_ADC_INPUT_MODE, 0x00}, // ADC input mode; R/W
|
||
//
|
||
// {CJC8988_R32_ADCL_SIGNAL_PATH, 0x00}, // Left ADC signal path control; R/W
|
||
// {CJC8988_R33_ADCR_SIGNAL_PATH, 0x00}, // Right ADC signal path control; R/W
|
||
//
|
||
// {CJC8988_R34_LEFT_OUT_MIX1_H, 0x52}, // Left DAC to left mixer enable; R/W
|
||
// {CJC8988_R35_LEFT_OUT_MIX2_L, 0x50}, // Right DAC to left mixer disable; R/W
|
||
// {CJC8988_R36_RIGHT_OUT_MIX1_L, 0x52}, // Left DAC to right mixer disable; R/W
|
||
// {CJC8988_R37_RIGHT_OUT_MIX2_H, 0x50}, // Right DAC to right mixer enable; R/W
|
||
//
|
||
// {CJC8988_R40_LOUT2_VOLUME, 0x79}, // Audio output left channel1 volume; R/W
|
||
// {CJC8988_R41_ROUT2_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R43_LOW_POWER_PLAYBACK, 0x08}, // Low power playback; R/W
|
||
//
|
||
// {CJC8988_R25_PWR_MGMT1_H, 0x40}, // Power management1 and VMIDSEL; R/W
|
||
// {CJC8988_R26_PWR_MGMT2_H, 0xf8}, // Power management2 and DAC left power up; R/W;
|
||
//};
|
||
//
|
||
//#define CJC8988_DAC_TO_LOUT1_REG_NUM ARRAY_SIZE(DAC_TO_LOUT1)
|
||
//
|
||
////*************************************************************************
|
||
//// LINE Input 1 to LOUT 1 mode, slave mode, I2S format, MCLK=12.288MHz, BCLK =3.072MHz, Fs=48KHz;
|
||
////
|
||
//static struct CJC8988_reg LINPUT1_TO_LOUT1[] = {
|
||
// {CJC8988_R0_LEFT_INPUT_VOLUME, 0x17}, // Audio input left channel volume; R/W
|
||
// {CJC8988_R1_RIGHT_INPUT_VOLUME, 0x17}, // Audio input right channel volume; R/W
|
||
// {CJC8988_R2_LOUT1_VOLUME, 0x79}, // Audio output letf channel1 volume; R/W
|
||
// {CJC8988_R3_ROUT1_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R5_ADC_DAC_CONTROL, 0x00}, // ADC and DAC CONTROL; R/W
|
||
// {CJC8988_R7_AUDIO_INTERFACE, 0x0A}, // Digital Audio interface format; R/W
|
||
// {CJC8988_R8_SAMPLE_RATE, 0x00}, // Clock and Sample rate control; R/W
|
||
// {CJC8988_R10_LEFT_DAC_VOLUME, 0xff}, // Left channel DAC digital volume; R/W
|
||
// {CJC8988_R11_RIGHT_DAC_VOLUME, 0xff}, // Right channel DAC digital volume; R/W
|
||
//
|
||
// {CJC8988_R12_BASS_CONTROL, 0x0f}, // BASS control; R/W
|
||
// {CJC8988_R13_TREBLE_CONTROL, 0x0f}, // Treble control; R/W
|
||
// {CJC8988_R16_3D_CONTROL, 0x00}, // 3D control; R/W
|
||
//
|
||
// {CJC8988_R21_LEFT_ADC_VOLUME, 0xc3}, // Left ADC digital volume; R/W
|
||
// {CJC8988_R22_RIGHT_ADC_VOLUME, 0xc3}, // Right ADC digital volume; R/W
|
||
//
|
||
// {CJC8988_R23_ADDITIONAL_CONTROL1, 0xc0}, // Additional control 1; R/W
|
||
// {CJC8988_R24_ADDITIONAL_CONTROL2, 0x00}, // Additional control 2; R/W
|
||
// {CJC8988_R27_ADDITIONAL_CONTROL3, 0x00}, // Additional control 3; R/W
|
||
//
|
||
// {CJC8988_R31_ADC_INPUT_MODE, 0x00}, // ADC input mode; R/W
|
||
//
|
||
// {CJC8988_R32_ADCL_SIGNAL_PATH, 0x00}, // Left ADC signal path control; R/W
|
||
// {CJC8988_R33_ADCR_SIGNAL_PATH, 0x00}, // Right ADC signal path control; R/W
|
||
//
|
||
// {CJC8988_R34_LEFT_OUT_MIX1_L, 0xA0}, // Left DAC to left mixer disable; R/W
|
||
// {CJC8988_R35_LEFT_OUT_MIX2_L, 0x50}, // Right DAC to left mixer disable; R/W
|
||
// {CJC8988_R36_RIGHT_OUT_MIX1_L, 0x50}, // Left DAC to right mixer disable; R/W
|
||
// {CJC8988_R37_RIGHT_OUT_MIX2_L, 0xA0}, // Right DAC to right mixer disable; R/W
|
||
//
|
||
// {CJC8988_R40_LOUT2_VOLUME, 0x79}, // Audio output left channel1 volume; R/W
|
||
// {CJC8988_R41_ROUT2_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R43_LOW_POWER_PLAYBACK, 0x00}, // Low power playback; R/W
|
||
//
|
||
// {CJC8988_R25_PWR_MGMT1_H, 0x40}, // Power management1 and VMIDSEL; R/W
|
||
// {CJC8988_R26_PWR_MGMT2_H, 0x78}, // Power management2 and DAC left power up; R/W;
|
||
//};
|
||
//
|
||
//#define CJC8988_LINPUT1_TO_LOUT1_REG_NUM ARRAY_SIZE(LINPUT1_TO_LOUT1)
|
||
//
|
||
////*************************************************************************
|
||
//// LINE Input 2 to ADC and DAC to LOUT 2 mode, slave mode, I2S format, MCLK=12MHz, BCLK = 12MHz, Fs=8KHz;
|
||
////
|
||
//static struct CJC8988_reg LINPUT2_ADC_TO_DAC_LOUT2_8[] = {
|
||
// {CJC8988_R0_LEFT_INPUT_VOLUME, 0x17}, // Audio input left channel volume; R/W
|
||
// {CJC8988_R1_RIGHT_INPUT_VOLUME, 0x17}, // Audio input right channel volume; R/W
|
||
// {CJC8988_R2_LOUT1_VOLUME, 0x79}, // Audio output letf channel1 volume; R/W
|
||
// {CJC8988_R3_ROUT1_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R5_ADC_DAC_CONTROL, 0x00}, // ADC and DAC CONTROL; R/W
|
||
// {CJC8988_R7_AUDIO_INTERFACE, 0x02}, // Digital Audio interface format; R/W
|
||
// {CJC8988_R8_SAMPLE_RATE, 0x0d}, // Clock and Sample rate control; R/W
|
||
// {CJC8988_R10_LEFT_DAC_VOLUME, 0xff}, // Left channel DAC digital volume; R/W
|
||
// {CJC8988_R11_RIGHT_DAC_VOLUME, 0xff}, // Right channel DAC digital volume; R/W
|
||
//
|
||
// {CJC8988_R12_BASS_CONTROL, 0x0f}, // BASS control; R/W
|
||
// {CJC8988_R13_TREBLE_CONTROL, 0x0f}, // Treble control; R/W
|
||
// {CJC8988_R16_3D_CONTROL, 0x00}, // 3D control; R/W
|
||
//
|
||
// {CJC8988_R21_LEFT_ADC_VOLUME, 0xc3}, // Left ADC digital volume; R/W
|
||
// {CJC8988_R22_RIGHT_ADC_VOLUME, 0xc3}, // Right ADC digital volume; R/W
|
||
//
|
||
// {CJC8988_R23_ADDITIONAL_CONTROL1, 0xc0}, // Additional control 1; R/W
|
||
// {CJC8988_R24_ADDITIONAL_CONTROL2, 0x00}, // Additional control 2; R/W
|
||
// {CJC8988_R27_ADDITIONAL_CONTROL3, 0x00}, // Additional control 3; R/W
|
||
//
|
||
// {CJC8988_R31_ADC_INPUT_MODE, 0x00}, // ADC input mode; R/W
|
||
//
|
||
// {CJC8988_R32_ADCL_SIGNAL_PATH, 0x40}, // Left ADC signal path control; R/W
|
||
// {CJC8988_R33_ADCR_SIGNAL_PATH, 0x40}, // Right ADC signal path control; R/W
|
||
//
|
||
// {CJC8988_R34_LEFT_OUT_MIX1_H, 0x52}, // Left DAC to left mixer disable; R/W
|
||
// {CJC8988_R35_LEFT_OUT_MIX2_L, 0x50}, // Right DAC to left mixer disable; R/W
|
||
// {CJC8988_R36_RIGHT_OUT_MIX1_L, 0x52}, // Left DAC to right mixer disable; R/W
|
||
// {CJC8988_R37_RIGHT_OUT_MIX2_H, 0x50}, // Right DAC to right mixer disable; R/W
|
||
//
|
||
// {CJC8988_R40_LOUT2_VOLUME, 0x79}, // Audio output left channel1 volume; R/W
|
||
// {CJC8988_R41_ROUT2_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R43_LOW_POWER_PLAYBACK, 0x08}, // Low power playback; R/W
|
||
//
|
||
// {CJC8988_R25_PWR_MGMT1_H, 0x7C}, // Power management1 and VMIDSEL; R/W
|
||
// {CJC8988_R26_PWR_MGMT2_H, 0xf8}, // Power management2 and DAC left power up; R/W;
|
||
//};
|
||
//
|
||
//#define CJC8988_LINPUT2_ADC_TO_DAC_LOUT2_8_REG_NUM ARRAY_SIZE(LINPUT2_ADC_TO_DAC_LOUT2_8)
|
||
//
|
||
////*************************************************************************
|
||
//// LINE Input 2 to ADC and DAC to LOUT 2 mode, slave mode, I2S format, MCLK=12MHz, BCLK = 12MHz, Fs=32KHz;
|
||
////
|
||
//static struct CJC8988_reg LINPUT2_ADC_TO_DAC_LOUT2_32[] = {
|
||
// {CJC8988_R0_LEFT_INPUT_VOLUME, 0x17}, // Audio input left channel volume; R/W
|
||
// {CJC8988_R1_RIGHT_INPUT_VOLUME, 0x17}, // Audio input right channel volume; R/W
|
||
// {CJC8988_R2_LOUT1_VOLUME, 0x79}, // Audio output letf channel1 volume; R/W
|
||
// {CJC8988_R3_ROUT1_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R5_ADC_DAC_CONTROL, 0x00}, // ADC and DAC CONTROL; R/W
|
||
// {CJC8988_R7_AUDIO_INTERFACE, 0x02}, // Digital Audio interface format; R/W
|
||
// {CJC8988_R8_SAMPLE_RATE, 0x19}, // Clock and Sample rate control; R/W
|
||
// {CJC8988_R10_LEFT_DAC_VOLUME, 0xff}, // Left channel DAC digital volume; R/W
|
||
// {CJC8988_R11_RIGHT_DAC_VOLUME, 0xff}, // Right channel DAC digital volume; R/W
|
||
//
|
||
// {CJC8988_R12_BASS_CONTROL, 0x0f}, // BASS control; R/W
|
||
// {CJC8988_R13_TREBLE_CONTROL, 0x0f}, // Treble control; R/W
|
||
// {CJC8988_R16_3D_CONTROL, 0x00}, // 3D control; R/W
|
||
//
|
||
// {CJC8988_R21_LEFT_ADC_VOLUME, 0xc3}, // Left ADC digital volume; R/W
|
||
// {CJC8988_R22_RIGHT_ADC_VOLUME, 0xc3}, // Right ADC digital volume; R/W
|
||
//
|
||
// {CJC8988_R23_ADDITIONAL_CONTROL1, 0xc0}, // Additional control 1; R/W
|
||
// {CJC8988_R24_ADDITIONAL_CONTROL2, 0x00}, // Additional control 2; R/W
|
||
// {CJC8988_R27_ADDITIONAL_CONTROL3, 0x00}, // Additional control 3; R/W
|
||
//
|
||
// {CJC8988_R31_ADC_INPUT_MODE, 0x00}, // ADC input mode; R/W
|
||
//
|
||
// {CJC8988_R32_ADCL_SIGNAL_PATH, 0x40}, // Left ADC signal path control; R/W
|
||
// {CJC8988_R33_ADCR_SIGNAL_PATH, 0x40}, // Right ADC signal path control; R/W
|
||
//
|
||
// {CJC8988_R34_LEFT_OUT_MIX1_H, 0x52}, // Left DAC to left mixer disable; R/W
|
||
// {CJC8988_R35_LEFT_OUT_MIX2_L, 0x50}, // Right DAC to left mixer disable; R/W
|
||
// {CJC8988_R36_RIGHT_OUT_MIX1_L, 0x52}, // Left DAC to right mixer disable; R/W
|
||
// {CJC8988_R37_RIGHT_OUT_MIX2_H, 0x50}, // Right DAC to right mixer disable; R/W
|
||
//
|
||
// {CJC8988_R40_LOUT2_VOLUME, 0x79}, // Audio output left channel1 volume; R/W
|
||
// {CJC8988_R41_ROUT2_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R43_LOW_POWER_PLAYBACK, 0x08}, // Low power playback; R/W
|
||
//
|
||
// {CJC8988_R25_PWR_MGMT1_H, 0x7C}, // Power management1 and VMIDSEL; R/W
|
||
// {CJC8988_R26_PWR_MGMT2_H, 0xf8}, // Power management2 and DAC left power up; R/W;
|
||
//};
|
||
//
|
||
//#define CJC8988_LINPUT2_ADC_TO_DAC_LOUT2_32_REG_NUM ARRAY_SIZE(LINPUT2_ADC_TO_DAC_LOUT2_32)
|
||
//
|
||
////*************************************************************************
|
||
//// LINE Input 2 to ADC and DAC to LOUT 2 mode, slave mode, I2S format, MCLK=12MHz, BCLK = 12MHz, Fs=44.1KHz;
|
||
////
|
||
//static struct CJC8988_reg LINPUT2_ADC_TO_DAC_LOUT2_44[] = {
|
||
// {CJC8988_R0_LEFT_INPUT_VOLUME, 0x17}, // Audio input left channel volume; R/W
|
||
// {CJC8988_R1_RIGHT_INPUT_VOLUME, 0x17}, // Audio input right channel volume; R/W
|
||
// {CJC8988_R2_LOUT1_VOLUME, 0x79}, // Audio output letf channel1 volume; R/W
|
||
// {CJC8988_R3_ROUT1_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R5_ADC_DAC_CONTROL, 0x00}, // ADC and DAC CONTROL; R/W
|
||
// {CJC8988_R7_AUDIO_INTERFACE, 0x02}, // Digital Audio interface format; R/W
|
||
// {CJC8988_R8_SAMPLE_RATE, 0x23}, // Clock and Sample rate control; R/W
|
||
// {CJC8988_R10_LEFT_DAC_VOLUME, 0xff}, // Left channel DAC digital volume; R/W
|
||
// {CJC8988_R11_RIGHT_DAC_VOLUME, 0xff}, // Right channel DAC digital volume; R/W
|
||
//
|
||
// {CJC8988_R12_BASS_CONTROL, 0x0f}, // BASS control; R/W
|
||
// {CJC8988_R13_TREBLE_CONTROL, 0x0f}, // Treble control; R/W
|
||
// {CJC8988_R16_3D_CONTROL, 0x00}, // 3D control; R/W
|
||
//
|
||
// {CJC8988_R21_LEFT_ADC_VOLUME, 0xc3}, // Left ADC digital volume; R/W
|
||
// {CJC8988_R22_RIGHT_ADC_VOLUME, 0xc3}, // Right ADC digital volume; R/W
|
||
//
|
||
// {CJC8988_R23_ADDITIONAL_CONTROL1, 0xc0}, // Additional control 1; R/W
|
||
// {CJC8988_R24_ADDITIONAL_CONTROL2, 0x00}, // Additional control 2; R/W
|
||
// {CJC8988_R27_ADDITIONAL_CONTROL3, 0x00}, // Additional control 3; R/W
|
||
//
|
||
// {CJC8988_R31_ADC_INPUT_MODE, 0x00}, // ADC input mode; R/W
|
||
//
|
||
// {CJC8988_R32_ADCL_SIGNAL_PATH, 0x40}, // Left ADC signal path control; R/W
|
||
// {CJC8988_R33_ADCR_SIGNAL_PATH, 0x40}, // Right ADC signal path control; R/W
|
||
//
|
||
// {CJC8988_R34_LEFT_OUT_MIX1_H, 0x52}, // Left DAC to left mixer disable; R/W
|
||
// {CJC8988_R35_LEFT_OUT_MIX2_L, 0x50}, // Right DAC to left mixer disable; R/W
|
||
// {CJC8988_R36_RIGHT_OUT_MIX1_L, 0x52}, // Left DAC to right mixer disable; R/W
|
||
// {CJC8988_R37_RIGHT_OUT_MIX2_H, 0x50}, // Right DAC to right mixer disable; R/W
|
||
//
|
||
// {CJC8988_R40_LOUT2_VOLUME, 0x79}, // Audio output left channel1 volume; R/W
|
||
// {CJC8988_R41_ROUT2_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
// {CJC8988_R43_LOW_POWER_PLAYBACK, 0x08}, // Low power playback; R/W
|
||
//
|
||
// {CJC8988_R25_PWR_MGMT1_H, 0x7C}, // Power management1 and VMIDSEL; R/W
|
||
// {CJC8988_R26_PWR_MGMT2_H, 0xf8}, // Power management2 and DAC left power up; R/W;
|
||
//};
|
||
#define CJC8988_RATES ( \
|
||
SNDRV_PCM_RATE_96000 | \
|
||
SNDRV_PCM_RATE_48000 | \
|
||
SNDRV_PCM_RATE_32000 | \
|
||
SNDRV_PCM_RATE_16000 | \
|
||
SNDRV_PCM_RATE_8000)
|
||
|
||
// CJC8988 LS2K1000-创龙板
|
||
// 深位定死16位,只能播放16位
|
||
// 如果给32位,I2S bclk 与 lrc 无法对齐,从信号上看类似于 left-justify 模式
|
||
#define CJC8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
|
||
|
||
static unsigned char CJC8988_SR_TABLE[][7] = {
|
||
// 8K, 12K, 16K, 24K, 32K, 48K, 96K
|
||
{0x6, 0x8, 0xa, 0x1c, 0xc, 0x0, 0xe}, // 12288000
|
||
{0x7, 0x9, 0xb, 0x1d, 0xd, 0x1, 0xf}, // 18432000
|
||
};
|
||
|
||
/* codec private data */
|
||
struct cjc8988_priv {
|
||
struct regmap *regmap;
|
||
unsigned int mode;
|
||
unsigned int freq;
|
||
};
|
||
|
||
static const char * const input_channel_text[] = { "INPUT1", "INPUT2" };
|
||
|
||
static const struct soc_enum left_input_channel_enum[] = {
|
||
SOC_ENUM_SINGLE(CJC8988_R32_ADCL_SIGNAL_PATH, 6, ARRAY_SIZE(input_channel_text), input_channel_text)
|
||
};
|
||
|
||
static const struct soc_enum right_input_channel_enum[] = {
|
||
SOC_ENUM_SINGLE(CJC8988_R33_ADCR_SIGNAL_PATH, 6, ARRAY_SIZE(input_channel_text), input_channel_text)
|
||
};
|
||
|
||
static const struct snd_kcontrol_new cjc8988_snd_controls[] = {
|
||
SOC_DOUBLE_R_RANGE("Volume", CJC8988_R2_LOUT1_VOLUME, CJC8988_R3_ROUT1_VOLUME,
|
||
0x00, 0x2f, 0x79,0),
|
||
SOC_ENUM("L-Input", left_input_channel_enum),
|
||
SOC_ENUM("R-Input", right_input_channel_enum),
|
||
};
|
||
|
||
static struct reg_default cjc8988_reg_defaults[] = {
|
||
{CJC8988_R0_LEFT_INPUT_VOLUME, 0x17}, // Audio input left channel volume; R/W
|
||
{CJC8988_R1_RIGHT_INPUT_VOLUME, 0x17}, // Audio input right channel volume; R/W
|
||
{CJC8988_R2_LOUT1_VOLUME, 0x79}, // Audio output letf channel1 volume; R/W
|
||
{CJC8988_R3_ROUT1_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
{CJC8988_R5_ADC_DAC_CONTROL, 0x00}, // ADC and DAC CONTROL; R/W
|
||
{CJC8988_R7_AUDIO_INTERFACE, 0x4E}, // Digital Audio interface format; R/W
|
||
{CJC8988_R8_SAMPLE_RATE, 0x00}, // Clock and Sample rate control; R/W
|
||
{CJC8988_R10_LEFT_DAC_VOLUME, 0xff}, // Left channel DAC digital volume; R/W
|
||
{CJC8988_R11_RIGHT_DAC_VOLUME, 0xff}, // Right channel DAC digital volume; R/W
|
||
{CJC8988_R12_BASS_CONTROL, 0x0f}, // BASS control; R/W
|
||
{CJC8988_R13_TREBLE_CONTROL, 0x0f}, // Treble control; R/W
|
||
{CJC8988_R16_3D_CONTROL, 0x00}, // 3D control; R/W
|
||
{CJC8988_R21_LEFT_ADC_VOLUME, 0xc3}, // Left ADC digital volume; R/W
|
||
{CJC8988_R22_RIGHT_ADC_VOLUME, 0xc3}, // Right ADC digital volume; R/W
|
||
{CJC8988_R23_ADDITIONAL_CONTROL1, 0xc0}, // Additional control 1; R/W
|
||
{CJC8988_R24_ADDITIONAL_CONTROL2, 0x04}, // Additional control 2; R/W
|
||
{CJC8988_R27_ADDITIONAL_CONTROL3, 0x00}, // Additional control 3; R/W
|
||
{CJC8988_R31_ADC_INPUT_MODE, 0x00}, // ADC input mode; R/W
|
||
// 0x40 : 默认 INPUT2,0x70 加上 MIC 增益,按需求定
|
||
// {CJC8988_R32_ADCL_SIGNAL_PATH, 0x70}, // Left ADC signal path control; R/W
|
||
// {CJC8988_R33_ADCR_SIGNAL_PATH, 0x70}, // Right ADC signal path control; R/W
|
||
{CJC8988_R32_ADCL_SIGNAL_PATH, 0x00}, // Left ADC signal path control; R/W
|
||
{CJC8988_R33_ADCR_SIGNAL_PATH, 0x00}, // Right ADC signal path control; R/W
|
||
{CJC8988_R34_LEFT_OUT_MIX1_H, 0x52}, // Left DAC to left mixer enable; R/W
|
||
{CJC8988_R35_LEFT_OUT_MIX2_L, 0x50}, // Right DAC to left mixer disable; R/W
|
||
{CJC8988_R36_RIGHT_OUT_MIX1_L, 0x52}, // Left DAC to right mixer disable; R/W
|
||
{CJC8988_R37_RIGHT_OUT_MIX2_H, 0x50}, // Right DAC to right mixer enable; R/W
|
||
{CJC8988_R40_LOUT2_VOLUME, 0x79}, // Audio output left channel1 volume; R/W
|
||
{CJC8988_R41_ROUT2_VOLUME, 0x79}, // Audio output right channel1 volume; R/W
|
||
{CJC8988_R43_LOW_POWER_PLAYBACK, 0x08}, // Low power playback; R/W
|
||
{CJC8988_R25_PWR_MGMT1_H, 0x7c}, // Power management1 and VMIDSEL; R/W
|
||
{CJC8988_R26_PWR_MGMT2_H, 0xf8}, // Power management2 and DAC left power up; R/W;
|
||
};
|
||
|
||
static void cjc8988_default_regs_change(unsigned int reg, unsigned int val)
|
||
{
|
||
int i;
|
||
for (i = 0; i < ARRAY_SIZE(cjc8988_reg_defaults); i++) {
|
||
if (reg == cjc8988_reg_defaults[i].reg)
|
||
{
|
||
cjc8988_reg_defaults[i].def = val;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
static bool cjc8988_valid_regs(struct device *dev, unsigned int reg)
|
||
{
|
||
switch (reg) {
|
||
case CJC8988_R0_LEFT_INPUT_VOLUME:
|
||
case CJC8988_R1_RIGHT_INPUT_VOLUME:
|
||
case CJC8988_R2_LOUT1_VOLUME:
|
||
case CJC8988_R3_ROUT1_VOLUME:
|
||
case CJC8988_R5_ADC_DAC_CONTROL:
|
||
case CJC8988_R7_AUDIO_INTERFACE:
|
||
case CJC8988_R8_SAMPLE_RATE:
|
||
case CJC8988_R10_LEFT_DAC_VOLUME:
|
||
case CJC8988_R11_RIGHT_DAC_VOLUME:
|
||
case CJC8988_R12_BASS_CONTROL:
|
||
case CJC8988_R13_TREBLE_CONTROL:
|
||
case CJC8988_R16_3D_CONTROL:
|
||
case CJC8988_R21_LEFT_ADC_VOLUME:
|
||
case CJC8988_R22_RIGHT_ADC_VOLUME:
|
||
case CJC8988_R23_ADDITIONAL_CONTROL1:
|
||
case CJC8988_R24_ADDITIONAL_CONTROL2:
|
||
case CJC8988_R27_ADDITIONAL_CONTROL3:
|
||
case CJC8988_R31_ADC_INPUT_MODE:
|
||
case CJC8988_R32_ADCL_SIGNAL_PATH:
|
||
case CJC8988_R33_ADCR_SIGNAL_PATH:
|
||
case CJC8988_R34_LEFT_OUT_MIX1_H:
|
||
case CJC8988_R35_LEFT_OUT_MIX2_L:
|
||
case CJC8988_R36_RIGHT_OUT_MIX1_L:
|
||
case CJC8988_R37_RIGHT_OUT_MIX2_H:
|
||
case CJC8988_R40_LOUT2_VOLUME:
|
||
case CJC8988_R41_ROUT2_VOLUME:
|
||
case CJC8988_R43_LOW_POWER_PLAYBACK:
|
||
case CJC8988_R25_PWR_MGMT1_H:
|
||
case CJC8988_R26_PWR_MGMT2_H:
|
||
return true;
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Note that this should be called from init rather than from hw_params.
|
||
*/
|
||
static int cjc8988_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
||
int clk_id, unsigned int freq, int dir)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
static int cjc8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||
unsigned int fmt)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
static int cjc8988_pcm_startup(struct snd_pcm_substream *substream,
|
||
struct snd_soc_dai *dai)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
static u8 cjc8988_get_depth(unsigned int bits)
|
||
{
|
||
switch (bits)
|
||
{
|
||
case 16:
|
||
return 0x01;
|
||
case 20:
|
||
return 0x05;
|
||
case 24:
|
||
return 0x09;
|
||
case 32:
|
||
return 0x0D;
|
||
default:
|
||
return 0x01;
|
||
}
|
||
}
|
||
|
||
static int cjc8988_sr_table_map_sample_index(unsigned int sample)
|
||
{
|
||
switch (sample)
|
||
{
|
||
case 8000:
|
||
return 0;
|
||
case 12000:
|
||
return 1;
|
||
case 16000:
|
||
return 2;
|
||
case 24000:
|
||
return 3;
|
||
case 32000:
|
||
return 4;
|
||
case 48000:
|
||
return 5;
|
||
case 96000:
|
||
return 6;
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
static u8 cjc8988_get_sample_rate(unsigned int freq, unsigned int sample)
|
||
{
|
||
int index = cjc8988_sr_table_map_sample_index(sample);
|
||
switch (freq)
|
||
{
|
||
case 12288000:
|
||
return CJC8988_SR_TABLE[0][index] << 1;
|
||
case 18432000:
|
||
return CJC8988_SR_TABLE[1][index] << 1;
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
static int cjc8988_pcm_hw_params(struct snd_pcm_substream *substream,
|
||
struct snd_pcm_hw_params *params,
|
||
struct snd_soc_dai *dai)
|
||
{
|
||
u8 val;
|
||
struct cjc8988_priv *cjc8988;
|
||
cjc8988 = snd_soc_component_get_drvdata(dai->component);
|
||
|
||
// NOTE-TMP-REV
|
||
// 深位定死32位,目前能播放16位
|
||
// 如果codec只给16位,正弦信号半个周期会有尖峰,怀疑与时钟有关
|
||
// val = cjc8988_get_depth(params->msbits);
|
||
// snd_soc_component_write(dai->component, CJC8988_R7_AUDIO_INTERFACE,
|
||
// (val | cjc8988->mode << 6 | 2));
|
||
|
||
val = cjc8988_get_sample_rate(cjc8988->freq, params->rate_num);
|
||
snd_soc_component_write(dai->component, CJC8988_R8_SAMPLE_RATE,
|
||
val);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int cjc8988_set_bias_level(struct snd_soc_component *component,
|
||
enum snd_soc_bias_level level)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
static int cjc8988_component_probe(struct snd_soc_component *component)
|
||
{
|
||
int i = 0;
|
||
for (i = 0; i < ARRAY_SIZE(cjc8988_reg_defaults); i++) {
|
||
snd_soc_component_write(component, cjc8988_reg_defaults[i].reg,
|
||
cjc8988_reg_defaults[i].def);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static const struct snd_soc_dai_ops cjc8988_dai_ops = {
|
||
.startup = cjc8988_pcm_startup,
|
||
.hw_params = cjc8988_pcm_hw_params,
|
||
.set_fmt = cjc8988_set_dai_fmt,
|
||
.set_sysclk = cjc8988_set_dai_sysclk,
|
||
};
|
||
|
||
static struct snd_soc_dai_driver cjc8988_dai = {
|
||
.name = "cjc8988-hifi",
|
||
.playback = {
|
||
.stream_name = "Playback",
|
||
.channels_min = 1,
|
||
.channels_max = 2,
|
||
.rates = CJC8988_RATES,
|
||
.formats = CJC8988_FORMATS,
|
||
},
|
||
.capture = {
|
||
.stream_name = "Capture",
|
||
.channels_min = 1,
|
||
.channels_max = 2,
|
||
.rates = CJC8988_RATES,
|
||
.formats = CJC8988_FORMATS,
|
||
},
|
||
.ops = &cjc8988_dai_ops,
|
||
.symmetric_rates = 1,
|
||
};
|
||
|
||
static const struct snd_soc_component_driver cjc8988_component_driver = {
|
||
.probe = cjc8988_component_probe,
|
||
.set_bias_level = cjc8988_set_bias_level,
|
||
.controls = cjc8988_snd_controls,
|
||
.num_controls = ARRAY_SIZE(cjc8988_snd_controls),
|
||
// .dapm_widgets = cjc8988_dapm_widgets,
|
||
// .num_dapm_widgets = ARRAY_SIZE(cjc8988_dapm_widgets),
|
||
// .dapm_routes = cjc8988_dapm_routes,
|
||
// .num_dapm_routes = ARRAY_SIZE(cjc8988_dapm_routes),
|
||
.suspend_bias_off = 1,
|
||
.idle_bias_on = 1,
|
||
.use_pmdown_time = 1,
|
||
.endianness = 1,
|
||
.non_legacy_dai_naming = 1,
|
||
};
|
||
|
||
static const struct regmap_config cjc8988_regmap = {
|
||
.reg_bits = 8,
|
||
.val_bits = 8,
|
||
|
||
.max_register = CJC8988_REG_NUM,
|
||
.writeable_reg = cjc8988_valid_regs,
|
||
.readable_reg = cjc8988_valid_regs,
|
||
|
||
.cache_type = REGCACHE_RBTREE,
|
||
.reg_defaults = cjc8988_reg_defaults,
|
||
.num_reg_defaults = ARRAY_SIZE(cjc8988_reg_defaults),
|
||
};
|
||
|
||
static const struct i2c_device_id cjc8988_id[] = {
|
||
{ "cjc8988", 0 },
|
||
{ }
|
||
};
|
||
MODULE_DEVICE_TABLE(i2c, cjc8988_id);
|
||
|
||
static int cjc8988_i2c_probe(struct i2c_client *i2c,
|
||
const struct i2c_device_id *id)
|
||
{
|
||
int ret;
|
||
struct device *dev = &i2c->dev;
|
||
struct cjc8988_priv * cjc8988 = devm_kzalloc(dev, sizeof(*cjc8988), GFP_KERNEL);
|
||
if (cjc8988 == NULL)
|
||
return -ENOMEM;
|
||
|
||
cjc8988->regmap = devm_regmap_init_i2c(i2c, &cjc8988_regmap);
|
||
if (IS_ERR(cjc8988->regmap)) {
|
||
ret = PTR_ERR(cjc8988->regmap);
|
||
dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
|
||
return ret;
|
||
}
|
||
|
||
if (device_property_present(dev, "master-mode")){
|
||
cjc8988->mode = 1;
|
||
}
|
||
else {
|
||
cjc8988->mode = 0;
|
||
}
|
||
|
||
device_property_read_u32(&i2c->dev, "clock-frequency", &cjc8988->freq);
|
||
i2c_set_clientdata(i2c, cjc8988);
|
||
|
||
if (device_property_present(dev, "cjc8988,adc-input2")){
|
||
cjc8988_default_regs_change(CJC8988_R32_ADCL_SIGNAL_PATH, 0x40);
|
||
cjc8988_default_regs_change(CJC8988_R33_ADCR_SIGNAL_PATH, 0x40);
|
||
}
|
||
|
||
return devm_snd_soc_register_component(dev,
|
||
&cjc8988_component_driver, &cjc8988_dai, 1);
|
||
}
|
||
|
||
static struct i2c_driver cjc8988_i2c_driver = {
|
||
.driver = {
|
||
.name = "cjc8988",
|
||
},
|
||
.probe = cjc8988_i2c_probe,
|
||
.id_table = cjc8988_id,
|
||
};
|
||
|
||
module_i2c_driver(cjc8988_i2c_driver);
|
||
|
||
MODULE_DESCRIPTION("ASoC CJC8988 driver");
|
||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||
MODULE_LICENSE("GPL");
|