From: zhangjun Date: Mon, 14 Oct 2013 08:50:31 +0000 (+0800) Subject: AndroidComputer Codec:add TINY ALSA support X-Git-Tag: firefly_0821_release~6566 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d7d4f99de781842ffacf4c9f7d3bbbe17f01fa00;p=firefly-linux-kernel-4.4.55.git AndroidComputer Codec:add TINY ALSA support --- diff --git a/sound/soc/codecs/cx2070x-i2c.h b/sound/soc/codecs/cx2070x-i2c.h old mode 100644 new mode 100755 index 096fc8f85752..410440b78edc --- a/sound/soc/codecs/cx2070x-i2c.h +++ b/sound/soc/codecs/cx2070x-i2c.h @@ -48,13 +48,13 @@ __REG(PATCH_VERSION, 0x1003, 0x1003, 0x00, 0, RO,W) __REG(CHIP_VERSION, 0x1005, 0x1005, 0x00, 0, RO,B) __REG(RELEASE_TYPE, 0x1006, 0x1006, 0x00, 0, RO,B) - + __REG(USB_LOCAL_VOLUME, 0x004E, 0x004E, 0x42, 0, RW,B) __REG(ROM_PATCH_VER_HB, 0x1584, 0xFFFF, 0x00, 0, RO,B) __REG(ROM_PATCH_VER_MB, 0x1585, 0xFFFF, 0x00, 0, RO,B) __REG(ROM_PATCH_VER_LB, 0x1586, 0xFFFF, 0x00, 0, RO,B) - __REG(DAC1_GAIN_LEFT, 0x100D, 0x100D, 0xc9, 0x4A, RW,B) - __REG(DAC2_GAIN_RIGHT, 0x100E, 0x100E, 0xc9, 0x4A, RW,B) + __REG(DAC1_GAIN_LEFT, 0x100D, 0x100D, 0x00, 0x00, RW,B) + __REG(DAC2_GAIN_RIGHT, 0x100E, 0x100E, 0x00, 0x00, RW,B) __REG(DSP_MAX_VOLUME, 0x100F, 0x100F, 0x00, 0, RW,B) __REG(CLASS_D_GAIN, 0x1011, 0x1010, b_00000000, 0, RW,B) @@ -81,8 +81,8 @@ __REG(ADC1_GAIN_LEFT, 0x1013, 0x1012, 0x00, 0x4A, RW,B) __REG(ADC1_GAIN_RIGHT, 0x1014, 0x1013, 0x00, 0x4A, RW,B) - __REG(ADC2_GAIN_LEFT, 0x1015, 0x1014, 0x00, 0x4A, RW,B) - __REG(ADC2_GAIN_RIGHT, 0x1016, 0x1015, 0x00, 0x4A, RW,B) + __REG(ADC2_GAIN_LEFT, 0x1015, 0x1014, 0x00, 0x00, RW,B) + __REG(ADC2_GAIN_RIGHT, 0x1016, 0x1015, 0x00, 0x00, RW,B) __REG(DSP_MAX_MIC_GAIN, 0x1017, 0x1016, 0x00, 0, RW,B) __REG(VOLUME_MUTE, 0x1018, 0x1017, 0, 0, WI,B) diff --git a/sound/soc/codecs/cx2070x.c b/sound/soc/codecs/cx2070x.c old mode 100644 new mode 100755 index 050db4438fb2..4b5cec0bfcc1 --- a/sound/soc/codecs/cx2070x.c +++ b/sound/soc/codecs/cx2070x.c @@ -216,6 +216,8 @@ struct cx2070x_priv enum Cx_INPUT_SEL input_sel; enum Cx_OUTPUT_SEL output_sel; unsigned int mute; + long int playback_path; + long int capture_path; }; #define get_cx2070x_priv(_codec_) ((struct cx2070x_priv *)snd_soc_codec_get_drvdata(codec)) @@ -434,6 +436,7 @@ static int NOINLINE cx2070x_real_write(struct snd_soc_codec *codec, unsigned int msg[0].addr = client->addr; msg[0].flags = client->flags & I2C_M_TEN; msg[0].buf = &data[0]; + msg[0].scl_rate = 200 * 1000; data[0]=(u8)(ri->addr>>8); data[1]=(u8)(ri->addr>>0); switch(ri->type®_WIDTH_MASK) @@ -489,11 +492,13 @@ static int NOINLINE cx2070x_real_read(struct snd_soc_codec *codec, unsigned int msg[0].flags = client->flags & I2C_M_TEN; msg[0].len = 2; msg[0].buf = &data[0]; + msg[0].scl_rate = 200 * 1000; msg[1].addr = client->addr; msg[1].flags = (client->flags & I2C_M_TEN) | I2C_M_RD; msg[1].len = ((ri->type®_WIDTH_MASK)==REG_WIDTH_W)?2:1; msg[1].buf = &data[2]; + msg[1].scl_rate = 200 * 1000; if (i2c_transfer(adap,msg,2)!=2) return -EIO; @@ -711,6 +716,180 @@ static const struct snd_kcontrol_new cx2070x_snd_controls[]= SOC_ENUM_EXT("Master Playback Switch", output_select_enum[0], output_select_event_get, output_select_event_set), }; +//For tiny alsa playback/capture/voice call path +static const char *cx2070x_playback_path_mode[] = {"OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT", "SPK_HP", //0-6 + "RING_SPK", "RING_HP", "RING_HP_NO_MIC", "RING_SPK_HP"};//7-10 + +static const char *cx2070x_capture_path_mode[] = {"MIC OFF", "Main Mic", "Hands Free Mic", "BT Sco Mic"}; + +static const SOC_ENUM_SINGLE_DECL(cx2070x_playback_path_type, 0, 0, cx2070x_playback_path_mode); + +static const SOC_ENUM_SINGLE_DECL(cx2070x_capture_path_type, 0, 0, cx2070x_capture_path_mode); + + +static int cx2070x_playback_path_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cx2070x_priv *cx2070x = get_cx2070x_priv(codec); + + if (!cx2070x) { + printk("%s : cx2070x_priv is NULL\n", __func__); + return -EINVAL; + } + + printk("%s : playback_path %ld\n",__func__,ucontrol->value.integer.value[0]); + + ucontrol->value.integer.value[0] = cx2070x->playback_path; + + return 0; +} + +static int cx2070x_playback_path_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cx2070x_priv *cx2070x = get_cx2070x_priv(codec); + long int pre_path; + + if (!cx2070x) { + printk("%s : cx2070x_priv is NULL\n", __func__); + return -EINVAL; + } + + if (cx2070x->playback_path == ucontrol->value.integer.value[0]){ + printk("%s : playback_path is not changed!\n",__func__); + return 0; + } + + pre_path = cx2070x->playback_path; + cx2070x->playback_path = ucontrol->value.integer.value[0]; + + printk("%s : set playback_path %ld, pre_path %ld\n", __func__, + cx2070x->playback_path, pre_path); + + switch (cx2070x->playback_path) { + case OFF: + if (pre_path != OFF) { + cx2070x_real_read(codec,DSP_INIT); + cx2070x_write(codec,DSP_INIT,(cx2070x_read_reg_cache(codec,DSP_INIT)| DSP_INIT_NEWC) & ~(1 << 3)); + } + break; + case RCV: + break; + case SPK_PATH: + case RING_SPK: + printk("%s : >>>>>>>>>>>>>>>PUT SPK_PATH\n",__func__); + if (pre_path == OFF) { + cx2070x_real_read(codec,DSP_INIT); + cx2070x_write(codec,DSP_INIT,cx2070x_read_reg_cache(codec,DSP_INIT)| DSP_INIT_NEWC | DSP_INIT_STREAM_3); + } + break; + case HP_PATH: + case HP_NO_MIC: + case RING_HP: + case RING_HP_NO_MIC: + if (pre_path == OFF) { + cx2070x_real_read(codec,DSP_INIT); + cx2070x_write(codec,DSP_INIT,cx2070x_read_reg_cache(codec,DSP_INIT)| DSP_INIT_NEWC | DSP_INIT_STREAM_3); + } + break; + case BT: + break; + case SPK_HP: + case RING_SPK_HP: + if (pre_path == OFF) { + cx2070x_real_read(codec,DSP_INIT); + cx2070x_write(codec,DSP_INIT,cx2070x_read_reg_cache(codec,DSP_INIT)| DSP_INIT_NEWC | DSP_INIT_STREAM_3); + } + break; + default: + return -EINVAL; + } + + return 0; +} + +static int cx2070x_capture_path_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cx2070x_priv *cx2070x = get_cx2070x_priv(codec); + + if (!cx2070x) { + printk("%s : cx2070x_priv is NULL\n", __func__); + return -EINVAL; + } + + printk("%s : capture_path %ld\n", __func__, + ucontrol->value.integer.value[0]); + + ucontrol->value.integer.value[0] = cx2070x->capture_path; + + return 0; +} + +static int cx2070x_capture_path_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cx2070x_priv *cx2070x = get_cx2070x_priv(codec); + long int pre_path; + + if (!cx2070x) { + printk("%s : cx2070x_priv is NULL\n", __func__); + return -EINVAL; + } + + if (cx2070x->capture_path == ucontrol->value.integer.value[0]){ + printk("%s : capture_path is not changed!\n", __func__); + return 0; + } + + pre_path = cx2070x->capture_path; + cx2070x->capture_path = ucontrol->value.integer.value[0]; + + printk("%s : set capture_path %ld, pre_path %ld\n", __func__, + cx2070x->capture_path, pre_path); + + switch (cx2070x->capture_path) { + case MIC_OFF: + if (pre_path != MIC_OFF) { + cx2070x_real_read(codec,DSP_INIT); + cx2070x_write(codec,DSP_INIT,(cx2070x_read_reg_cache(codec,DSP_INIT)| DSP_INIT_NEWC) & ~(DSP_INIT_STREAM_5)); + } + break; + case Main_Mic: + printk("%s : >>>>>>>>>>>>>>>PUT MAIN_MIC_PATH\n",__func__); + if (pre_path == MIC_OFF) { + cx2070x_real_read(codec,DSP_INIT); + cx2070x_write(codec,DSP_INIT,cx2070x_read_reg_cache(codec,DSP_INIT)| DSP_INIT_NEWC | DSP_INIT_STREAM_5); + } + break; + case Hands_Free_Mic: + if (pre_path == MIC_OFF) { + cx2070x_real_read(codec,DSP_INIT); + cx2070x_write(codec,DSP_INIT,cx2070x_read_reg_cache(codec,DSP_INIT)| DSP_INIT_NEWC | DSP_INIT_STREAM_5); + } + break; + case BT_Sco_Mic: + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_kcontrol_new cx2070x_snd_path_controls[] = { + SOC_ENUM_EXT("Playback Path", cx2070x_playback_path_type, + cx2070x_playback_path_get, cx2070x_playback_path_put), + + SOC_ENUM_EXT("Capture MIC Path", cx2070x_capture_path_type, + cx2070x_capture_path_get, cx2070x_capture_path_put), +}; + + // add non dapm controls static int cx2070x_add_controls(struct snd_soc_codec *codec) { @@ -1116,12 +1295,13 @@ static int cx2070x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm /*params for port2 by showy.zhang*/ cx2070x_real_write(codec,STREAM5_RATE,s5); cx2070x_real_write(codec,STREAM3_RATE,s3);// cause by incorrect parameter - +#if 0 + cx2070x_real_read(codec,DSP_INIT); dsp=cx2070x_read_reg_cache(codec,DSP_INIT); - + printk(">>>>>>>>>>>> dsp = %0x", dsp); if ((err=cx2070x_dsp_init(codec,dsp|DSP_INIT_NEWC))<0) return err; - +#endif return 0; } @@ -1130,20 +1310,25 @@ static int cx2070x_mute(struct snd_soc_dai *dai, int mute) struct snd_soc_codec *codec = dai->codec; ERROR("%lu: %s(%d) called\n",jiffies,__func__,mute); - +#if 0 cx2070x_real_write(codec,VOLUME_MUTE,mute?VOLUME_MUTE_ALL:b_00000000); -/* if( mute) { - cx2070x_real_write(codec,DSP_POWER,0xe0); // deep sleep mode - cx2070x_dsp_init(codec,DSP_INIT_STREAM_OFF); +// cx2070x_real_write(codec,DSP_POWER,0xe0); // deep sleep mode +// cx2070x_dsp_init(codec,DSP_INIT_STREAM_OFF); + /*mute I2S output*/ + cx2070x_real_read(codec,DSP_INIT); + cx2070x_write(codec,DSP_INIT,(cx2070x_read_reg_cache(codec,DSP_INIT)| DSP_INIT_NEWC) & ~(1 << 3)); } else { - cx2070x_dsp_init(codec,DSP_INIT_NEWC | 0xff); + /*unmute I2S output*/ + cx2070x_real_read(codec,DSP_INIT); + cx2070x_write(codec,DSP_INIT,cx2070x_read_reg_cache(codec,DSP_INIT)| DSP_INIT_NEWC | DSP_INIT_STREAM_3); + //cx2070x_dsp_init(codec,DSP_INIT_NEWC | 0xff); } -*/ +#endif return 0; } @@ -1591,8 +1776,10 @@ static int NOINLINE cx2070x_init(struct snd_soc_codec* codec) cx2070x_apply_firmware_patch(codec); #endif - cx2070x_add_controls(codec); - cx2070x_add_widgets(codec); + //cx2070x_add_controls(codec); + //cx2070x_add_widgets(codec); + snd_soc_add_controls(codec, cx2070x_snd_path_controls, + ARRAY_SIZE(cx2070x_snd_path_controls)); //snd_soc_dapm_nc_pin(&codec->dapm, "LINE IN"); //snd_soc_dapm_nc_pin( &codec->dapm, "LINE OUT"); @@ -1635,6 +1822,9 @@ static int NOINLINE cx2070x_init(struct snd_soc_codec* codec) #if defined(CONFIG_SND_CXLIFEGUARD) cxdbg_dev_init(codec); #endif + + cx2070x_real_write(codec, USB_LOCAL_VOLUME, 0x42); + if( ret == 0) { printk(KERN_INFO "CX2070X: codec is ready.\n"); diff --git a/sound/soc/codecs/cx2070x.h b/sound/soc/codecs/cx2070x.h old mode 100644 new mode 100755 index 5b04e8f80dde..2c7c7133e461 --- a/sound/soc/codecs/cx2070x.h +++ b/sound/soc/codecs/cx2070x.h @@ -61,6 +61,27 @@ enum Cx_OUTPUT_SEL{ Cx_OUTPUT_SEL_DPORT2, }; +enum { + OFF, + RCV, + SPK_PATH, + HP_PATH, + HP_NO_MIC, + BT, + SPK_HP, + RING_SPK, + RING_HP, + RING_HP_NO_MIC, + RING_SPK_HP, +}; + +enum { + MIC_OFF, + Main_Mic, + Hands_Free_Mic, + BT_Sco_Mic, +}; + #define CX2070X_I2C_DRIVER_NAME "cx2070x-i2c" #define CX2070X_SPI_DRIVER_NAME "cx2070x-spi" #define CX2070X_FIRMWARE_FILENAME "cnxt/cx2070x.fw"