diff --git a/Documentation/devicetree/bindings/sound/tas5805.txt b/Documentation/devicetree/bindings/sound/tas5805.txt new file mode 100644 index 000000000000..05ff201dfcef --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tas5805.txt @@ -0,0 +1,18 @@ +Texas Instruments TAS5805 Audio amplifier + +The TAS5805 serial control bus communicates through the I2C protocol only. The +serial bus is also used for periodic codec fault checking/reporting during +audio playback. For more product information please see the links below: + +Required properties: + +- compatible : "ti, tas5805" +- reg : I2C slave address + +Example: + +tas5805: tas5805@7c { + status = "okay"; + compatible = "ti,tas5805"; + reg = <0x2d>; +}; diff --git a/MAINTAINERS b/MAINTAINERS index 49d725df3397..23e57187329b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13981,6 +13981,14 @@ F: sound/soc/codecs/amlogic/Makefile F: sound/soc/codecs/amlogic/tas5707.c F: sound/soc/codecs/amlogic/tas5707.h +AMLOGIC Audio codec driver +M: Yonghao Jiao +F: arch/arm/configs/meson32_deconfig +F: sound/soc/codecs/amlogic/Kconfig +F: sound/soc/codecs/amlogic/Makefile +F: sound/soc/codecs/amlogic/tas5805.c +F: sound/soc/codecs/amlogic/tas5805.h + AMLOGIC AXG ADD DTS FOR A113D SOCKET AND DEVELOPMENT BOARDS M: Yun Cai F: arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts @@ -14671,10 +14679,12 @@ AMLOGIC TL1 SOUND CARD AMLOGIC TL1 AUDIO EXTERANL INPUT/OUTPUT DRIVERS AMLOGIC TL1 NEW EQDRC AMLOGIC TL1 MIXER CONTROLS +AMLOGIC TL1 VAD DRIVER M: Xing Wang ; }; }; - }; /* Audio Related end */ @@ -1129,6 +1128,34 @@ status = "disabled"; }; + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + status = "disabled"; + }; }; /* end of audiobus */ &pinctrl_periphs { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts new file mode 100644 index 000000000000..355d25ee4d92 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -0,0 +1,1776 @@ +/* + * arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontl1.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +#include "mesontl1_t309-panel.dtsi" + +/ { + model = "Amlogic TL1 T962X2 T309"; + amlogic-dt-id = "tl1_t962x2_t309"; + compatible = "amlogic, tl1_t962x2_t309"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x12000000 0x13400000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x71000000 0xc00000>; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*vbi reserved mem*/ + vbi_reserved:linux,vbi { + compatible = "amlogic, vbi-mem"; + size = <0x100000>; + alloc-ranges = <0x0e000000 0x800000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x2000000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + memory-region = <&vbi_reserved>; + status = "okay"; + interrupts = <0 83 1>; + reserve-iomap = "true"; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 1>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1680>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + sustainable-power = <1680>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + sustainable-power = <1680>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <761000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <791000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <801000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <831000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <861000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <891000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <921000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c0>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_a>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + eq_enable = <1>; + multiband_drc_enable = <0>; + fullband_drc_enable = <0>; + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 4f1bee41f6ab..6ddf8823143f 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -167,6 +167,7 @@ reg = <0xff632000 0x1c>; tdmout_index = <0>; tdmin_index = <0>; + dat1_ch_sel = <1>; }; auge_sound { @@ -178,7 +179,7 @@ aml-audio-card,dai-link@0 { format = "i2s"; mclk-fs = <256>; - //continuous-clock; + continuous-clock; //bitclock-inversion; //frame-inversion; /* master mode */ @@ -937,7 +938,7 @@ clocks = <&clkaudio CLKID_AUDIO_MCLK_A &clkc CLKID_MPLL0 - &clkc CLKID_MPLL1>; + &clkc CLKID_MPLL0>; clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; pinctrl-names = "tdm_pins"; @@ -1024,7 +1025,7 @@ * 7: "Enable:192K", */ asrc_id = <0>; - auto_asrc = <0>; + auto_asrc = <3>; status = "okay"; }; @@ -1107,8 +1108,8 @@ asrca: resample@0 { compatible = "amlogic, tl1-resample-a"; - clocks = <&clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_MCLK_F + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A &clkaudio CLKID_AUDIO_RESAMPLE_A>; clock-names = "resample_pll", "resample_src", "resample_clk"; /*same with toddr_src @@ -1123,7 +1124,7 @@ */ resample_module = <3>; - status = "disabled"; + status = "okay"; }; asrcb: resample@1 { @@ -1149,6 +1150,41 @@ status = "disabled"; }; + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <0>; + + status = "disabled"; + }; }; /* end of audiobus */ &pinctrl_periphs { @@ -1229,6 +1265,14 @@ pinctrl-0=<&i2c2_z_pins>; clock-frequency = <400000>; + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + ad82584f: ad82584f@62 { compatible = "ESMT, ad82584f"; #sound-dai-cells = <0>; diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index db75074efec6..71f5e9fab311 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -482,6 +482,7 @@ CONFIG_AMLOGIC_SND_CODEC_AMLT9015S=y CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y CONFIG_AMLOGIC_SND_CODEC_TL1_ACODEC=y CONFIG_AMLOGIC_SND_SOC_TAS5707=y +CONFIG_AMLOGIC_SND_SOC_TAS5805=y CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y CONFIG_AMLOGIC_SND_SOC_PCM186X=y CONFIG_AMLOGIC_SND_SOC_SSM3525=y diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts index 261293d955d2..f805271bbd23 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts @@ -854,6 +854,7 @@ unifykey-index-3 = <&keysn_3>; unifykey-index-4 = <&keysn_4>; unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; keysn_0: key_0{ key-name = "usid"; @@ -887,6 +888,11 @@ key-device = "normal"; key-permit = "read","write","del"; }; + keysn_6:key_6{ + key-name = "gva_certs"; + key-device = "normal"; + key-permit = "read","write","del"; + }; };//End unifykey audio_data: audio_data { compatible = "amlogic, audio_data"; @@ -1111,7 +1117,7 @@ #sound-dai-cells = <0>; clocks = <&clkaudio CLKID_AUDIO_PDM &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 + &clkc CLKID_MPLL2 &clkaudio CLKID_AUDIO_PDMIN0 &clkaudio CLKID_AUDIO_PDMIN1>; clock-names = "gate", diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts index 6c223f739b93..1b2300f0f4ef 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts @@ -668,13 +668,14 @@ compatible = "amlogic, unifykey"; status = "ok"; - unifykey-num = <6>; + unifykey-num = <7>; unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; unifykey-index-3 = <&keysn_3>; unifykey-index-4 = <&keysn_4>; unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; keysn_0: key_0{ key-name = "usid"; @@ -708,6 +709,11 @@ key-device = "normal"; key-permit = "read","write","del"; }; + keysn_6:key_6{ + key-name = "gva_certs"; + key-device = "normal"; + key-permit = "read","write","del"; + }; };//End unifykey audio_data: audio_data { compatible = "amlogic, audio_data"; @@ -934,7 +940,7 @@ #sound-dai-cells = <0>; clocks = <&clkaudio CLKID_AUDIO_PDM &clkc CLKID_FCLK_DIV3 - &clkc CLKID_MPLL3 + &clkc CLKID_MPLL2 &clkaudio CLKID_AUDIO_PDMIN0 &clkaudio CLKID_AUDIO_PDMIN1>; clock-names = "gate", @@ -992,6 +998,26 @@ status = "okay"; }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; }; /* end of audiobus */ &pinctrl_periphs { diff --git a/include/linux/amlogic/major.h b/include/linux/amlogic/major.h index 4d2f9c2becad..1ce50430bb88 100644 --- a/include/linux/amlogic/major.h +++ b/include/linux/amlogic/major.h @@ -29,6 +29,7 @@ #define AMAUDIO2_MAJOR (13+(AML_BASE)) #define VFM_MAJOR (14+(AML_BASE)) #define IONVIDEO_MAJOR (15+(AML_BASE)) +#define VAD_MAJOR (16+(AML_BASE)) /* *#define UIO_MAJOR 4+(AML_BASE) *#define USB_DEV_EP_MAJOR 5+(AML_BASE) diff --git a/sound/soc/amlogic/auge/Makefile b/sound/soc/amlogic/auge/Makefile index f7fbe5ece59d..4cf47bec8853 100644 --- a/sound/soc/amlogic/auge/Makefile +++ b/sound/soc/amlogic/auge/Makefile @@ -29,4 +29,7 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \ pwrdet_hw.o \ sharebuffer.o \ extn.o \ - frhdmirx_hw.o + frhdmirx_hw.o \ + vad.o \ + vad_hw.o \ + vad_dev.o diff --git a/sound/soc/amlogic/auge/audio_utils.c b/sound/soc/amlogic/auge/audio_utils.c index cae3be9b38ff..32dca83e41c3 100644 --- a/sound/soc/amlogic/auge/audio_utils.c +++ b/sound/soc/amlogic/auge/audio_utils.c @@ -25,6 +25,7 @@ #include "ddr_mngr.h" #include "resample.h" #include "effects_v2.h" +#include "vad.h" #include #include @@ -951,6 +952,10 @@ int snd_card_add_kcontrols(struct snd_soc_card *card) return ret; } + ret = card_add_vad_kcontrols(card); + if (ret < 0) + pr_warn_once("Failed to add VAD controls\n"); + return snd_soc_add_card_controls(card, snd_auge_controls, ARRAY_SIZE(snd_auge_controls)); diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index d350436f7192..4d70dec390cd 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -14,6 +14,7 @@ * more details. * */ +#define DEBUG #undef pr_fmt #define pr_fmt(fmt) "audio_ddr_mngr: " fmt @@ -23,6 +24,9 @@ #include #include +#include +#include + #include "regs.h" #include "ddr_mngr.h" #include "audio_utils.h" @@ -33,131 +37,11 @@ #include "effects_hw_v2.h" #include "effects_v2.h" #include "pwrdet_hw.h" +#include "vad.h" #define DRV_NAME "audio-ddr-manager" static DEFINE_MUTEX(ddr_mutex); -#if 0 -struct ddr_desc { - /* start address of DDR */ - unsigned int start; - /* finish address of DDR */ - unsigned int finish; - /* interrupt address or counts of DDR blocks */ - unsigned int intrpt; - /* fifo total counts */ - unsigned int fifo_depth; - /* fifo start threshold */ - unsigned int fifo_thr; - enum ddr_types data_type; - unsigned int edian; - unsigned int pp_mode; - //unsigned int reg_base; - struct clk *ddr; - struct clk *ddr_arb; -}; -#endif - -struct ddr_chipinfo { - /* INT and Start address is same or separated */ - bool int_start_same_addr; - /* force finished */ - bool force_finished; - /* same source */ - bool same_src_fn; - /* insert channel number */ - bool insert_chnum; - - /* ddr bus in urgent */ - bool ugt; - - /* source sel switch to ctrl1 - * for toddr, 0: source sel is controlled by ctrl0 - * 1: source sel is controlled by ctrl1 - * for frddr, 0: source sel is controlled by ctrl0 - * 1: source sel is controlled by ctrl2 - */ - bool src_sel_ctrl; - - /* - * resample source sel switch - * resample : from ctrl0 to ctrl3 - * toddr : from ctrl0 to ctrl1 - */ - bool asrc_src_sel_ctrl; - /* spdif in 32bit, only support left justified */ - bool asrc_only_left_j; - - /* toddr number max - * 0: default, 3 toddr, axg, g12a, g12b - * 4: 4 toddr, tl1 - */ - int fifo_num; -}; - -struct toddr { - //struct ddr_desc dscrpt; - struct device *dev; - unsigned int resample: 1; - unsigned int ext_signed: 1; - unsigned int msb_bit; - unsigned int lsb_bit; - unsigned int reg_base; - unsigned int bitdepth; - unsigned int channels; - unsigned int rate; - enum toddr_src src; - unsigned int fifo_id; - - unsigned int asrc_src_sel; - - int is_lb; /* check whether for loopback */ - int irq; - bool in_use: 1; - struct aml_audio_controller *actrl; - struct ddr_chipinfo *chipinfo; -}; - -enum status { - DISABLED, - READY, /* controls has set enable, but ddr is not in running */ - RUNNING, -}; - -struct toddr_attach { - bool enable; - int id; - int status; - /* which module should be attached, - * check which toddr in use should be attached - */ - enum toddr_src attach_module; -}; - -struct frddr_attach { - bool enable; - int status; - /* which module for attach , - * check which frddr in use should be added - */ - enum frddr_dest attach_module; -}; - -struct frddr { - //struct ddr_desc dscrpt; - struct device *dev; - enum frddr_dest dest; - struct aml_audio_controller *actrl; - unsigned int reg_base; - unsigned int fifo_id; - - unsigned int msb; - unsigned int type; - - int irq; - bool in_use; - struct ddr_chipinfo *chipinfo; -}; #define DDRMAX 4 static struct frddr frddrs[DDRMAX]; @@ -173,6 +57,11 @@ static struct toddr_attach attach_pwrdet; static void aml_check_pwrdet(bool enable); static bool aml_check_pwrdet_module(int src); +/* VAD */ +static struct toddr_attach attach_vad; +static void aml_check_vad(struct toddr *to, bool enable); + + /* Audio EQ DRC */ static struct frddr_attach attach_aed; static void aml_check_aed(bool enable, int dst); @@ -213,7 +102,7 @@ static struct toddr *register_toddr_l(struct device *dev, to->dev = dev; to->actrl = actrl; to->in_use = true; - pr_info("toddrs[%d] registered by device %s\n", i, dev_name(dev)); + pr_debug("toddrs[%d] registered by device %s\n", i, dev_name(dev)); return to; } @@ -259,7 +148,7 @@ static int unregister_toddr_l(struct device *dev, void *data) to->dev = NULL; to->actrl = NULL; to->in_use = false; - pr_info("toddrs[%d] released by device %s\n", i, dev_name(dev)); + pr_debug("toddrs[%d] released by device %s\n", i, dev_name(dev)); return 0; } @@ -275,8 +164,6 @@ int fetch_toddr_index_by_src(int toddr_src) } } - pr_err("invalid toddr src\n"); - return -1; } @@ -291,8 +178,6 @@ struct toddr *fetch_toddr_by_src(int toddr_src) } } - pr_err("invalid toddr src\n"); - return NULL; } @@ -332,6 +217,9 @@ int aml_toddr_set_buf(struct toddr *to, unsigned int start, unsigned int reg_base = to->reg_base; unsigned int reg; + to->start_addr = start; + to->end_addr = end; + reg = calc_toddr_address(EE_AUDIO_TODDR_A_START_ADDR, reg_base); aml_audiobus_write(actrl, reg, start); reg = calc_toddr_address(EE_AUDIO_TODDR_A_FINISH_ADDR, reg_base); @@ -347,6 +235,41 @@ int aml_toddr_set_buf(struct toddr *to, unsigned int start, return 0; } +int aml_toddr_set_buf_startaddr(struct toddr *to, unsigned int start) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + to->start_addr = start; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_START_ADDR, reg_base); + aml_audiobus_write(actrl, reg, start); + + /* int address */ + if (to->chipinfo + && (!to->chipinfo->int_start_same_addr)) { + reg = calc_toddr_address(EE_AUDIO_TODDR_A_INIT_ADDR, reg_base); + aml_audiobus_write(actrl, reg, start); + } + + return 0; +} + +int aml_toddr_set_buf_endaddr(struct toddr *to, unsigned int end) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + to->end_addr = end; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_FINISH_ADDR, reg_base); + aml_audiobus_write(actrl, reg, end); + + return 0; +} + int aml_toddr_set_intrpt(struct toddr *to, unsigned int intrpt) { struct aml_audio_controller *actrl = to->actrl; @@ -371,6 +294,34 @@ unsigned int aml_toddr_get_position(struct toddr *to) return aml_audiobus_read(actrl, reg); } +unsigned int aml_toddr_get_addr(struct toddr *to, enum status_sel sel) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg_sel, reg, addr; + + reg_sel = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); + aml_audiobus_update_bits(actrl, reg_sel, + 0xf << 8, + sel << 8); + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_STATUS2, reg_base); + addr = aml_audiobus_read(actrl, reg); + + if (sel == VAD_WAKEUP_ADDR) { + /* clear VAD addr/cnt */ + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); + aml_audiobus_update_bits(actrl, reg, 0x1 << 1, 0x1 << 1); + } + + /* reset to default, current write addr */ + aml_audiobus_update_bits(actrl, reg_sel, + 0xf << 8, + 0x0 << 8); + + return addr; +} + void aml_toddr_enable(struct toddr *to, bool enable) { struct aml_audio_controller *actrl = to->actrl; @@ -383,9 +334,16 @@ void aml_toddr_enable(struct toddr *to, bool enable) /* check resample */ aml_check_resample(to, enable); - /* check power detect */ - if (aml_check_pwrdet_module(to->src)) - aml_check_pwrdet(enable); + if (to->chipinfo + && to->chipinfo->wakeup) { + if (to->chipinfo->wakeup == 1) { + /* check power detect */ + if (aml_check_pwrdet_module(to->src)) + aml_check_pwrdet(enable); + } else if (to->chipinfo->wakeup == 2) + /* check VAD */ + aml_check_vad(to, enable); + } if (!enable) aml_audiobus_write(actrl, reg, 0x0); @@ -444,6 +402,35 @@ void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh) } } +void aml_toddr_update_fifos_rd_th(struct toddr *to, int th) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg, mask, val; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); + if (to->chipinfo + && to->chipinfo->src_sel_ctrl) { + mask = 0xfff << 12; + val = (th - 1) << 12; + } else { + mask = 0xff << 16; + val = (th - 1) << 16; + } + aml_audiobus_update_bits(actrl, reg, mask, val); +} + +void aml_toddr_force_finish(struct toddr *to) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); + aml_audiobus_update_bits(actrl, reg, 1 << 25, 1 << 25); + aml_audiobus_update_bits(actrl, reg, 1 << 25, 0 << 25); +} + void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt) { struct aml_audio_controller *actrl = to->actrl; @@ -499,8 +486,6 @@ void aml_toddr_set_resample(struct toddr *to, bool enable) unsigned int reg_base = to->reg_base; unsigned int reg; - pr_info("toddr selects data to %s resample\n", - enable ? "enable" : "disable"); reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); aml_audiobus_update_bits(actrl, reg, 1<<30, enable<<30); } @@ -511,9 +496,6 @@ void aml_toddr_set_resample_ab(struct toddr *to, int asrc_src_sel, bool enable) unsigned int reg_base = to->reg_base; unsigned int reg; - pr_info("toddr selects data to %s resample %c\n", - enable ? "enable" : "disable", - (asrc_src_sel == 0) ? 'a' : 'b'); reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); if (asrc_src_sel == 0) aml_audiobus_update_bits(actrl, reg, 1 << 27, enable << 27); @@ -546,11 +528,12 @@ static void aml_resample_enable( } } - pr_info("Resample %d in running, module:%d, toddr:%d, asrc_src_sel:%d\n", - p_attach_resample->id, - p_attach_resample->attach_module, + pr_info("toddr %d selects data to %s resample_%c for module:%s\n", to->fifo_id, - to->asrc_src_sel); + enable ? "enable" : "disable", + (p_attach_resample->id == 0) ? 'a' : 'b', + toddr_src_get_str(p_attach_resample->attach_module) + ); if (enable) { int bitwidth = to->bitdepth; @@ -708,17 +691,18 @@ void aml_pwrdet_enable(bool enable, int pwrdet_module) if (!to) { attach_pwrdet.status = READY; - pr_info("not in capture, power detect is ready\n"); } else { attach_pwrdet.status = RUNNING; aml_set_pwrdet(to, enable); + pr_info("Capture with power detect\n"); } } } else { if (attach_pwrdet.status == RUNNING) { struct toddr *to = fetch_toddr_by_src(pwrdet_module); - aml_set_pwrdet(to, enable); + if (to) + aml_set_pwrdet(to, enable); } attach_pwrdet.status = DISABLED; } @@ -751,6 +735,79 @@ static void aml_check_pwrdet(bool enable) } } +static void aml_vad_enable( + struct toddr_attach *p_attach_vad, + bool enable) +{ + struct toddr *to = fetch_toddr_by_src(p_attach_vad->attach_module); + + if (!to) + return; + + vad_set_toddr_info(enable ? to : NULL); + + /* vad enable or not */ + vad_enable(enable); +} + +void aml_set_vad(bool enable, int module) +{ + struct toddr_attach *p_attach_vad = &attach_vad; + bool update_running = false; + + p_attach_vad->enable = enable; + p_attach_vad->attach_module = module; + + if (enable) { + if ((p_attach_vad->status == DISABLED) + || (p_attach_vad->status == READY)) { + struct toddr *to = fetch_toddr_by_src( + p_attach_vad->attach_module); + + if (!to) { + p_attach_vad->status = READY; + } else { + p_attach_vad->status = RUNNING; + update_running = true; + pr_info("Capture with VAD\n"); + } + } + } else { + if (p_attach_vad->status == RUNNING) + update_running = true; + + p_attach_vad->status = DISABLED; + } + + if (update_running) + aml_vad_enable(p_attach_vad, enable); +} + +/* + * when try to enable vad, if toddr is not in used, + * set vad status as ready + */ +static void aml_check_vad(struct toddr *to, bool enable) +{ + struct toddr_attach *p_attach_vad = &attach_vad; + bool is_vad = false; + + if (p_attach_vad->enable + && (to->src == p_attach_vad->attach_module)) + is_vad = true; + + /* vad in enable */ + if (is_vad) { + if (enable) + p_attach_vad->status = RUNNING; + else + p_attach_vad->status = DISABLED; + + aml_vad_enable(p_attach_vad, enable); + } +} + + /* from DDRS */ static struct frddr *register_frddr_l(struct device *dev, struct aml_audio_controller *actrl, @@ -786,7 +843,7 @@ static struct frddr *register_frddr_l(struct device *dev, from->dev = dev; from->actrl = actrl; from->in_use = true; - pr_info("frddrs[%d] registered by device %s\n", i, dev_name(dev)); + pr_debug("frddrs[%d] registered by device %s\n", i, dev_name(dev)); return from; } @@ -826,7 +883,7 @@ static int unregister_frddr_l(struct device *dev, void *data) from->dev = NULL; from->actrl = NULL; from->in_use = false; - pr_info("frddrs[%d] released by device %s\n", i, dev_name(dev)); + pr_debug("frddrs[%d] released by device %s\n", i, dev_name(dev)); return 0; } @@ -841,7 +898,6 @@ int fetch_frddr_index_by_src(int frddr_src) } } - pr_err("invalid frdd_src\n"); return -1; } @@ -856,8 +912,6 @@ struct frddr *fetch_frddr_by_src(int frddr_src) } } - pr_err("invalid frddr src\n"); - return NULL; } @@ -877,7 +931,8 @@ int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel) && (frddrs[i].fifo_id != current_fifo_id) && (frddrs[i].dest == ss_sel)) { - pr_info("ss_sel:%d used, invalid for share buffer\n", + pr_info(" frddr:%d, ss_sel:%d used, invalid for share buffer\n", + i, ss_sel); ret = 0; break; @@ -971,9 +1026,18 @@ void aml_frddr_enable(struct frddr *fr, bool enable) /* ensure disable before enable frddr */ aml_audiobus_update_bits(actrl, reg, 1<<31, enable<<31); - if (!enable) + if (!enable) { aml_audiobus_write(actrl, reg, 0x0); + /* clr src sel and its en */ + if (fr->chipinfo + && fr->chipinfo->src_sel_ctrl) { + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, + reg_base); + aml_audiobus_write(actrl, reg, 0x0); + } + } + /* check for Audio EQ/DRC */ if (aml_check_aed_module(fr->dest)) aml_check_aed(enable, fr->dest); @@ -1019,8 +1083,6 @@ void aml_frddr_select_dst_ss(struct frddr *fr, unsigned int reg_base = fr->reg_base; unsigned int reg, ss_valid; - reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, reg_base); - ss_valid = aml_check_sharebuffer_valid(fr, dst); /* same source en */ @@ -1029,21 +1091,54 @@ void aml_frddr_select_dst_ss(struct frddr *fr, && ss_valid) { int s_v = 0, s_m = 0; - switch (sel) { - case 1: - s_m = 0xf << 4; - s_v = enable ? (dst << 4 | 1 << 7) : 0 << 4; - break; - case 2: - s_m = 0xf << 8; - s_v = enable ? (dst << 8 | 1 << 11) : 0 << 8; - break; - default: - pr_warn_once("sel :%d is not supported for same source\n", - sel); - break; + if (fr->chipinfo + && fr->chipinfo->src_sel_ctrl) { + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, + reg_base); + + switch (sel) { + case 1: + s_m = 0x17 << 8; + s_v = enable ? + (dst << 8 | 1 << 12) : 0 << 8; + break; + case 2: + s_m = 0x17 << 16; + s_v = enable ? + (dst << 16 | 1 << 20) : 0 << 16; + break; + default: + pr_warn_once("sel :%d is not supported for same source\n", + sel); + break; + } + s_m |= 0xff << 24; + if (enable) + s_v |= (fr->channels - 1) << 24; + else + s_v |= 0x0 << 24; + } else { + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, + reg_base); + + switch (sel) { + case 1: + s_m = 0xf << 4; + s_v = enable ? + (dst << 4 | 1 << 7) : 0 << 4; + break; + case 2: + s_m = 0xf << 8; + s_v = enable ? + (dst << 8 | 1 << 11) : 0 << 8; + break; + default: + pr_warn_once("sel :%d is not supported for same source\n", + sel); + break; + } } - pr_info("%s sel:%d, dst_src:%d\n", + pr_debug("%s sel:%d, dst_src:%d\n", __func__, sel, dst); aml_audiobus_update_bits(actrl, reg, s_m, s_v); } @@ -1073,8 +1168,11 @@ unsigned int aml_frddr_get_fifo_id(struct frddr *fr) } void aml_frddr_set_format(struct frddr *fr, - unsigned int msb, unsigned int frddr_type) + unsigned int chnum, + unsigned int msb, + unsigned int frddr_type) { + fr->channels = chnum; fr->msb = msb; fr->type = frddr_type; } @@ -1336,11 +1434,13 @@ int card_add_ddr_kcontrols(struct snd_soc_card *card) static struct ddr_chipinfo axg_ddr_chipinfo = { .int_start_same_addr = true, .asrc_only_left_j = true, + .wakeup = 1, }; static struct ddr_chipinfo g12a_ddr_chipinfo = { .same_src_fn = true, .asrc_only_left_j = true, + .wakeup = 1, }; static struct ddr_chipinfo tl1_ddr_chipinfo = { @@ -1349,6 +1449,7 @@ static struct ddr_chipinfo tl1_ddr_chipinfo = { .src_sel_ctrl = true, .asrc_src_sel_ctrl = true, .fifo_num = 4, + .wakeup = 2, }; static const struct of_device_id aml_ddr_mngr_device_id[] = { @@ -1368,11 +1469,45 @@ static const struct of_device_id aml_ddr_mngr_device_id[] = { }; MODULE_DEVICE_TABLE(of, aml_ddr_mngr_device_id); +static bool pm_audio_in_suspend; + +void pm_audio_set_suspend(bool is_suspend) +{ + pm_audio_in_suspend = is_suspend; +} + +bool pm_audio_is_suspend(void) +{ + return pm_audio_in_suspend; +} + +/* Detects a suspend and resume event */ +static int ddr_pm_event(struct notifier_block *notifier, + unsigned long pm_event, void *unused) +{ + pr_info("%s, pm_event:%lu\n", __func__, pm_event); + + switch (pm_event) { + case PM_SUSPEND_PREPARE: + pm_audio_set_suspend(true); + break; + case PM_POST_SUSPEND: + break; + default: + break; + } + return NOTIFY_DONE; +} + +static struct notifier_block ddr_pm_notifier_block = { + .notifier_call = ddr_pm_event, +}; + static int aml_ddr_mngr_platform_probe(struct platform_device *pdev) { struct ddr_chipinfo *p_ddr_chipinfo; int ddr_num = 3; /* early chipset support max 3 ddr num */ - int i; + int i, ret; p_ddr_chipinfo = (struct ddr_chipinfo *) of_device_get_match_data(&pdev->dev); @@ -1436,6 +1571,12 @@ static int aml_ddr_mngr_platform_probe(struct platform_device *pdev) frddrs[DDR_D].fifo_id = DDR_D; } } + + ret = register_pm_notifier(&ddr_pm_notifier_block); + if (ret) + pr_warn("[%s] failed to register PM notifier %d\n", + __func__, ret); + return 0; } diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index 30ed31c7d9ee..ab1c795b64b1 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -73,6 +73,16 @@ enum frddr_dest { SPDIFOUT_B, }; +enum status_sel { + CURRENT_DDR_ADDR, + NEXT_FINISH_ADDR, + COUNT_CURRENT_DDR_ACK, + COUNT_NEXT_FINISH_DDR_ACK, + VAD_WAKEUP_ADDR, /* from tl1, vad */ + VAD_FS_ADDR, + VAD_FIFO_CNT, +}; + struct toddr_fmt { unsigned int type; unsigned int msb; @@ -83,6 +93,140 @@ struct toddr_fmt { unsigned int rate; }; +#if 0 +struct ddr_desc { + /* start address of DDR */ + unsigned int start; + /* finish address of DDR */ + unsigned int finish; + /* interrupt address or counts of DDR blocks */ + unsigned int intrpt; + /* fifo total counts */ + unsigned int fifo_depth; + /* fifo start threshold */ + unsigned int fifo_thr; + enum ddr_types data_type; + unsigned int edian; + unsigned int pp_mode; + //unsigned int reg_base; + struct clk *ddr; + struct clk *ddr_arb; +}; +#endif + +struct ddr_chipinfo { + /* INT and Start address is same or separated */ + bool int_start_same_addr; + /* force finished */ + bool force_finished; + /* same source */ + bool same_src_fn; + /* insert channel number */ + bool insert_chnum; + + /* ddr bus in urgent */ + bool ugt; + + /* source sel switch to ctrl1 + * for toddr, 0: source sel is controlled by ctrl0 + * 1: source sel is controlled by ctrl1 + * for frddr, 0: source sel is controlled by ctrl0 + * 1: source sel is controlled by ctrl2 + */ + bool src_sel_ctrl; + + /* + * resample source sel switch + * resample : from ctrl0 to ctrl3 + * toddr : from ctrl0 to ctrl1 + */ + bool asrc_src_sel_ctrl; + /* spdif in 32bit, only support left justified */ + bool asrc_only_left_j; + + /* toddr number max + * 0: default, 3 toddr, axg, g12a, g12b + * 4: 4 toddr, tl1 + */ + int fifo_num; + + /* power detect or VAD + * 0: disabled + * 1: power detect + * 2: vad + */ + int wakeup; +}; + +struct toddr { + //struct ddr_desc dscrpt; + struct device *dev; + unsigned int resample: 1; + unsigned int ext_signed: 1; + unsigned int msb_bit; + unsigned int lsb_bit; + unsigned int reg_base; + unsigned int bitdepth; + unsigned int channels; + unsigned int rate; + + unsigned int start_addr; + unsigned int end_addr; + + enum toddr_src src; + unsigned int fifo_id; + + unsigned int asrc_src_sel; + + int is_lb; /* check whether for loopback */ + int irq; + bool in_use: 1; + struct aml_audio_controller *actrl; + struct ddr_chipinfo *chipinfo; +}; + +enum status { + DISABLED, + READY, /* controls has set enable, but ddr is not in running */ + RUNNING, +}; + +struct toddr_attach { + bool enable; + int id; + int status; + /* which module should be attached, + * check which toddr in use should be attached + */ + enum toddr_src attach_module; +}; + +struct frddr_attach { + bool enable; + int status; + /* which module for attach , + * check which frddr in use should be added + */ + enum frddr_dest attach_module; +}; + +struct frddr { + //struct ddr_desc dscrpt; + struct device *dev; + enum frddr_dest dest; + struct aml_audio_controller *actrl; + unsigned int reg_base; + unsigned int fifo_id; + + unsigned int channels; + unsigned int msb; + unsigned int type; + + int irq; + bool in_use; + struct ddr_chipinfo *chipinfo; +}; + /* to ddrs */ int fetch_toddr_index_by_src(int toddr_src); struct toddr *fetch_toddr_by_src(int toddr_src); @@ -92,11 +236,17 @@ struct toddr *aml_audio_register_toddr(struct device *dev, int aml_audio_unregister_toddr(struct device *dev, void *data); int aml_toddr_set_buf(struct toddr *to, unsigned int start, unsigned int end); +int aml_toddr_set_buf_startaddr(struct toddr *to, unsigned int start); +int aml_toddr_set_buf_endaddr(struct toddr *to, unsigned int end); + int aml_toddr_set_intrpt(struct toddr *to, unsigned int intrpt); unsigned int aml_toddr_get_position(struct toddr *to); +unsigned int aml_toddr_get_addr(struct toddr *to, enum status_sel sel); void aml_toddr_select_src(struct toddr *to, enum toddr_src); void aml_toddr_enable(struct toddr *to, bool enable); void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh); +void aml_toddr_update_fifos_rd_th(struct toddr *to, int th); +void aml_toddr_force_finish(struct toddr *to); void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt); void aml_toddr_insert_chanum(struct toddr *to); unsigned int aml_toddr_read(struct toddr *to); @@ -106,6 +256,8 @@ void aml_toddr_write(struct toddr *to, unsigned int val); void aml_set_resample(int id, bool enable, int resample_module); /* power detect */ void aml_pwrdet_enable(bool enable, int pwrdet_module); +/* Voice Activity Detection */ +void aml_set_vad(bool enable, int module); /* from ddrs */ int fetch_frddr_index_by_src(int frddr_src); @@ -130,7 +282,9 @@ void aml_frddr_set_fifos(struct frddr *fr, unsigned int depth, unsigned int thresh); unsigned int aml_frddr_get_fifo_id(struct frddr *fr); void aml_frddr_set_format(struct frddr *fr, - unsigned int msb, unsigned int frddr_type); + unsigned int chnum, + unsigned int msb, + unsigned int frddr_type); /* audio eq drc */ void aml_set_aed(bool enable, int aed_module); @@ -144,5 +298,8 @@ const char *frddr_src_get_str(int idx); int card_add_ddr_kcontrols(struct snd_soc_card *card); +void pm_audio_set_suspend(bool is_suspend); +bool pm_audio_is_suspend(void); + #endif diff --git a/sound/soc/amlogic/auge/extn.c b/sound/soc/amlogic/auge/extn.c index c0fe61605c77..55d3e46ec438 100644 --- a/sound/soc/amlogic/auge/extn.c +++ b/sound/soc/amlogic/auge/extn.c @@ -613,6 +613,72 @@ static int frhdmirx_set_mode( return 0; } +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI +/* spdif in audio format detect: LPCM or NONE-LPCM */ +struct sppdif_audio_info { + unsigned char aud_type; + /*IEC61937 package presamble Pc value*/ + short pc; + char *aud_type_str; +}; + +static const char *const spdif_audio_type_texts[] = { + "LPCM", + "AC3", + "EAC3", + "DTS", + "DTS-HD", + "TRUEHD", + "PAUSE" +}; + +static const struct sppdif_audio_info type_texts[] = { + {0, 0, "LPCM"}, + {1, 0x1, "AC3"}, + {2, 0x15, "EAC3"}, + {3, 0xb, "DTS-I"}, + {3, 0x0c, "DTS-II"}, + {3, 0x0d, "DTS-III"}, + {3, 0x11, "DTS-IV"}, + {4, 0, "DTS-HD"}, + {5, 0x16, "TRUEHD"}, + {6, 0x103, "PAUSE"}, + {6, 0x003, "PAUSE"}, + {6, 0x100, "PAUSE"}, +}; + +static const struct soc_enum hdmirx_audio_type_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdif_audio_type_texts), + spdif_audio_type_texts); + +static int hdmiin_check_audio_type(void) +{ + int total_num = sizeof(type_texts)/sizeof(struct sppdif_audio_info); + int pc = frhdmirx_get_chan_status_pc(); + int audio_type = 0; + int i; + + for (i = 0; i < total_num; i++) { + if (pc == type_texts[i].pc) { + audio_type = type_texts[i].aud_type; + break; + } + } + + pr_debug("%s audio type:%d\n", __func__, audio_type); + + return audio_type; +} + +static int hdmirx_audio_type_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.enumerated.item[0] = + hdmiin_check_audio_type(); + return 0; +} +#endif static const struct snd_kcontrol_new extn_controls[] = { /* Out */ @@ -664,6 +730,10 @@ static const struct snd_kcontrol_new extn_controls[] = { 0, aml_get_atmos_audio_edid, aml_set_atmos_audio_edid), + SOC_ENUM_EXT("HDMIIN Audio Type", + hdmirx_audio_type_enum, + hdmirx_audio_type_get_enum, + NULL), #endif }; @@ -723,8 +793,8 @@ static int extn_platform_probe(struct platform_device *pdev) /* Default ARC SRC */ p_extn->arc_src = 1; - /* Default: PAO mode */ - p_extn->hdmirx_mode = 1; + /* Default: SPDIF in mode */ + p_extn->hdmirx_mode = 0; ret = snd_soc_register_component(&pdev->dev, &extn_component, diff --git a/sound/soc/amlogic/auge/frhdmirx_hw.c b/sound/soc/amlogic/auge/frhdmirx_hw.c index c46f6df81a44..19c55f480522 100644 --- a/sound/soc/amlogic/auge/frhdmirx_hw.c +++ b/sound/soc/amlogic/auge/frhdmirx_hw.c @@ -84,7 +84,11 @@ void frhdmirx_ctrl(int channels, int src) /* PAO mode */ if (src) { audiobus_write(EE_AUDIO_FRHDMIRX_CTRL0, - 0x1 << 23 | 0x1 << 22 | 0x1 << 7); + 0x1 << 23 | /* slect pao mode */ + 0x1 << 22 | /* capture input by fall edge*/ + 0x1 << 7 | /* start sending ch num info out */ + 0x1 << 8 | /* start detect PAPB */ + 0x1 << 6 /* chan status sel: pao pc/pd value */); return; } @@ -101,7 +105,7 @@ void frhdmirx_ctrl(int channels, int src) 0x1 << 30 | /* chnum_sel */ lane_mask << 24 | /* chnum_sel */ 0x1 << 22 | /* clk_inv */ - 0x0 << 11 /* req_sel, Sync 4 spdifin by which */ + 0x0 << 11 /* req_sel, Sync 4 spdifin by which */ ); /* nonpcm2pcm_th */ @@ -110,3 +114,14 @@ void frhdmirx_ctrl(int channels, int src) /* enable irq bits */ frhdmirx_enable_irq_bits(channels, src); } + +unsigned int frhdmirx_get_chan_status_pc(void) +{ + unsigned int val; + + val = audiobus_read(EE_AUDIO_FRHDMIRX_STAT1); + return (val >> 16) & 0xff; +} + + + diff --git a/sound/soc/amlogic/auge/frhdmirx_hw.h b/sound/soc/amlogic/auge/frhdmirx_hw.h index ce51e13242cd..e0ebfe46323e 100644 --- a/sound/soc/amlogic/auge/frhdmirx_hw.h +++ b/sound/soc/amlogic/auge/frhdmirx_hw.h @@ -20,5 +20,5 @@ extern void frhdmirx_enable(bool enable); extern void frhdmirx_src_select(int src); extern void frhdmirx_ctrl(int channels, int src); - +extern unsigned int frhdmirx_get_chan_status_pc(void); #endif diff --git a/sound/soc/amlogic/auge/locker.c b/sound/soc/amlogic/auge/locker.c index bc53b6a0e0f6..d41cc4ab6ca7 100644 --- a/sound/soc/amlogic/auge/locker.c +++ b/sound/soc/amlogic/auge/locker.c @@ -14,6 +14,8 @@ * more details. * */ +#define DEBUG + #include #include @@ -192,7 +194,7 @@ void audio_locker_set(int enable) int audio_locker_get(void) { if (!s_locker) { - pr_err("audio locker is not init\n"); + pr_debug("audio locker is not init\n"); return -1; } diff --git a/sound/soc/amlogic/auge/pdm.c b/sound/soc/amlogic/auge/pdm.c index e29228d51294..d4ef74f0e7b1 100644 --- a/sound/soc/amlogic/auge/pdm.c +++ b/sound/soc/amlogic/auge/pdm.c @@ -34,6 +34,7 @@ #include "iomap.h" #include "regs.h" #include "ddr_mngr.h" +#include "vad.h" /*#define __PTM_PDM_CLK__*/ @@ -55,8 +56,8 @@ static struct snd_pcm_hardware aml_pdm_hardware = { .channels_min = PDM_CHANNELS_MIN, .channels_max = PDM_CHANNELS_MAX, - .buffer_bytes_max = 32 * 1024, - .period_bytes_max = 16 * 1024, + .buffer_bytes_max = 512 * 1024, + .period_bytes_max = 256 * 1024, .period_bytes_min = 32, .periods_min = 2, .periods_max = 1024, @@ -592,6 +593,10 @@ static int aml_pdm_dai_prepare( unsigned int bitwidth; unsigned int toddr_type, lsb; + if (vad_pdm_is_running() + && pm_audio_is_suspend()) + return 0; + /* set bclk */ bitwidth = snd_pcm_format_width(runtime->format); lsb = 32 - bitwidth; @@ -690,12 +695,21 @@ static int aml_pdm_dai_trigger( { struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai); - pr_info("%s\n", __func__); + pr_info("%s, cmd:%d\n", __func__, cmd); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + + if (vad_pdm_is_running() + && pm_audio_is_suspend()) { + pm_audio_set_suspend(false); + /* VAD switch to alsa buffer */ + vad_update_buffer(0); + break; + } + pdm_fifo_reset(); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { @@ -709,6 +723,13 @@ static int aml_pdm_dai_trigger( case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (vad_pdm_is_running() + && pm_audio_is_suspend()) { + /* switch to VAD buffer */ + vad_update_buffer(1); + break; + } + dev_info(substream->pcm->card->dev, "pdm capture stop\n"); pdm_enable(0); aml_toddr_enable(p_pdm->tddr, 0); diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index 326ebaa2f45a..7c56eb1cc200 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -14,6 +14,8 @@ * more details. * */ +#define DEBUG + #include #include #include @@ -82,7 +84,7 @@ static struct audioresample *get_audioresample(int id) p_resample = ((id == 0) ? s_resample_a : s_resample_b); if (!p_resample) { - pr_info("Not init audio resample\n"); + pr_debug("Not init audio resample\n"); return NULL; } @@ -105,19 +107,6 @@ static int resample_clk_set(struct audioresample *p_resample) /* enable clock */ if (p_resample->enable) { - ret = clk_prepare_enable(p_resample->clk); - if (ret) { - pr_err("Can't enable resample_clk clock: %d\n", - ret); - return -EINVAL; - } - - ret = clk_prepare_enable(p_resample->sclk); - if (ret) { - pr_err("Can't enable resample_src clock: %d\n", - ret); - return -EINVAL; - } if (p_resample->out_rate) { #ifdef __PTM_RESAMPLE_CLK__ @@ -144,6 +133,20 @@ static int resample_clk_set(struct audioresample *p_resample) return -EINVAL; } + ret = clk_prepare_enable(p_resample->sclk); + if (ret) { + pr_err("Can't enable resample_src clock: %d\n", + ret); + return -EINVAL; + } + + ret = clk_prepare_enable(p_resample->clk); + if (ret) { + pr_err("Can't enable resample_clk clock: %d\n", + ret); + return -EINVAL; + } + pr_info("%s, resample_pll:%lu, sclk:%lu, clk:%lu\n", __func__, clk_get_rate(p_resample->pll), @@ -226,7 +229,7 @@ static int resample_get_enum( struct audioresample *p_resample = snd_kcontrol_chip(kcontrol); if (!p_resample) { - pr_info("audio resample is not init\n"); + pr_debug("audio resample is not init\n"); return 0; } @@ -248,8 +251,9 @@ int resample_set(int id, int index) p_resample->asrc_rate_idx = index; - pr_info("%s %s\n", + pr_info("%s resample_%c %s\n", __func__, + (id == 0) ? 'a' : 'b', auge_resample_texts[index]); if (audio_resample_set(p_resample, (bool)index, resample_rate)) @@ -274,7 +278,7 @@ static int resample_set_enum( int index = ucontrol->value.enumerated.item[0]; if (!p_resample) { - pr_info("audio resample is not init\n"); + pr_debug("audio resample is not init\n"); return 0; } @@ -355,7 +359,7 @@ static int resample_module_get_enum( struct audioresample *p_resample = snd_kcontrol_chip(kcontrol); if (!p_resample) { - pr_info("audio resample is not init\n"); + pr_debug("audio resample is not init\n"); return 0; } @@ -371,7 +375,7 @@ static int resample_module_set_enum( struct audioresample *p_resample = snd_kcontrol_chip(kcontrol); if (!p_resample) { - pr_info("audio resample is not init\n"); + pr_debug("audio resample is not init\n"); return 0; } @@ -582,4 +586,3 @@ static struct platform_driver resample_platform_driver = { .probe = resample_platform_probe, }; module_platform_driver(resample_platform_driver); - diff --git a/sound/soc/amlogic/auge/resample_hw.c b/sound/soc/amlogic/auge/resample_hw.c index 0425c607a572..1722ce8eb82d 100644 --- a/sound/soc/amlogic/auge/resample_hw.c +++ b/sound/soc/amlogic/auge/resample_hw.c @@ -70,8 +70,8 @@ int resample_init(int id, int input_sr) else pr_err("unsupport input sample rate:%d\n", input_sr); - pr_info("resample id:%d, clk_rate = %u, input_sr = %d, Avg_cnt_init = %u\n", - id, + pr_info("resample id:%c, clk_rate = %u, input_sr = %d, Avg_cnt_init = %u\n", + (id == 0) ? 'a' : 'b', clk_rate, input_sr, Avg_cnt_init); diff --git a/sound/soc/amlogic/auge/sharebuffer.c b/sound/soc/amlogic/auge/sharebuffer.c index 1ca66ad386fb..f94fd2a03b0c 100644 --- a/sound/soc/amlogic/auge/sharebuffer.c +++ b/sound/soc/amlogic/auge/sharebuffer.c @@ -34,7 +34,9 @@ static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream, spdifout_samesource_set(spdif_id, aml_frddr_get_fifo_id(fr), - bit_depth, true); + bit_depth, + runtime->channels, + true); /* spdif to hdmitx */ spdifout_to_hdmitx_ctrl(spdif_id); @@ -59,7 +61,9 @@ static int sharebuffer_spdifout_free(struct snd_pcm_substream *substream, if (spdif_id != 1) spdifout_samesource_set(spdif_id, aml_frddr_get_fifo_id(fr), - bit_depth, false); + bit_depth, + runtime->channels, + false); return 0; } @@ -90,7 +94,8 @@ int sharebuffer_prepare(struct snd_pcm_substream *substream, // TODO: same with tdm } else if (samesource_sel < 5) { /* same source with spdif a/b */ - sharebuffer_spdifout_prepare(substream, fr, samesource_sel - 3); + sharebuffer_spdifout_prepare(substream, + fr, samesource_sel - 3); } /* frddr, share buffer, src_sel1 */ diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index ce5a88bcc7d9..b28d920a6e1f 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -14,7 +14,7 @@ * more details. * */ - +#define DEBUG #include #include #include @@ -51,6 +51,8 @@ /* for debug */ /*#define __SPDIFIN_INSERT_CHNUM__*/ +/*#define __SPDIFIN_AUDIO_TYPE_HW__*/ + struct spdif_chipinfo { unsigned int id; @@ -236,7 +238,7 @@ static int spdifin_check_audio_type(void) } } - pr_debug("%s audio type:%d\n", __func__, audio_type); + /*pr_debug("%s audio type:%d\n", __func__, audio_type);*/ return audio_type; } @@ -253,6 +255,7 @@ static int spdifin_audio_type_get_enum( /* For fake */ static bool is_mute; +static int spdifin_src; static int aml_audio_set_spdif_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -268,6 +271,36 @@ static int aml_audio_get_spdif_mute(struct snd_kcontrol *kcontrol, return 0; } +static const char *const spdifin_src_texts[] = { + "spdifin pad", "spdifout", "N/A", "HDMIRX" +}; + +const struct soc_enum spdifin_src_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdifin_src_texts), + spdifin_src_texts); + +int spdifin_source_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.enumerated.item[0] = spdifin_src; + return 0; +} + +int spdifin_source_set_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int src = ucontrol->value.enumerated.item[0]; + + if (src > 3) { + pr_err("bad parameter for spdifin src set\n"); + return -1; + } + spdifin_set_src(src); + spdifin_src = src; + return 0; +} static const struct snd_kcontrol_new snd_spdif_controls[] = { @@ -288,6 +321,10 @@ static const struct snd_kcontrol_new snd_spdif_controls[] = { SOC_SINGLE_BOOL_EXT("Audio spdif mute", 0, aml_audio_get_spdif_mute, aml_audio_set_spdif_mute), + SOC_ENUM_EXT("Audio spdifin source", + spdifin_src_enum, + spdifin_source_get_enum, + spdifin_source_set_enum), }; @@ -525,11 +562,12 @@ static void spdifin_status_event(struct aml_spdif *p_spdif) pr_info("Event: EXTCON_SPDIFIN_SAMPLERATE, new sample rate:%s\n", spdifin_samplerate[mode + 1]); +#ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample enable, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) resample_set(p_spdif->asrc_id, p_spdif->auto_asrc); - +#endif extcon_set_state(p_spdif->edev, EXTCON_SPDIFIN_SAMPLERATE, 1); } @@ -547,16 +585,18 @@ static void spdifin_status_event(struct aml_spdif *p_spdif) EXTCON_SPDIFIN_AUDIOTYPE, 1); #ifdef __PTM_SPDIF_CLK__ +#ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample disable, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) resample_set(p_spdif->asrc_id, 0); +#endif #endif } if (intrpt_status & 0x10) pr_info("Pd changed\n"); } else { if (intrpt_status & 0x8) - pr_info("CH status changed\n"); + pr_debug("CH status changed\n"); if (intrpt_status & 0x10) { int val = spdifin_get_ch_status0to31(); @@ -579,9 +619,11 @@ static void spdifin_status_event(struct aml_spdif *p_spdif) extcon_set_state(p_spdif->edev, EXTCON_SPDIFIN_AUDIOTYPE, 0); +#ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample to 48k, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) resample_set(p_spdif->asrc_id, p_spdif->auto_asrc); +#endif } if (intrpt_status & 0x40) pr_info("valid changed\n"); @@ -818,7 +860,7 @@ static struct snd_pcm_ops aml_spdif_ops = { .mmap = aml_spdif_mmap, }; -#define PREALLOC_BUFFER (32 * 1024) +#define PREALLOC_BUFFER (128 * 1024) #define PREALLOC_BUFFER_MAX (256 * 1024) static int aml_spdif_new(struct snd_soc_pcm_runtime *rtd) { @@ -827,7 +869,7 @@ static int aml_spdif_new(struct snd_soc_pcm_runtime *rtd) p_spdif = (struct aml_spdif *)dev_get_drvdata(dev); - pr_info("%s spdif_%s, clk continuous:%d\n", + pr_debug("%s spdif_%s, clk continuous:%d\n", __func__, (p_spdif->id == 0) ? "a":"b", p_spdif->clk_cont); @@ -934,9 +976,12 @@ static int aml_dai_spdif_startup( pr_err("Can't enable pcm clk_spdifin clock: %d\n", ret); goto err; } + +#ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample to 48k in default, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) resample_set(p_spdif->asrc_id, p_spdif->auto_asrc); +#endif } return 0; @@ -963,10 +1008,11 @@ static void aml_dai_spdif_shutdown( clk_disable_unprepare(p_spdif->sysclk); clk_disable_unprepare(p_spdif->gate_spdifout); } else { +#ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample disabled, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) resample_set(p_spdif->asrc_id, 0); - +#endif clk_disable_unprepare(p_spdif->clk_spdifin); clk_disable_unprepare(p_spdif->fixed_clk); clk_disable_unprepare(p_spdif->gate_spdifin); @@ -1003,7 +1049,9 @@ static int aml_dai_spdif_prepare( } fifo_id = aml_frddr_get_fifo_id(fr); - aml_frddr_set_format(fr, bit_depth - 1, + aml_frddr_set_format(fr, + runtime->channels, + bit_depth - 1, spdifout_get_frddr_type(bit_depth)); aml_frddr_select_dst(fr, dst); aml_frddr_set_fifos(fr, 0x40, 0x20); @@ -1171,7 +1219,7 @@ static int aml_dai_spdif_hw_params(struct snd_pcm_substream *substream, static int aml_dai_set_spdif_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - pr_info("%s , fmt %#x\n", __func__, fmt); + pr_debug("%s , fmt %#x\n", __func__, fmt); return 0; } @@ -1185,10 +1233,10 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif) int ret; if (spdif_is_4x_clk()) { - pr_info("set 4x audio clk for 958\n"); + pr_debug("set 4x audio clk for 958\n"); p_spdif->sysclk_freq *= 4; } else { - pr_info("set normal 512 fs /4 fs\n"); + pr_debug("set normal 512 fs /4 fs\n"); } mpll_freq = p_spdif->sysclk_freq * mul; @@ -1210,10 +1258,10 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif) pr_err("Can't enable clk_spdifout clock: %d\n", ret); return; } - pr_info("\t set spdifout clk:%d, mpll:%d\n", + pr_debug("\t set spdifout clk:%d, mpll:%d\n", p_spdif->sysclk_freq, mpll_freq); - pr_info("\t get spdifout clk:%lu, mpll:%lu\n", + pr_debug("\t get spdifout clk:%lu, mpll:%lu\n", clk_get_rate(p_spdif->clk_spdifout), clk_get_rate(p_spdif->sysclk)); } @@ -1361,7 +1409,7 @@ static int aml_spdif_parse_of(struct platform_device *pdev) if (ret < 0) p_spdif->auto_asrc = 0; - pr_info("SPDIF id %d asrc_id:%d auto_asrc:%d\n", + pr_debug("SPDIF id %d asrc_id:%d auto_asrc:%d\n", p_spdif->id, p_spdif->asrc_id, p_spdif->auto_asrc); @@ -1486,7 +1534,7 @@ static int aml_spdif_platform_probe(struct platform_device *pdev) dev_warn_once(dev, "check whether to update spdif chipinfo\n"); - pr_info("%s, spdif ID = %u\n", __func__, aml_spdif->id); + pr_debug("%s, spdif ID = %u\n", __func__, aml_spdif->id); /* get audio controller */ node_prt = of_get_parent(node); diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index 496036d9f693..65b4d4703950 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -14,7 +14,7 @@ * more details. * */ - +#define DEBUG #include #include "iomap.h" @@ -64,7 +64,7 @@ void aml_spdifin_chnum_en(struct aml_audio_controller *actrl, reg = EE_AUDIO_SPDIFIN_CTRL0; aml_audiobus_update_bits(actrl, reg, 1 << 26, is_enable << 26); - pr_info("%s spdifin ctrl0:0x%x\n", + pr_debug("%s spdifin ctrl0:0x%x\n", __func__, aml_audiobus_read(actrl, reg)); } @@ -234,7 +234,7 @@ void aml_spdif_fifo_ctrl( return; } - pr_info("%s, bit depth:%d, frddr type:%d, toddr:type:%d\n", + pr_debug("%s, bit depth:%d, frddr type:%d, toddr:type:%d\n", __func__, bitwidth, frddr_type, @@ -403,12 +403,16 @@ void spdifout_clk_ctrl(int spdif_id, bool is_enable) audiobus_write(reg, is_enable << 31 | 0x0 << 24 | 0x3 << 0); } -void spdifout_fifo_ctrl(int spdif_id, int fifo_id, int bitwidth) +static void spdifout_fifo_ctrl(int spdif_id, + int fifo_id, int bitwidth, int channels) { unsigned int frddr_type = spdifout_get_frddr_type(bitwidth); - unsigned int offset, reg; + unsigned int offset, reg, i, chmask = 0; - pr_info("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits\n", + for (i = 0; i < channels; i++) + chmask |= (1 << i); + + pr_debug("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits\n", (spdif_id == 0) ? "a":"b", fifo_id, frddr_type, @@ -419,7 +423,7 @@ void spdifout_fifo_ctrl(int spdif_id, int fifo_id, int bitwidth) reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * spdif_id; audiobus_update_bits(reg, 0x3<<21|0x1<<20|0x1<<19|0xff<<4, - 0x0<<21|0<<20|0<<19|0x3<<4); + 0x0<<21|0<<20|0<<19|chmask<<4); offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1; reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * spdif_id; @@ -454,7 +458,7 @@ void spdifout_enable(int spdif_id, bool is_enable) { unsigned int offset, reg; - pr_info("spdif_%s is set to %s\n", + pr_debug("spdif_%s is set to %s\n", (spdif_id == 0) ? "a":"b", is_enable ? "enable":"disable"); @@ -471,7 +475,7 @@ void spdifout_enable(int spdif_id, bool is_enable) } void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, bool is_enable) + int bitwidth, int channels, bool is_enable) { int spdif_id; @@ -485,7 +489,7 @@ void spdifout_samesource_set(int spdif_index, int fifo_id, spdifout_clk_ctrl(spdif_id, /*is_enable*/true); if (is_enable) - spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth); + spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth, channels); } int spdifin_get_sample_rate(void) @@ -528,6 +532,11 @@ int spdifin_get_audio_type(void) return (val >> 16) & 0xff; } +void spdifin_set_src(int src) +{ + audiobus_update_bits(EE_AUDIO_SPDIFIN_CTRL0, 0x3 << 4, src << 4); +} + void spdif_set_channel_status_info( struct iec958_chsts *chsts, int spdif_id) { @@ -589,7 +598,7 @@ void spdif_set_channel_status_info( void spdifout_play_with_zerodata(unsigned int spdif_id) { - pr_info("%s, spdif id:%d enable:%d\n", + pr_debug("%s, spdif id:%d enable:%d\n", __func__, spdif_id, spdifout_is_enable(spdif_id)); @@ -619,7 +628,8 @@ void spdifout_play_with_zerodata(unsigned int spdif_id) spdifout_to_hdmitx_ctrl(spdif_id); /* spdif ctrl */ - spdifout_fifo_ctrl(spdif_id, frddr_index, bitwidth); + spdifout_fifo_ctrl(spdif_id, + frddr_index, bitwidth, runtime.channels); /* channel status info */ spdif_get_channel_status_info(&chsts, sample_rate); @@ -638,7 +648,7 @@ void spdifout_play_with_zerodata(unsigned int spdif_id) void spdifout_play_with_zerodata_free(unsigned int spdif_id) { - pr_info("%s, spdif id:%d\n", + pr_debug("%s, spdif id:%d\n", __func__, spdif_id); diff --git a/sound/soc/amlogic/auge/spdif_hw.h b/sound/soc/amlogic/auge/spdif_hw.h index 51d5e0b52fff..3e133f620fba 100644 --- a/sound/soc/amlogic/auge/spdif_hw.h +++ b/sound/soc/amlogic/auge/spdif_hw.h @@ -74,7 +74,7 @@ extern void aml_spdifout_get_aed_info(int spdifout_id, extern void spdifout_to_hdmitx_ctrl(int spdif_index); extern void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, bool is_enable); + int bitwidth, int channels, bool is_enable); extern void spdifout_enable(int spdif_id, bool is_enable); extern int spdifin_get_sample_rate(void); @@ -88,4 +88,5 @@ extern void spdif_set_channel_status_info( extern void spdifout_play_with_zerodata(unsigned int spdif_id); extern void spdifout_play_with_zerodata_free(unsigned int spdif_id); +extern void spdifin_set_src(int src); #endif diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index fb3ef019b050..f227be4751dd 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -14,7 +14,7 @@ * more details. * */ - +#define DEBUG #include #include #include @@ -38,10 +38,11 @@ #include "ddr_mngr.h" #include "tdm_hw.h" +#include "sharebuffer.h" +#include "vad.h" /*#define __PTM_TDM_CLK__*/ -#include "sharebuffer.h" #define DRV_NAME "aml_tdm" @@ -55,22 +56,22 @@ static void dump_pcm_setting(struct pcm_setting *setting) if (setting == NULL) return; - pr_info("dump_pcm_setting(%p)\n", setting); - pr_info("\tpcm_mode(%d)\n", setting->pcm_mode); - pr_info("\tsysclk(%d)\n", setting->sysclk); - pr_info("\tsysclk_bclk_ratio(%d)\n", setting->sysclk_bclk_ratio); - pr_info("\tbclk(%d)\n", setting->bclk); - pr_info("\tbclk_lrclk_ratio(%d)\n", setting->bclk_lrclk_ratio); - pr_info("\tlrclk(%d)\n", setting->lrclk); - pr_info("\ttx_mask(%#x)\n", setting->tx_mask); - pr_info("\trx_mask(%#x)\n", setting->rx_mask); - pr_info("\tslots(%d)\n", setting->slots); - pr_info("\tslot_width(%d)\n", setting->slot_width); - pr_info("\tlane_mask_in(%#x)\n", setting->lane_mask_in); - pr_info("\tlane_mask_out(%#x)\n", setting->lane_mask_out); - pr_info("\tlane_oe_mask_in(%#x)\n", setting->lane_oe_mask_in); - pr_info("\tlane_oe_mask_out(%#x)\n", setting->lane_oe_mask_out); - pr_info("\tlane_lb_mask_in(%#x)\n", setting->lane_lb_mask_in); + pr_debug("dump_pcm_setting(%p)\n", setting); + pr_debug("\tpcm_mode(%d)\n", setting->pcm_mode); + pr_debug("\tsysclk(%d)\n", setting->sysclk); + pr_debug("\tsysclk_bclk_ratio(%d)\n", setting->sysclk_bclk_ratio); + pr_debug("\tbclk(%d)\n", setting->bclk); + pr_debug("\tbclk_lrclk_ratio(%d)\n", setting->bclk_lrclk_ratio); + pr_debug("\tlrclk(%d)\n", setting->lrclk); + pr_debug("\ttx_mask(%#x)\n", setting->tx_mask); + pr_debug("\trx_mask(%#x)\n", setting->rx_mask); + pr_debug("\tslots(%d)\n", setting->slots); + pr_debug("\tslot_width(%d)\n", setting->slot_width); + pr_debug("\tlane_mask_in(%#x)\n", setting->lane_mask_in); + pr_debug("\tlane_mask_out(%#x)\n", setting->lane_mask_out); + pr_debug("\tlane_oe_mask_in(%#x)\n", setting->lane_oe_mask_in); + pr_debug("\tlane_oe_mask_out(%#x)\n", setting->lane_oe_mask_out); + pr_debug("\tlane_lb_mask_in(%#x)\n", setting->lane_lb_mask_in); } struct tdm_chipinfo { @@ -115,6 +116,9 @@ struct aml_tdm { /* virtual link for i2s to hdmitx */ int i2s2hdmitx; int acodec_adc; + uint last_mpll_freq; + uint last_mclk_freq; + uint last_fmt; }; static const struct snd_pcm_hardware aml_tdm_hardware = { @@ -367,33 +371,6 @@ struct snd_soc_platform_driver aml_tdm_platform = { .pcm_new = aml_tdm_new, }; -static int aml_dai_tdm_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); - int ret; - - ret = clk_prepare_enable(p_tdm->mclk); - if (ret) { - pr_err("Can't enable mclk: %d\n", ret); - goto err; - } - - return ret; -err: - pr_err("failed enable clock\n"); - return ret; -} - -static void aml_dai_tdm_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); - - /* disable clock and gate */ - clk_disable_unprepare(p_tdm->mclk); -} - static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { @@ -403,7 +380,6 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, bit_depth = snd_pcm_format_width(runtime->format); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { struct frddr *fr = p_tdm->fddr; enum frddr_dest dst; @@ -448,7 +424,9 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, p_tdm->id); return -EINVAL; } - aml_frddr_set_format(fr, bit_depth - 1, + aml_frddr_set_format(fr, + runtime->channels, + bit_depth - 1, tdmout_get_frddr_type(bit_depth)); aml_frddr_select_dst(fr, dst); aml_frddr_set_fifos(fr, 0x40, 0x20); @@ -459,6 +437,10 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, unsigned int toddr_type; struct toddr_fmt fmt; + if (vad_tdm_is_running(p_tdm->id) + && pm_audio_is_suspend()) + return 0; + switch (bit_depth) { case 8: case 16: @@ -542,6 +524,16 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + + if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) + && vad_tdm_is_running(p_tdm->id) + && pm_audio_is_suspend()) { + pm_audio_set_suspend(false); + /* VAD switch to alsa buffer */ + vad_update_buffer(0); + break; + } + /* reset fifo here. * If not, xrun will cause channel mapping mismatch */ @@ -561,6 +553,14 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) + && vad_tdm_is_running(p_tdm->id) + && pm_audio_is_suspend()) { + /* switch to VAD buffer */ + vad_update_buffer(1); + break; + } + aml_tdm_enable(p_tdm->actrl, substream->stream, p_tdm->id, false); @@ -727,6 +727,11 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream, return ret; } + /* Must enabe channel number for VAD */ + if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) + && (vad_tdm_is_running(p_tdm->id))) + tdmin_set_chnum_en(p_tdm->actrl, p_tdm->id, true); + /* share buffer trigger */ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) && p_tdm->chipinfo @@ -744,6 +749,15 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream, rate * ratio * mux); } + if (!p_tdm->contns_clk && !IS_ERR(p_tdm->mclk)) { + pr_debug("%s(), enable mclk for %s", __func__, cpu_dai->name); + ret = clk_prepare_enable(p_tdm->mclk); + if (ret) { + pr_err("Can't enable mclk: %d\n", ret); + return ret; + } + } + return 0; } @@ -758,6 +772,11 @@ static int aml_dai_tdm_hw_free(struct snd_pcm_substream *substream, aml_tdm_set_channel_mask(p_tdm->actrl, substream->stream, p_tdm->id, i, 0); + /* Disable channel number for VAD */ + if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) + && (vad_tdm_is_running(p_tdm->id))) + tdmin_set_chnum_en(p_tdm->actrl, p_tdm->id, false); + /* share buffer free */ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) && p_tdm->chipinfo @@ -769,6 +788,12 @@ static int aml_dai_tdm_hw_free(struct snd_pcm_substream *substream, fr, p_tdm->samesource_sel); } + /* disable clock and gate */ + if (!p_tdm->contns_clk && !IS_ERR(p_tdm->mclk)) { + pr_info("%s(), disable mclk for %s", __func__, cpu_dai->name); + clk_disable_unprepare(p_tdm->mclk); + } + return 0; } @@ -776,8 +801,14 @@ static int aml_dai_set_tdm_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); - pr_info("asoc aml_dai_set_tdm_fmt, %#x, %p, id(%d), clksel(%d)\n", + pr_debug("asoc aml_dai_set_tdm_fmt, %#x, %p, id(%d), clksel(%d)\n", fmt, p_tdm, p_tdm->id, p_tdm->clk_sel); + if (p_tdm->last_fmt == fmt) { + pr_debug("%s(), fmt not change\n", __func__); + goto capture; + } else + p_tdm->last_fmt = fmt; + switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) { case SND_SOC_DAIFMT_CONT: p_tdm->contns_clk = true; @@ -794,9 +825,9 @@ static int aml_dai_set_tdm_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) aml_tdm_set_format(p_tdm->actrl, &(p_tdm->setting), p_tdm->clk_sel, p_tdm->id, fmt, - cpu_dai->capture_active, - cpu_dai->playback_active); + 1, 1); +capture: /* update skew for ACODEC_ADC */ if (cpu_dai->capture_active && p_tdm->chipinfo @@ -832,6 +863,7 @@ static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai, { struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); unsigned int ratio = aml_mpll_mclk_ratio(freq); + unsigned int mpll_freq = 0; p_tdm->setting.sysclk = freq; @@ -844,10 +876,22 @@ static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai, ratio = 20; #endif - clk_set_rate(p_tdm->clk, freq * ratio); - clk_set_rate(p_tdm->mclk, freq); + mpll_freq = freq * ratio; + if (mpll_freq != p_tdm->last_mpll_freq) { + clk_set_rate(p_tdm->clk, mpll_freq); + p_tdm->last_mpll_freq = mpll_freq; + } else { + pr_debug("%s(), mpll no change, keep clk\n", __func__); + } - pr_info("set mclk:%d, mpll:%d, get mclk:%lu, mpll:%lu\n", + if (freq != p_tdm->last_mclk_freq) { + clk_set_rate(p_tdm->mclk, freq); + p_tdm->last_mclk_freq = freq; + } else { + pr_debug("%s(), mclk no change, keep clk\n", __func__); + } + + pr_debug("set mclk:%d, mpll:%d, get mclk:%lu, mpll:%lu\n", freq, freq * ratio, clk_get_rate(p_tdm->mclk), @@ -868,10 +912,10 @@ static int aml_dai_set_bclk_ratio(struct snd_soc_dai *cpu_dai, if (p_tdm->setting.pcm_mode == SND_SOC_DAIFMT_I2S || p_tdm->setting.pcm_mode == SND_SOC_DAIFMT_LEFT_J) { - pr_info("aml_dai_set_bclk_ratio, select I2S mode\n"); + pr_debug("aml_dai_set_bclk_ratio, select I2S mode\n"); lrclk_hi = bclk_ratio / 2; } else { - pr_info("aml_dai_set_bclk_ratio, select TDM mode\n"); + pr_debug("aml_dai_set_bclk_ratio, select TDM mode\n"); } aml_tdm_set_bclk_ratio(p_tdm->actrl, p_tdm->clk_sel, lrclk_hi, bclk_ratio); @@ -914,15 +958,15 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, lanes_oe_in_cnt = pop_count(p_tdm->setting.lane_oe_mask_in); lanes_lb_cnt = pop_count(p_tdm->setting.lane_lb_mask_in); - pr_info("%s(), txmask(%#x), rxmask(%#x)\n", + pr_debug("%s(), txmask(%#x), rxmask(%#x)\n", __func__, tx_mask, rx_mask); - pr_info("\tlanes_out_cnt(%d), lanes_in_cnt(%d)\n", + pr_debug("\tlanes_out_cnt(%d), lanes_in_cnt(%d)\n", lanes_out_cnt, lanes_in_cnt); - pr_info("\tlanes_oe_out_cnt(%d), lanes_oe_in_cnt(%d)\n", + pr_debug("\tlanes_oe_out_cnt(%d), lanes_oe_in_cnt(%d)\n", lanes_oe_out_cnt, lanes_oe_in_cnt); - pr_info("\tlanes_lb_cnt(%d)\n", + pr_debug("\tlanes_lb_cnt(%d)\n", lanes_lb_cnt); - pr_info("\tslots(%d), slot_width(%d)\n", + pr_debug("\tslots(%d), slot_width(%d)\n", slots, slot_width); p_tdm->setting.tx_mask = tx_mask; p_tdm->setting.rx_mask = rx_mask; @@ -971,7 +1015,7 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, } else { if (lanes_lb_cnt) in_src = p_tdm->id + 3; - if (lanes_in_cnt && lanes_in_cnt <= 3) + if (lanes_in_cnt && lanes_in_cnt <= 4) in_src = p_tdm->id; if (in_src > 5) { pr_err("unknown src(%d) for tdmin\n", in_src); @@ -1020,9 +1064,22 @@ static int aml_dai_tdm_remove(struct snd_soc_dai *cpu_dai) return 0; } +static int aml_dai_tdm_mute_stream(struct snd_soc_dai *cpu_dai, + int mute, int stream) +{ + struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + pr_debug("tdm playback mute: %d\n", mute); + aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, mute); + } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { + pr_debug("tdm capture mute: %d\n", mute); + aml_tdm_mute_capture(p_tdm->actrl, p_tdm->id, mute); + } + return 0; +} + static struct snd_soc_dai_ops aml_dai_tdm_ops = { - .startup = aml_dai_tdm_startup, - .shutdown = aml_dai_tdm_shutdown, .prepare = aml_dai_tdm_prepare, .trigger = aml_dai_tdm_trigger, .hw_params = aml_dai_tdm_hw_params, @@ -1032,6 +1089,7 @@ static struct snd_soc_dai_ops aml_dai_tdm_ops = { .set_bclk_ratio = aml_dai_set_bclk_ratio, .set_clkdiv = aml_dai_set_clkdiv, .set_tdm_slot = aml_dai_set_tdm_slot, + .mute_stream = aml_dai_tdm_mute_stream, }; #define AML_DAI_TDM_RATES (SNDRV_PCM_RATE_8000_384000) diff --git a/sound/soc/amlogic/auge/tdm_hw.c b/sound/soc/amlogic/auge/tdm_hw.c index c167b448480d..f8f89bc40264 100644 --- a/sound/soc/amlogic/auge/tdm_hw.c +++ b/sound/soc/amlogic/auge/tdm_hw.c @@ -188,6 +188,72 @@ void aml_tdm_fifo_ctrl( } +static void aml_clk_set_tdmout_by_id( + struct aml_audio_controller *actrl, + unsigned int tdm_index, + unsigned int sclk_sel, + unsigned int lrclk_sel, + bool sclk_ws_inv, + bool is_master, + bool binv) +{ + unsigned int val_sclk_ws_inv = 0; + unsigned int reg = EE_AUDIO_CLK_TDMOUT_A_CTRL + tdm_index; + + /* This is just a copy from previous setting. WHY??? */ + val_sclk_ws_inv = sclk_ws_inv && is_master; + if (val_sclk_ws_inv) + aml_audiobus_update_bits(actrl, reg, + 0x3<<30|1<<28|0xf<<24|0xf<<20, + 0x3<<30|val_sclk_ws_inv<<28| + sclk_sel<<24|lrclk_sel<<20); + else + aml_audiobus_update_bits(actrl, reg, + 0x3<<30|1<<29|0xf<<24|0xf<<20, + 0x3<<30|binv<<29| + sclk_sel<<24|lrclk_sel<<20); +} + +static void aml_clk_set_tdmin_by_id( + struct aml_audio_controller *actrl, + unsigned int tdm_index, + unsigned int sclk_sel, + unsigned int lrclk_sel) +{ + unsigned int reg = + EE_AUDIO_CLK_TDMIN_A_CTRL + tdm_index; + aml_audiobus_update_bits(actrl, + reg, + 0xff<<20, + sclk_sel<<24|lrclk_sel<<20); +} + +static void aml_tdmout_invert_lrclk( + struct aml_audio_controller *actrl, + unsigned int tdm_index, + bool finv) +{ + unsigned int off_set = + EE_AUDIO_TDMOUT_B_CTRL1 - EE_AUDIO_TDMOUT_A_CTRL1; + unsigned int reg_out = + EE_AUDIO_TDMOUT_A_CTRL1 + off_set * tdm_index; + aml_audiobus_update_bits(actrl, + reg_out, 0x1<<28, finv<<28); +} + +static void aml_tdmout_bclk_skew( + struct aml_audio_controller *actrl, + unsigned int tdm_index, + unsigned int bclkout_skew) +{ + unsigned int off_set = + EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0; + unsigned int reg_out = + EE_AUDIO_TDMOUT_A_CTRL0 + off_set * tdm_index; + aml_audiobus_update_bits(actrl, + reg_out, 0x1f<<15, bclkout_skew<<15); +} + void aml_tdm_set_format( struct aml_audio_controller *actrl, struct pcm_setting *p_config, @@ -223,24 +289,7 @@ void aml_tdm_set_format( default: return; } - - //TODO: clk tree - reg_out = EE_AUDIO_CLK_TDMOUT_A_CTRL + id; - reg_in = EE_AUDIO_CLK_TDMIN_A_CTRL + id; - aml_audiobus_update_bits(actrl, - reg_out, - 0xff<<20, - valb<<24|valf<<20); - aml_audiobus_update_bits(actrl, - reg_in, - 0xff<<20, - valb<<24|valf<<20); - - if (p_config->sclk_ws_inv) - aml_audiobus_update_bits(actrl, - reg_out, - 1 << 28, - 0 << 28); + aml_clk_set_tdmin_by_id(actrl, id, valb, valf); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: @@ -355,27 +404,11 @@ void aml_tdm_set_format( /* TDM out */ if (playback_active) { - - reg_out = EE_AUDIO_CLK_TDMOUT_A_CTRL + id; - aml_audiobus_update_bits(actrl, reg_out, - 0x3<<30, 0x3<<30); - - if (p_config->sclk_ws_inv && master_mode) - aml_audiobus_update_bits(actrl, reg_out, - 0x1 << 28, - 0x1 << 28); - else - aml_audiobus_update_bits(actrl, reg_out, - 0x1<<29, binv<<29); - - off_set = EE_AUDIO_TDMOUT_B_CTRL1 - EE_AUDIO_TDMOUT_A_CTRL1; - reg_out = EE_AUDIO_TDMOUT_A_CTRL1 + off_set * id; - aml_audiobus_update_bits(actrl, reg_out, 0x1<<28, finv<<28); - - off_set = EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0; - reg_out = EE_AUDIO_TDMOUT_A_CTRL0 + off_set * id; - aml_audiobus_update_bits(actrl, reg_out, - 0x1f<<15, bclkout_skew<<15); + aml_clk_set_tdmout_by_id(actrl, + id, valb, valf, + p_config->sclk_ws_inv, master_mode, binv); + aml_tdmout_invert_lrclk(actrl, id, finv); + aml_tdmout_bclk_skew(actrl, id, bclkout_skew); } /* TDM in */ @@ -492,6 +525,19 @@ void aml_update_tdmin_src( 0xf << 20, in_src << 20); } +void tdmin_set_chnum_en( + struct aml_audio_controller *actrl, + int index, bool enable) +{ + unsigned int reg, offset; + + offset = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; + reg = EE_AUDIO_TDMIN_A_CTRL + offset * index; + + aml_audiobus_update_bits(actrl, reg, + 0x1 << 6, enable << 6); +} + void aml_tdm_set_channel_mask( struct aml_audio_controller *actrl, int stream, int index, int lane, int mask) @@ -647,3 +693,44 @@ void i2s_to_hdmitx_ctrl(int tdm_index) | tdm_index << 4 /* Bclk_sel */ ); } + +void aml_tdm_mute_playback( + struct aml_audio_controller *actrl, + int tdm_index, + bool mute) +{ + unsigned int offset, reg; + unsigned int mute_mask = 0xffffffff; + unsigned int mute_val = 0; + int i = 0, lanes = 4; + + if (mute) + mute_val = 0xffffffff; + + offset = EE_AUDIO_TDMOUT_B_MUTE0 + - EE_AUDIO_TDMOUT_A_MUTE0; + reg = EE_AUDIO_TDMOUT_A_MUTE0 + offset * tdm_index; + for (i = 0; i < lanes; i++) + aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val); +} + +void aml_tdm_mute_capture( + struct aml_audio_controller *actrl, + int tdm_index, + bool mute) +{ + unsigned int offset, reg; + unsigned int mute_mask = 0xffffffff; + unsigned int mute_val = 0; + int i = 0, lanes = 4; + + if (mute) + mute_val = 0xffffffff; + + offset = EE_AUDIO_TDMIN_B_MUTE0 + - EE_AUDIO_TDMIN_A_MUTE0; + reg = EE_AUDIO_TDMIN_A_MUTE0 + offset * tdm_index; + for (i = 0; i < lanes; i++) + aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val); +} + diff --git a/sound/soc/amlogic/auge/tdm_hw.h b/sound/soc/amlogic/auge/tdm_hw.h index 7e47302aba75..85fe6303434f 100644 --- a/sound/soc/amlogic/auge/tdm_hw.h +++ b/sound/soc/amlogic/auge/tdm_hw.h @@ -107,6 +107,10 @@ extern void aml_update_tdmin_src( struct aml_audio_controller *actrl, int index, int in_src); +extern void tdmin_set_chnum_en( + struct aml_audio_controller *actrl, + int index, bool enable); + extern void aml_tdm_set_channel_mask( struct aml_audio_controller *actrl, int stream, int index, int lanes, int mask); @@ -138,4 +142,12 @@ extern void aml_tdm_clk_pad_select( int tdm_index, int clk_sel); extern void i2s_to_hdmitx_ctrl(int tdm_index); +void aml_tdm_mute_playback( + struct aml_audio_controller *actrl, + int index, + bool mute); +void aml_tdm_mute_capture( + struct aml_audio_controller *actrl, + int tdm_index, + bool mute); #endif diff --git a/sound/soc/amlogic/auge/vad.c b/sound/soc/amlogic/auge/vad.c new file mode 100644 index 000000000000..6738fdf63b97 --- /dev/null +++ b/sound/soc/amlogic/auge/vad.c @@ -0,0 +1,786 @@ +/* + * sound/soc/amlogic/auge/vad.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#define DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "vad_hw_coeff.c" +#include "vad_hw.h" +#include "vad.h" + +#define DRV_NAME "VAD" + +#define DMA_BUFFER_BYTES_MAX (2 * 1024 * 1024) + +enum vad_level { + LEVEL_USER, + LEVEL_KERNEL, +}; + +struct vad { + struct aml_audio_controller *actrl; + struct device *dev; + + struct clk *gate; + struct clk *pll; + struct clk *clk; + + struct toddr *tddr; + + struct tasklet_struct tasklet; + + struct snd_dma_buffer dma_buffer; + unsigned int start_last; + unsigned int end_last; + unsigned int addr; + + int switch_buffer; + + /* vad flag interrupt */ + int irq_wakeup; + /* frame sync interrupt */ + int irq_fs; + /* data source select + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + int src; + /* Enable */ + int en; + + /* user space or kernel space to check hot word + * 1: check hot word in kernel + * 0: check hot word in user space + */ + enum vad_level level; +}; + +static struct vad *s_vad; + +static struct vad *get_vad(void) +{ + struct vad *p_vad; + + p_vad = s_vad; + + if (!p_vad) { + pr_debug("Not init vad\n"); + return NULL; + } + + return p_vad; +} + +static bool vad_is_enable(void) +{ + struct vad *p_vad = get_vad(); + + if (!p_vad) + return false; + + return p_vad->en; +} + +static bool vad_src_check(enum vad_src src) +{ + struct vad *p_vad = get_vad(); + + if (!p_vad) + return false; + + if (p_vad->src == src) + return true; + + return false; +} + +bool vad_tdm_is_running(int tdm_idx) +{ + enum vad_src src; + + if (tdm_idx > 2) + return false; + + src = (enum vad_src)tdm_idx; + + if (vad_is_enable() && vad_src_check(src)) + return true; + + return false; +} + +bool vad_pdm_is_running(void) +{ + if (vad_is_enable() && vad_src_check(VAD_SRC_PDMIN)) + return true; + + return false; +} + +static void vad_notify_user_space(struct device *dev) +{ + pr_info("Notify to wake up user space\n"); + + pm_wakeup_event(dev, 2000); +} + +static int vad_engine_check(void) +{ + return 1; +} + +/* Check buffer in kernel for VAD */ +static void vad_transfer_buffer_output(struct vad *p_vad) +{ + + for (;;) { + if (vad_engine_check()) { + vad_notify_user_space(p_vad->dev); + break; + } + } +} + +static void vad_tasklet(unsigned long data) +{ + struct vad *p_vad = (struct vad *)data; + + vad_transfer_buffer_output(p_vad); +} + +static irqreturn_t vad_wakeup_isr(int irq, void *data) +{ + struct vad *p_vad = (struct vad *)data; + + pr_info("%s\n", __func__); + + if (p_vad->level == LEVEL_KERNEL) + tasklet_schedule(&p_vad->tasklet); + + return IRQ_HANDLED; +} + +static irqreturn_t vad_fs_isr(int irq, void *data) +{ + return IRQ_HANDLED; +} + +static int vad_set_clks(struct vad *p_vad, bool enable) +{ + if (enable) { + int ret = 0; + + /* enable clock gate */ + ret = clk_prepare_enable(p_vad->gate); + + /* enable clock */ + ret = clk_prepare_enable(p_vad->pll); + if (ret) { + pr_err("Can't enable vad pll: %d\n", ret); + return -EINVAL; + } + + clk_set_rate(p_vad->clk, 25000000); + ret = clk_prepare_enable(p_vad->clk); + if (ret) { + pr_err("Can't enable vad clk: %d\n", ret); + return -EINVAL; + } + } else { + /* disable clock and gate */ + clk_disable_unprepare(p_vad->clk); + clk_disable_unprepare(p_vad->pll); + clk_disable_unprepare(p_vad->gate); + } + + return 0; +} + +static int vad_init(struct vad *p_vad) +{ + int ret = 0, flag = 0; + + /* malloc buffer */ + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, + p_vad->dev, + DMA_BUFFER_BYTES_MAX, + &p_vad->dma_buffer); + if (ret) { + dev_err(p_vad->dev, "Cannot allocate buffer(s)\n"); + return ret; + } + + /* register irq */ + if (p_vad->level == LEVEL_KERNEL) { + flag = IRQF_SHARED | IRQF_NO_SUSPEND; + + tasklet_init(&p_vad->tasklet, vad_tasklet, + (unsigned long)p_vad); + + } else if (p_vad->level == LEVEL_USER) + flag = IRQF_SHARED; + + ret = request_irq(p_vad->irq_wakeup, + vad_wakeup_isr, flag, "vad_wakeup", + p_vad); + if (ret) { + dev_err(p_vad->dev, "failed to claim irq_wakeup %u\n", + p_vad->irq_wakeup); + return -ENXIO; + } + + ret = request_irq(p_vad->irq_fs, + vad_fs_isr, 0, "vad_fs", + p_vad); + if (ret) { + dev_err(p_vad->dev, "failed to claim irq_fs %u\n", + p_vad->irq_fs); + return -ENXIO; + } + + /* clock ready */ + vad_set_clks(p_vad, true); + + return ret; +} + +static void vad_deinit(struct vad *p_vad) +{ + if (p_vad->level == LEVEL_KERNEL) + tasklet_kill(&p_vad->tasklet); + + /* free irq */ + free_irq(p_vad->irq_wakeup, p_vad); + free_irq(p_vad->irq_fs, p_vad); + + /* free buffer */ + snd_dma_free_pages(&p_vad->dma_buffer); + + /* clock disabled */ + vad_set_clks(p_vad, false); +} + +void vad_update_buffer(int isvad) +{ + struct vad *p_vad = get_vad(); + unsigned int start, end, addr; + unsigned int rd_th; + + if (!p_vad || !p_vad->en || !p_vad->tddr) + return; + + addr = aml_toddr_get_position(p_vad->tddr); + + if (isvad) { /* switch to vad buffer */ + struct toddr *tddr = p_vad->tddr; + + p_vad->start_last = tddr->start_addr; + p_vad->end_last = tddr->end_addr; + + rd_th = 0x100; + + pr_debug("Switch to VAD buffer\n"); + pr_debug("\t ASAL start:%d, end:%d, bytes:%d, current:%d\n", + tddr->start_addr, tddr->end_addr, + tddr->end_addr - tddr->start_addr, addr); + + start = p_vad->dma_buffer.addr; + end = start + p_vad->dma_buffer.bytes - 8; + + pr_debug("\t VAD start:%d, end:%d, bytes:%d\n", + start, end, + end - start); + } else { + pr_debug("Switch to ALSA buffer\n"); + + //addr = aml_toddr_get_addr(p_vad->tddr, VAD_WAKEUP_ADDR); + addr = aml_toddr_get_position(p_vad->tddr); + + start = p_vad->start_last; + end = p_vad->end_last; + + rd_th = 0x40; + + vad_set_trunk_data_readable(true); + } + + p_vad->addr = addr; + aml_toddr_set_buf(p_vad->tddr, start, end); + aml_toddr_force_finish(p_vad->tddr); + aml_toddr_update_fifos_rd_th(p_vad->tddr, rd_th); +} + +int vad_transfer_chunk_data(unsigned long data, int frames) +{ + struct vad *p_vad = get_vad(); + char __user *buf = (char __user *)data; + unsigned char *hwbuf; + int bytes; + int start, end, addr, size; + int chnum, bytes_per_sample; + + if (!buf || !p_vad || !p_vad->en || !p_vad->tddr) + return 0; + + size = p_vad->dma_buffer.bytes; + start = p_vad->dma_buffer.addr; + end = start + size - 8; + addr = p_vad->addr; + hwbuf = p_vad->dma_buffer.area; + + if (addr < start || addr > end) + return 0; + + chnum = p_vad->tddr->channels; + /* bytes for each sample */ + bytes_per_sample = p_vad->tddr->bitdepth >> 3; + + bytes = frames * chnum * bytes_per_sample < size ? + frames * chnum * bytes_per_sample : size; + + pr_debug("%s dma bytes:%d, wanted bytes:%d, actual bytes:%d\n", + __func__, + size, + frames * chnum * bytes_per_sample, + bytes); + + pr_debug("%s dma bytes:%d, start:%d, end:%d, current:%d\n", + __func__, + size, + start, + end, + addr); + + if (addr - start >= bytes) { + if (copy_to_user(buf, + hwbuf + addr - bytes - start, + bytes)) + return 0; + } else { + int tmp_bytes = bytes - (addr - start); + int tmp_offset = (end - tmp_bytes) - start; + + if (copy_to_user(buf, + hwbuf + tmp_offset, + tmp_bytes)) + return 0; + + if (copy_to_user(buf + tmp_bytes, + hwbuf, + addr - start)) + return 0; + } + + /* After data copied, reset dma buffer */ + memset(hwbuf, 0x0, size); + + return bytes / (chnum * bytes_per_sample); +} + +void vad_set_toddr_info(struct toddr *to) +{ + struct vad *p_vad = get_vad(); + + if (!p_vad || !p_vad->en) + return; + + pr_debug("%s update vad toddr:%p\n", __func__, to); + + p_vad->tddr = to; +} + +void vad_enable(bool enable) +{ + struct vad *p_vad = get_vad(); + + if (!p_vad || !p_vad->en) + return; + + /* Force VAD enable to set parameters */ + if (enable) { + int *p_de_coeff = vad_de_coeff; + int len_de = ARRAY_SIZE(vad_de_coeff); + int *p_win_coeff = vad_ram_coeff; + int len_ram = ARRAY_SIZE(vad_ram_coeff); + + vad_set_enable(true); + vad_set_ram_coeff(len_ram, p_win_coeff); + vad_set_de_params(len_de, p_de_coeff); + vad_set_pwd(); + vad_set_cep(); + vad_set_src(p_vad->src); + vad_set_in(); + + /* reset then enable VAD */ + vad_set_enable(false); + } + vad_set_enable(enable); +} + +static int vad_get_enable_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct vad *p_vad = snd_kcontrol_chip(kcontrol); + + if (!p_vad) { + pr_debug("VAD is not inited\n"); + return 0; + } + + ucontrol->value.integer.value[0] = p_vad->en; + + return 0; +} + +static int vad_set_enable_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct vad *p_vad = snd_kcontrol_chip(kcontrol); + + if (!p_vad) { + pr_debug("VAD is not inited\n"); + return 0; + } + + p_vad->en = ucontrol->value.integer.value[0]; + + if (p_vad->en) { + vad_init(p_vad); + + aml_set_vad(p_vad->en, p_vad->src); + } else { + aml_set_vad(p_vad->en, p_vad->src); + + vad_deinit(p_vad); + } + + return 0; +} + + +static const char *const vad_src_txt[] = { + "TDMIN_A", + "TDMIN_B", + "TDMIN_C", + "SPDIFIN", + "PDMIN", + "LOOPBACK_B", + "TDMIN_LB", + "LOOPBACK_A", +}; + +const struct soc_enum vad_src_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(vad_src_txt), + vad_src_txt); + +static int vad_get_src_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct vad *p_vad = snd_kcontrol_chip(kcontrol); + + if (!p_vad) { + pr_debug("VAD is not inited\n"); + return 0; + } + + ucontrol->value.integer.value[0] = p_vad->src; + + return 0; +} + +static int vad_set_src_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct vad *p_vad = snd_kcontrol_chip(kcontrol); + + if (!p_vad) { + pr_debug("VAD is not inited\n"); + return 0; + } + + p_vad->src = ucontrol->value.integer.value[0]; + + if (p_vad->en) + aml_set_vad(p_vad->en, p_vad->src); + + return 0; +} + +static int vad_get_switch_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct vad *p_vad = snd_kcontrol_chip(kcontrol); + + if (!p_vad) { + pr_debug("VAD is not inited\n"); + return 0; + } + + ucontrol->value.integer.value[0] = p_vad->switch_buffer; + + return 0; +} + +static int vad_set_switch_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct vad *p_vad = snd_kcontrol_chip(kcontrol); + + if (!p_vad) { + pr_debug("VAD is not inited\n"); + return 0; + } + + p_vad->switch_buffer = ucontrol->value.integer.value[0]; + + if (p_vad->en) + vad_update_buffer(p_vad->switch_buffer); + + return 0; +} + +static const struct snd_kcontrol_new vad_controls[] = { + SOC_SINGLE_BOOL_EXT("VAD enable", + 0, + vad_get_enable_enum, + vad_set_enable_enum), + + SOC_ENUM_EXT("VAD Source sel", + vad_src_enum, + vad_get_src_enum, + vad_set_src_enum), + + SOC_SINGLE_BOOL_EXT("VAD Switch", + 0, + vad_get_switch_enum, + vad_set_switch_enum), + +}; + +int card_add_vad_kcontrols(struct snd_soc_card *card) +{ + unsigned int idx; + int err; + + struct vad *p_vad = get_vad(); + + if (!p_vad) + return -ENODEV; + + for (idx = 0; idx < ARRAY_SIZE(vad_controls); idx++) { + err = snd_ctl_add(card->snd_card, + snd_ctl_new1(&vad_controls[idx], + p_vad)); + if (err < 0) + return err; + } + + return 0; +} + +static const struct of_device_id vad_device_id[] = { + { + .compatible = "amlogic, snd-vad", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, vad_device_id); + +static int vad_platform_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct device_node *node_prt = NULL; + struct platform_device *pdev_parent; + struct device *dev = &pdev->dev; + struct aml_audio_controller *actrl = NULL; + struct vad *p_vad = NULL; + int ret = 0; + + p_vad = devm_kzalloc(&pdev->dev, sizeof(struct vad), GFP_KERNEL); + if (!p_vad) + return -ENOMEM; + + p_vad->dev = dev; + dev_set_drvdata(dev, p_vad); + + /* get audio controller */ + node_prt = of_get_parent(node); + if (node_prt == NULL) + return -ENXIO; + + pdev_parent = of_find_device_by_node(node_prt); + of_node_put(node_prt); + actrl = (struct aml_audio_controller *) + platform_get_drvdata(pdev_parent); + p_vad->actrl = actrl; + + /* clock */ + p_vad->gate = devm_clk_get(&pdev->dev, "gate"); + if (IS_ERR(p_vad->gate)) { + dev_err(&pdev->dev, + "Can't get vad clock gate\n"); + return PTR_ERR(p_vad->gate); + } + p_vad->pll = devm_clk_get(&pdev->dev, "pll"); + if (IS_ERR(p_vad->pll)) { + dev_err(&pdev->dev, + "Can't retrieve vad pll clock\n"); + return PTR_ERR(p_vad->pll); + } + p_vad->clk = devm_clk_get(&pdev->dev, "clk"); + if (IS_ERR(p_vad->clk)) { + dev_err(&pdev->dev, + "Can't retrieve vad clock\n"); + return PTR_ERR(p_vad->clk); + } + ret = clk_set_parent(p_vad->clk, p_vad->pll); + if (ret) { + dev_err(&pdev->dev, + "Can't set p_vad->clk parent clock\n"); + return PTR_ERR(p_vad->clk); + } + + /* irqs */ + p_vad->irq_wakeup = platform_get_irq_byname(pdev, "irq_wakeup"); + if (p_vad->irq_wakeup < 0) { + dev_err(dev, "Failed to get irq_wakeup:%d\n", + p_vad->irq_wakeup); + return -ENXIO; + } + p_vad->irq_fs = platform_get_irq_byname(pdev, "irq_frame_sync"); + if (p_vad->irq_fs < 0) { + dev_err(dev, "Failed to get irq_frame_sync:%d\n", + p_vad->irq_fs); + return -ENXIO; + } + + /* data source select */ + ret = of_property_read_u32(node, "src", + &p_vad->src); + if (ret < 0) { + dev_err(dev, "Failed to get vad data src select:%d\n", + p_vad->src); + return -EINVAL; + } + /* to deal with hot word in user space or kernel space */ + ret = of_property_read_u32(node, "level", + &p_vad->level); + if (ret < 0) { + dev_info(dev, + "Failed to get vad level, default in user space\n"); + p_vad->level = 0; + } + + pr_info("%s vad data source sel:%d, level:%d\n", + __func__, + p_vad->src, + p_vad->level); + + s_vad = p_vad; + + device_init_wakeup(dev, 1); + + return 0; +} + +int vad_platform_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct device *dev = &pdev->dev; + struct vad *p_vad = dev_get_drvdata(dev); + + pr_info("%s\n", __func__); + + /* whether in freeze */ + if (is_pm_freeze_mode() + && vad_is_enable()) { + pr_info("%s, Entry in freeze\n", __func__); + + if (p_vad->level == LEVEL_USER) + dev_pm_set_wake_irq(dev, p_vad->irq_wakeup); + } + + return 0; +} + +int vad_platform_resume(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct vad *p_vad = dev_get_drvdata(dev); + + pr_info("%s\n", __func__); + + /* whether in freeze mode */ + if (is_pm_freeze_mode() + && vad_is_enable()) { + pr_info("%s, Exist from freeze\n", __func__); + + if (p_vad->level == LEVEL_USER) + dev_pm_clear_wake_irq(dev); + } + + return 0; +} + +struct platform_driver vad_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = vad_device_id, + }, + .probe = vad_platform_probe, + .suspend = vad_platform_suspend, + .resume = vad_platform_resume, +}; + +module_platform_driver(vad_driver); + +MODULE_AUTHOR("Amlogic, Inc."); +MODULE_DESCRIPTION("Amlogic Voice Activity Detection ASoc driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("Platform:" DRV_NAME); +MODULE_DEVICE_TABLE(of, vad_device_id); diff --git a/sound/soc/amlogic/auge/vad.h b/sound/soc/amlogic/auge/vad.h new file mode 100644 index 000000000000..cd094682eb15 --- /dev/null +++ b/sound/soc/amlogic/auge/vad.h @@ -0,0 +1,47 @@ +/* + * sound/soc/amlogic/auge/vad.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __VAD_H__ +#define __VAD_H__ + +#include "ddr_mngr.h" + +enum vad_src { + VAD_SRC_TDMIN_A, + VAD_SRC_TDMIN_B, + VAD_SRC_TDMIN_C, + VAD_SRC_SPDIFIN, + VAD_SRC_PDMIN, + VAD_SRC_LOOPBACK_B, + VAD_SRC_TDMIN_LB, + VAD_SRC_LOOPBACK_A, +}; + +extern void vad_update_buffer(int isvad); +extern int vad_transfer_chunk_data(unsigned long data, int frames); + +extern bool vad_tdm_is_running(int tdm_idx); +extern bool vad_pdm_is_running(void); + +extern void vad_enable(bool enable); +extern void vad_set_toddr_info(struct toddr *to); + +extern void vad_set_trunk_data_readable(bool en); + +extern int card_add_vad_kcontrols(struct snd_soc_card *card); + +#endif diff --git a/sound/soc/amlogic/auge/vad_dev.c b/sound/soc/amlogic/auge/vad_dev.c new file mode 100644 index 000000000000..9af68606481a --- /dev/null +++ b/sound/soc/amlogic/auge/vad_dev.c @@ -0,0 +1,175 @@ +/* + * sound/soc/amlogic/auge/vad_dev.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ +#define DEBUG + +#include +#include +#include +#include + +#include +#include + +#include + +#include "vad.h" + +#define DRV_NAME "vad" + +#define IOCTL_READI_SUSPENDED_FRAMES _IOR('Z', 0x0, struct snd_xferi) + +static bool readable; + +bool vad_is_trunk_data_readable(void) +{ + return readable; +} + +void vad_set_trunk_data_readable(bool en) +{ + readable = en; +} + +static ssize_t readable_show(struct class *cla, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", readable); +} + +static struct class_attribute vad_attrs[] = { + __ATTR_RO(readable), + + __ATTR_NULL +}; + +static struct class vad_class = { + .name = DRV_NAME, + .class_attrs = vad_attrs, +}; + +static int vad_open(struct inode *inode, struct file *file) +{ + pr_info("%s\n", __func__); + + return 0; +} + +static long vad_unlocked_ioctl( + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + if (cmd == IOCTL_READI_SUSPENDED_FRAMES) { + struct snd_xferi xferi; + struct snd_xferi __user *_xferi = + (struct snd_xferi __user *)arg; + int result; + + if (!vad_is_trunk_data_readable()) + return 0; + + if (put_user(0, &_xferi->result)) + return 0; + if (copy_from_user(&xferi, _xferi, sizeof(xferi))) + return 0; + + result = vad_transfer_chunk_data( + (unsigned long)xferi.buf, + xferi.frames); + + __put_user(result, &_xferi->result); + + pr_debug("VAD resume trunk data, frames:%lu, result:%d\n", + xferi.frames, + result); + + /* if audio data is read, waiting for next time */ + vad_set_trunk_data_readable(false); + + return result; + } + + return -ENOTTY; +} + + +#ifdef CONFIG_COMPAT +static long vad_ioctl_compat( + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + pr_info("%s\n", __func__); + return -ENOIOCTLCMD; +} +#else +#define vad_ioctl_compat NULL +#endif + +static const struct file_operations vad_fops = { + .owner = THIS_MODULE, + .open = vad_open, + .unlocked_ioctl = vad_unlocked_ioctl, + .compat_ioctl = vad_ioctl_compat, +}; + +static int __init vad_init(void) +{ + struct device *vad_dev; + struct class *p_vad_class; + int ret = 0; + + ret = register_chrdev(VAD_MAJOR, DRV_NAME, &vad_fops); + if (ret) { + pr_err("Can't register char devie for " DRV_NAME "\n"); + goto err0; + } + + ret = class_register(&vad_class); + if (ret < 0) { + pr_err("Create vad class failed\n"); + ret = -EEXIST; + goto err1; + } + + p_vad_class = &vad_class; + vad_dev = device_create(p_vad_class, + NULL, MKDEV(VAD_MAJOR, 0), + NULL, DRV_NAME); + if (vad_dev == NULL) { + ret = -EEXIST; + goto err2; + } + + pr_info("Register %s", DRV_NAME); + + return 0; +err2: + class_destroy(p_vad_class); +err1: + unregister_chrdev(VAD_MAJOR, DRV_NAME); +err0: + return ret; +} + +static void __exit vad_exit(void) +{ + unregister_chrdev(VAD_MAJOR, DRV_NAME); +} + +module_init(vad_init); +module_exit(vad_exit); diff --git a/sound/soc/amlogic/auge/vad_hw.c b/sound/soc/amlogic/auge/vad_hw.c new file mode 100644 index 000000000000..c122dd074b39 --- /dev/null +++ b/sound/soc/amlogic/auge/vad_hw.c @@ -0,0 +1,109 @@ +/* + * sound/soc/amlogic/auge/vad_hw.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "vad_hw.h" + + +void vad_set_ram_coeff(int len, int *params) +{ + int i, ctrl_v; + + for (i = 0; i < len; i++) { + ctrl_v = 0x1 << 31 | (i << 0); + vad_write(VAD_LUT_WR, params[i]); + vad_write(VAD_LUT_CTRL, ctrl_v); + } +} + +/* parameters for downsample and emphasis filter */ +void vad_set_de_params(int len, int *params) +{ + int i; + + for (i = 0; i < len; i++) + vad_write(VAD_FIR_CTRL + i, params[i]); +} + +/* Power detection */ +void vad_set_pwd(void) +{ + /* frame for 32 ms */ + vad_write(VAD_FRAME_CTRL0, + 0x2 << 30 | + 0x1 << 24 | + 0x1 << 16); + + vad_write(VAD_FRAME_CTRL1, 0x00000d65); + vad_write(VAD_FRAME_CTRL2, 0xd00103ff); +} + +void vad_set_cep(void) +{ + vad_write(VAD_CEP_CTRL0, 0x11050000); + vad_write(VAD_CEP_CTRL1, 0x0000001b); + vad_write(VAD_CEP_CTRL2, 0xc001fd); + vad_write(VAD_CEP_CTRL3, 0x137f0000); + vad_write(VAD_CEP_CTRL4, 0x186d0000); + vad_write(VAD_CEP_CTRL5, 0xfd00f61); + vad_write(VAD_DEC_CTRL, 0x10030001); +} + +void vad_set_src(int src) +{ + audiobus_update_bits(EE_AUDIO_TOVAD_CTRL0, + 0x7 << 12, + src << 12); +} + +void vad_set_in(void) +{ + /* two channel enable */ + vad_write(VAD_IN_SEL0, 0x00000001); + vad_write(VAD_IN_SEL1, 0x00000002); + + vad_write(VAD_TO_DDR, 0xa0000719); +} + +void vad_set_enable(bool enable) +{ + audiobus_update_bits(EE_AUDIO_TOVAD_CTRL0, + 0x1 << 31 | 0x1 << 30, + enable << 31 | 0x1 << 30); + + if (enable) { + vad_write(VAD_TOP_CTRL0, 0x7ff); + vad_write(VAD_TOP_CTRL0, 0x0); + + vad_write(VAD_TOP_CTRL1, 0xff); + vad_write(VAD_TOP_CTRL1, 0x0); + + vad_update_bits(VAD_TOP_CTRL0, + 0xfff << 20, + 1 << 31 | /* vad_en */ + 1 << 30 | /* dec_fir_en */ + 1 << 29 | /* pre_emp_en */ + 1 << 28 | /* pre_ram_en */ + 1 << 27 | /* frame_his_en */ + 1 << 23 | /* ceps_ceps_en */ + 1 << 22 | /* ceps_spec_en */ + 0 << 20 /* two_channel_en */ + ); + } else { + vad_write(VAD_TOP_CTRL0, 0x0); + + vad_write(VAD_TOP_CTRL1, 0x0); + } +} diff --git a/sound/soc/amlogic/auge/vad_hw.h b/sound/soc/amlogic/auge/vad_hw.h new file mode 100644 index 000000000000..44a1224aeabc --- /dev/null +++ b/sound/soc/amlogic/auge/vad_hw.h @@ -0,0 +1,38 @@ +/* + * sound/soc/amlogic/auge/vad_hw.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ +#ifndef __VAD_HW_H__ +#define __VAD_HW_H__ +#include + +#include "regs.h" +#include "iomap.h" + +extern void vad_set_ram_coeff(int len, int *params); + + +extern void vad_set_de_params(int len, int *params); + +extern void vad_set_pwd(void); + +extern void vad_set_cep(void); + +extern void vad_set_src(int src); + +extern void vad_set_in(void); + +extern void vad_set_enable(bool enable); +#endif diff --git a/sound/soc/amlogic/auge/vad_hw_coeff.c b/sound/soc/amlogic/auge/vad_hw_coeff.c new file mode 100644 index 000000000000..e521b9883375 --- /dev/null +++ b/sound/soc/amlogic/auge/vad_hw_coeff.c @@ -0,0 +1,167 @@ +/* + * sound/soc/amlogic/auge/vad_hw_coeff.c + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/* parameters for downsample and emphasis filter */ +static int vad_de_coeff[] = { + 0x31007f05, + 0x000003e6, + 0x0000070c, + 0x0716071a, + 0x071207fa, + 0x07d407b1, + 0x07a907d0, + 0x0728064c, + 0x06750671, + 0x075906b1, + 0x059404b4, + 0x04be0785, + 0x044c0361, + 0x024d0263, + 0x026a0000, +}; + +static int vad_ram_coeff[] = { + 0x00003A3D, + 0x00003A42, + 0x00003A50, + 0x00003A67, + 0x00003A87, + 0x00003AB0, + 0x00003AE2, + 0x00003B1D, + 0x00003B61, + 0x00003BAF, + 0x00003C05, + 0x00003C64, + 0x00003CCC, + 0x00003D3C, + 0x00003DB5, + 0x00003E37, + 0x00003EC2, + 0x00003F55, + 0x00003FF0, + 0x0000284A, + 0x0000289F, + 0x000028F9, + 0x00002957, + 0x000029B9, + 0x00002A1F, + 0x00002A88, + 0x00002AF5, + 0x00002B66, + 0x00002BDA, + 0x00002C52, + 0x00002CCE, + 0x00002D4D, + 0x00002DCF, + 0x00002E54, + 0x00002EDC, + 0x00002F68, + 0x00002FF6, + 0x00001844, + 0x0000188E, + 0x000018D9, + 0x00001926, + 0x00001974, + 0x000019C3, + 0x00001A14, + 0x00001A65, + 0x00001AB8, + 0x00001B0C, + 0x00001B60, + 0x00001BB6, + 0x00001C0C, + 0x00001C63, + 0x00001CBB, + 0x00001D14, + 0x00001D6D, + 0x00001DC7, + 0x00001E22, + 0x00001E7C, + 0x00001ED8, + 0x00001F34, + 0x00001F90, + 0x00001FEC, + 0x00000824, + 0x00000853, + 0x00000881, + 0x000008AF, + 0x000008DE, + 0x0000090C, + 0x0000093B, + 0x00000969, + 0x00000997, + 0x000009C5, + 0x000009F3, + 0x00000A20, + 0x00000A4E, + 0x00000A7B, + 0x00000AA7, + 0x00000AD4, + 0x00000B00, + 0x00000B2C, + 0x00000B57, + 0x00000B82, + 0x00000BAD, + 0x00000BD7, + 0x00000C00, + 0x00000C29, + 0x00000C52, + 0x00000C7A, + 0x00000CA1, + 0x00000CC8, + 0x00000CEE, + 0x00000D13, + 0x00000D38, + 0x00000D5C, + 0x00000D7F, + 0x00000DA2, + 0x00000DC3, + 0x00000DE4, + 0x00000E05, + 0x00000E24, + 0x00000E42, + 0x00000E60, + 0x00000E7C, + 0x00000E98, + 0x00000EB3, + 0x00000ECD, + 0x00000EE6, + 0x00000EFE, + 0x00000F15, + 0x00000F2B, + 0x00000F40, + 0x00000F54, + 0x00000F66, + 0x00000F78, + 0x00000F89, + 0x00000F99, + 0x00000FA7, + 0x00000FB5, + 0x00000FC1, + 0x00000FCD, + 0x00000FD7, + 0x00000FE0, + 0x00000FE8, + 0x00000FEF, + 0x00000FF4, + 0x00000FF9, + 0x00000FFC, + 0x00000FFF, + 0x00000FFF +}; + diff --git a/sound/soc/amlogic/common/spdif_info.c b/sound/soc/amlogic/common/spdif_info.c index c900c5fdb675..85bd5e2bb092 100644 --- a/sound/soc/amlogic/common/spdif_info.c +++ b/sound/soc/amlogic/common/spdif_info.c @@ -14,6 +14,7 @@ * more details. * */ +#define DEBUG #undef pr_fmt #define pr_fmt(fmt) "spdif_info: " fmt @@ -111,7 +112,7 @@ void spdif_get_channel_status_info( chsts->chstat1_r = 0xe00; } } - pr_info("rate: %d, channel status ch0_l:0x%x, ch0_r:0x%x, ch1_l:0x%x, ch1_r:0x%x\n", + pr_debug("rate: %d, channel status ch0_l:0x%x, ch0_r:0x%x, ch1_l:0x%x, ch1_r:0x%x\n", rate, chsts->chstat0_l, chsts->chstat0_r, diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 218ec12314d6..35a7a500f58f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -136,6 +136,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TAS571X if I2C select SND_SOC_TAS5720 if I2C select SND_SOC_TFA9879 if I2C + select SND_SOC_TAS5805 if I2C select SND_SOC_TLV320AIC23_I2C if I2C select SND_SOC_TLV320AIC23_SPI if SPI_MASTER select SND_SOC_TLV320AIC26 if SPI_MASTER @@ -812,6 +813,15 @@ config SND_SOC_TAS5720 Enable support for Texas Instruments TAS5720L/M high-efficiency mono Class-D audio power amplifiers. +config SND_SOC_TAS5805 + tristate "Texas Instruments TAS5805 amplifiers" + depends on I2C + help + Enable support for Texas Instruments TAS5805 + Class-D audio power amplifiers. + control by I2C + Select this if your TAS5805 is connected to I2C bus. + config SND_SOC_TFA9879 tristate "NXP Semiconductors TFA9879 amplifier" depends on I2C diff --git a/sound/soc/codecs/amlogic/Kconfig b/sound/soc/codecs/amlogic/Kconfig index ac0d8467953e..b4cd38258572 100644 --- a/sound/soc/codecs/amlogic/Kconfig +++ b/sound/soc/codecs/amlogic/Kconfig @@ -68,6 +68,17 @@ config AMLOGIC_SND_CODEC_PMU3 AML PMU3 codec, this codec is internal +config AMLOGIC_SND_SOC_TAS5805 + bool "Texas Instruments TAS5805 amplifier" + depends on AMLOGIC_SND_SOC_CODECS + depends on I2C + default n + help + Enable support for Texas Instruments TAS5805 CODEC. + Select this if your TAS5805 is connected via an I2C bus. + Enable support for Texas Instruments TAS5805 CODEC. + Select this if your TAS5805 is connected via an I2C bus. + config AMLOGIC_SND_CODEC_TXLX_ACODEC bool "Amlogic Audio txlx acodec" depends on AMLOGIC_SND_SOC_CODECS diff --git a/sound/soc/codecs/amlogic/Makefile b/sound/soc/codecs/amlogic/Makefile index 915e6461f554..e1fdb3b653d7 100644 --- a/sound/soc/codecs/amlogic/Makefile +++ b/sound/soc/codecs/amlogic/Makefile @@ -18,6 +18,7 @@ snd-soc-pcm186x-objs := pcm186x.o pcm186x-i2c.o pcm186x-spi.o snd-soc-ssm3515-objs := ssm3515.o snd-soc-ssm3525-objs := ssm3525.o snd-soc-ad82584f-objs := ad82584f.o +snd-soc-tas5805-objs := tas5805.o # Amlogic obj-$(CONFIG_AMLOGIC_SND_CODEC_DUMMY_CODEC) += snd-soc-dummy_codec.o @@ -39,3 +40,4 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_TAS575X) += tas575x.o obj-$(CONFIG_AMLOGIC_SND_SOC_ES7243) += es7243.o obj-$(CONFIG_AMLOGIC_SND_SOC_AD82584F) += ad82584f.o obj-$(CONFIG_AMLOGIC_SND_SOC_CS42528) += cs42528.o +obj-$(CONFIG_AMLOGIC_SND_SOC_TAS5805) += snd-soc-tas5805.o diff --git a/sound/soc/codecs/amlogic/ad82584f.c b/sound/soc/codecs/amlogic/ad82584f.c index b30cf815b38f..88fea3497960 100644 --- a/sound/soc/codecs/amlogic/ad82584f.c +++ b/sound/soc/codecs/amlogic/ad82584f.c @@ -36,12 +36,15 @@ static const DECLARE_TLV_DB_SCALE(mvol_tlv, -10300, 50, 1); static const DECLARE_TLV_DB_SCALE(chvol_tlv, -10300, 50, 1); static const struct snd_kcontrol_new ad82584f_snd_controls[] = { - SOC_SINGLE_TLV("Master Volume", MVOL, 0, + SOC_SINGLE_TLV("AMP Master Volume", MVOL, 0, 0xff, 1, mvol_tlv), - SOC_SINGLE_TLV("Ch1 Volume", C1VOL, 0, + SOC_SINGLE_TLV("AMP Ch1 Volume", C1VOL, 0, 0xff, 1, chvol_tlv), - SOC_SINGLE_TLV("Ch2 Volume", C2VOL, 0, + SOC_SINGLE_TLV("AMP Ch2 Volume", C2VOL, 0, 0xff, 1, chvol_tlv), + + SOC_SINGLE("AMP Ch1 Switch", MUTE, 5, 1, 1), + SOC_SINGLE("AMP Ch2 Switch", MUTE, 4, 1, 1), }; static int ad82584f_reg_init(struct snd_soc_codec *codec); @@ -52,7 +55,7 @@ static const struct reg_default ad82584f_reg_defaults[AD82584F_REGISTER_COUNT] = { {0x00, 0x00},//##State_Control_1 {0x01, 0x04},//##State_Control_2 - {0x02, 0x00},//##State_Control_3 + {0x02, 0x30},//##State_Control_3 {0x03, 0x4e},//##Master_volume_control {0x04, 0x00},//##Channel_1_volume_control {0x05, 0x00},//##Channel_2_volume_control @@ -190,7 +193,7 @@ struct reg_default ad82584f_reg_defaults[AD82584F_REGISTER_COUNT] = { static const int m_reg_tab[AD82584F_REGISTER_COUNT][2] = { {0x00, 0x00},//##State_Control_1 {0x01, 0x04},//##State_Control_2 - {0x02, 0x00},//##State_Control_3 + {0x02, 0x30},//##State_Control_3 {0x03, 0x4e},//##Master_volume_control {0x04, 0x00},//##Channel_1_volume_control {0x05, 0x00},//##Channel_2_volume_control @@ -591,6 +594,12 @@ struct ad82584f_priv { struct regmap *regmap; struct snd_soc_codec *codec; struct ad82584f_platform_data *pdata; + + unsigned char Ch1_vol; + unsigned char Ch2_vol; + unsigned char master_vol; + unsigned char mute_val; + #ifdef CONFIG_HAS_EARLYSUSPEND struct early_suspend early_suspend; #endif @@ -809,7 +818,7 @@ static int ad82584f_init(struct snd_soc_codec *codec) ad82584f_set_eq_drc(codec); /*unmute,default power-on is mute.*/ - snd_soc_write(codec, 0x02, 0x00); + /*snd_soc_write(codec, 0x02, 0x00);*/ return 0; } @@ -844,8 +853,16 @@ static int ad82584f_remove(struct snd_soc_codec *codec) #ifdef CONFIG_PM static int ad82584f_suspend(struct snd_soc_codec *codec) { + struct ad82584f_priv *ad82584f = snd_soc_codec_get_drvdata(codec); + dev_info(codec->dev, "ad82584f_suspend!\n"); + /* save volume */ + ad82584f->Ch1_vol = snd_soc_read(codec, C1VOL); + ad82584f->Ch2_vol = snd_soc_read(codec, C2VOL); + ad82584f->master_vol = snd_soc_read(codec, MVOL); + ad82584f->mute_val = snd_soc_read(codec, MUTE); + ad82584f_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; @@ -853,9 +870,17 @@ static int ad82584f_suspend(struct snd_soc_codec *codec) static int ad82584f_resume(struct snd_soc_codec *codec) { + struct ad82584f_priv *ad82584f = snd_soc_codec_get_drvdata(codec); + dev_info(codec->dev, "ad82584f_resume!\n"); ad82584f_init(codec); + + snd_soc_write(codec, C1VOL, ad82584f->Ch1_vol); + snd_soc_write(codec, C2VOL, ad82584f->Ch2_vol); + snd_soc_write(codec, MVOL, ad82584f->master_vol); + snd_soc_write(codec, MUTE, ad82584f->mute_val); + ad82584f_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/amlogic/ad82584f.h b/sound/soc/codecs/amlogic/ad82584f.h index f363938a84f2..fd149b8bbf0c 100644 --- a/sound/soc/codecs/amlogic/ad82584f.h +++ b/sound/soc/codecs/amlogic/ad82584f.h @@ -1,6 +1,7 @@ #ifndef _AD82584F_H #define _AD82584F_H +#define MUTE 0x02 #define MVOL 0x03 #define C1VOL 0x04 #define C2VOL 0x05 diff --git a/sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c b/sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c index d2673b244fe2..174babef5a71 100644 --- a/sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c +++ b/sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c @@ -129,7 +129,8 @@ static int aml_DAC_Gain_set_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); u32 reg_addr = ACODEC_1; u32 val = snd_soc_read(codec, reg_addr); @@ -177,7 +178,8 @@ static int aml_DAC2_Gain_set_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); u32 reg_addr = ACODEC_7; u32 val = snd_soc_read(codec, reg_addr); @@ -784,6 +786,12 @@ static int aml_tl1_acodec_probe(struct platform_device *pdev) pr_info("aml_tl1_acodec tdmout_index=%d\n", aml_acodec->tdmout_index); + of_property_read_u32( + pdev->dev.of_node, + "dat1_ch_sel", + &aml_acodec->dat1_ch_sel); + pr_info("aml_tl1_acodec dat1_ch_sel=%d\n", + aml_acodec->dat1_ch_sel); of_property_read_u32( pdev->dev.of_node, "tdmin_index", diff --git a/sound/soc/codecs/amlogic/tas5707.c b/sound/soc/codecs/amlogic/tas5707.c index 38c9d5d1c2e3..a8d765401baf 100644 --- a/sound/soc/codecs/amlogic/tas5707.c +++ b/sound/soc/codecs/amlogic/tas5707.c @@ -185,6 +185,7 @@ static const struct snd_kcontrol_new tas5707_snd_controls[] = { 0xff, 1, chvol_tlv), SOC_SINGLE("Ch1 Switch", DDX_SOFT_MUTE, 0, 1, 1), SOC_SINGLE("Ch2 Switch", DDX_SOFT_MUTE, 1, 1, 1), + SOC_SINGLE("Shutdown Switch", DDX_SYS_CTL_2, 6, 1, 1), SOC_SINGLE_RANGE("Fine Master Volume", DDX_CHANNEL3_VOL, 0, 0x80, 0x83, 0), SOC_SINGLE_BOOL_EXT("Set EQ Enable", 0, diff --git a/sound/soc/codecs/amlogic/tas5805.c b/sound/soc/codecs/amlogic/tas5805.c new file mode 100644 index 000000000000..36f11cf2c519 --- /dev/null +++ b/sound/soc/codecs/amlogic/tas5805.c @@ -0,0 +1,547 @@ +/* + * Driver for the TAS5805M Audio Amplifier + * + * Author: Andy Liu + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tas5805.h" + +#define TAS5805M_DRV_NAME "tas5805m" + +#define TAS5805M_RATES (SNDRV_PCM_RATE_8000 | \ + SNDRV_PCM_RATE_11025 | \ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) +#define TAS5805M_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define TAS5805M_REG_00 (0x00) +#define TAS5805M_REG_03 (0x03) +#define TAS5805M_REG_24 (0x24) +#define TAS5805M_REG_25 (0x25) +#define TAS5805M_REG_26 (0x26) +#define TAS5805M_REG_27 (0x27) +#define TAS5805M_REG_28 (0x28) +#define TAS5805M_REG_29 (0x29) +#define TAS5805M_REG_2A (0x2a) +#define TAS5805M_REG_2B (0x2b) +#define TAS5805M_REG_35 (0x35) +#define TAS5805M_REG_7F (0x7f) + +#define TAS5805M_PAGE_00 (0x00) +#define TAS5805M_PAGE_2A (0x2a) + +#define TAS5805M_BOOK_00 (0x00) +#define TAS5805M_BOOK_8C (0x8c) + +#define TAS5805M_VOLUME_MAX (158) +#define TAS5805M_VOLUME_MIN (0) + +const uint32_t tas5805m_volume[] = { + 0x0000001B, //0, -110dB + 0x0000001E, //1, -109dB + 0x00000021, //2, -108dB + 0x00000025, //3, -107dB + 0x0000002A, //4, -106dB + 0x0000002F, //5, -105dB + 0x00000035, //6, -104dB + 0x0000003B, //7, -103dB + 0x00000043, //8, -102dB + 0x0000004B, //9, -101dB + 0x00000054, //10, -100dB + 0x0000005E, //11, -99dB + 0x0000006A, //12, -98dB + 0x00000076, //13, -97dB + 0x00000085, //14, -96dB + 0x00000095, //15, -95dB + 0x000000A7, //16, -94dB + 0x000000BC, //17, -93dB + 0x000000D3, //18, -92dB + 0x000000EC, //19, -91dB + 0x00000109, //20, -90dB + 0x0000012A, //21, -89dB + 0x0000014E, //22, -88dB + 0x00000177, //23, -87dB + 0x000001A4, //24, -86dB + 0x000001D8, //25, -85dB + 0x00000211, //26, -84dB + 0x00000252, //27, -83dB + 0x0000029A, //28, -82dB + 0x000002EC, //29, -81dB + 0x00000347, //30, -80dB + 0x000003AD, //31, -79dB + 0x00000420, //32, -78dB + 0x000004A1, //33, -77dB + 0x00000532, //34, -76dB + 0x000005D4, //35, -75dB + 0x0000068A, //36, -74dB + 0x00000756, //37, -73dB + 0x0000083B, //38, -72dB + 0x0000093C, //39, -71dB + 0x00000A5D, //40, -70dB + 0x00000BA0, //41, -69dB + 0x00000D0C, //42, -68dB + 0x00000EA3, //43, -67dB + 0x0000106C, //44, -66dB + 0x0000126D, //45, -65dB + 0x000014AD, //46, -64dB + 0x00001733, //47, -63dB + 0x00001A07, //48, -62dB + 0x00001D34, //49, -61dB + 0x000020C5, //50, -60dB + 0x000024C4, //51, -59dB + 0x00002941, //52, -58dB + 0x00002E49, //53, -57dB + 0x000033EF, //54, -56dB + 0x00003A45, //55, -55dB + 0x00004161, //56, -54dB + 0x0000495C, //57, -53dB + 0x0000524F, //58, -52dB + 0x00005C5A, //59, -51dB + 0x0000679F, //60, -50dB + 0x00007444, //61, -49dB + 0x00008274, //62, -48dB + 0x0000925F, //63, -47dB + 0x0000A43B, //64, -46dB + 0x0000B845, //65, -45dB + 0x0000CEC1, //66, -44dB + 0x0000E7FB, //67, -43dB + 0x00010449, //68, -42dB + 0x0001240C, //69, -41dB + 0x000147AE, //70, -40dB + 0x00016FAA, //71, -39dB + 0x00019C86, //72, -38dB + 0x0001CEDC, //73, -37dB + 0x00020756, //74, -36dB + 0x000246B5, //75, -35dB + 0x00028DCF, //76, -34dB + 0x0002DD96, //77, -33dB + 0x00033718, //78, -32dB + 0x00039B87, //79, -31dB + 0x00040C37, //80, -30dB + 0x00048AA7, //81, -29dB + 0x00051884, //82, -28dB + 0x0005B7B1, //83, -27dB + 0x00066A4A, //84, -26dB + 0x000732AE, //85, -25dB + 0x00081385, //86, -24dB + 0x00090FCC, //87, -23dB + 0x000A2ADB, //88, -22dB + 0x000B6873, //89, -21dB + 0x000CCCCD, //90, -20dB + 0x000E5CA1, //91, -19dB + 0x00101D3F, //92, -18dB + 0x0012149A, //93, -17dB + 0x00144961, //94, -16dB + 0x0016C311, //95, -15dB + 0x00198A13, //96, -14dB + 0x001CA7D7, //97, -13dB + 0x002026F3, //98, -12dB + 0x00241347, //99, -11dB + 0x00287A27, //100, -10dB + 0x002D6A86, //101, -9dB + 0x0032F52D, //102, -8dB + 0x00392CEE, //103, -7dB + 0x004026E7, //104, -6dB + 0x0047FACD, //105, -5dB + 0x0050C336, //106, -4dB + 0x005A9DF8, //107, -3dB + 0x0065AC8C, //108, -2dB + 0x00721483, //109, -1dB + 0x00800000, //110, 0dB + 0x008F9E4D, //111, 1dB + 0x00A12478, //112, 2dB + 0x00B4CE08, //113, 3dB + 0x00CADDC8, //114, 4dB + 0x00E39EA9, //115, 5dB + 0x00FF64C1, //116, 6dB + 0x011E8E6A, //117, 7dB + 0x0141857F, //118, 8dB + 0x0168C0C6, //119, 9dB + 0x0194C584, //120, 10dB + 0x01C62940, //121, 11dB + 0x01FD93C2, //122, 12dB + 0x023BC148, //123, 13dB + 0x02818508, //124, 14dB + 0x02CFCC01, //125, 15dB + 0x0327A01A, //126, 16dB + 0x038A2BAD, //127, 17dB + 0x03F8BD7A, //128, 18dB + 0x0474CD1B, //129, 19dB + 0x05000000, //130, 20dB + 0x059C2F02, //131, 21dB + 0x064B6CAE, //132, 22dB + 0x07100C4D, //133, 23dB + 0x07ECA9CD, //134, 24dB + 0x08E43299, //135, 25dB + 0x09F9EF8E, //136, 26dB + 0x0B319025, //137, 27dB + 0x0C8F36F2, //138, 28dB + 0x0E1787B8, //139, 29dB + 0x0FCFB725, //140, 30dB + 0x11BD9C84, //141, 31dB + 0x13E7C594, //142, 32dB + 0x16558CCB, //143, 33dB + 0x190F3254, //144, 34dB + 0x1C1DF80E, //145, 35dB + 0x1F8C4107, //146, 36dB + 0x2365B4BF, //147, 37dB + 0x27B766C2, //148, 38dB + 0x2C900313, //149, 39dB + 0x32000000, //150, 40dB + 0x3819D612, //151, 41dB + 0x3EF23ECA, //152, 42dB + 0x46A07B07, //153, 43dB + 0x4F3EA203, //154, 44dB + 0x58E9F9F9, //155, 45dB + 0x63C35B8E, //156, 46dB + 0x6FEFA16D, //157, 47dB + 0x7D982575, //158, 48dB +}; + +struct tas5805m_priv { + struct regmap *regmap; + + struct mutex lock; + + int vol; + int mute; +}; + +const struct regmap_config tas5805m_regmap = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, +}; + +static int tas5805m_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = + (SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE); + uinfo->count = 1; + + uinfo->value.integer.min = TAS5805M_VOLUME_MIN; + uinfo->value.integer.max = TAS5805M_VOLUME_MAX; + uinfo->value.integer.step = 1; + + return 0; +} + +static int tas5805m_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = + (SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE); + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + uinfo->value.integer.step = 1; + + return 0; +} + +static int tas5805m_vol_locked_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + + mutex_lock(&tas5805m->lock); + ucontrol->value.integer.value[0] = tas5805m->vol; + mutex_unlock(&tas5805m->lock); + + return 0; +} + +static inline int get_volume_index(int vol) +{ + int index; + + index = vol; + + if (index < TAS5805M_VOLUME_MIN) + index = TAS5805M_VOLUME_MIN; + + if (index > TAS5805M_VOLUME_MAX) + index = TAS5805M_VOLUME_MAX; + + return index; +} + +static void tas5805m_set_volume(struct snd_soc_codec *codec, int vol) +{ + unsigned int index; + uint32_t volume_hex; + uint8_t byte4; + uint8_t byte3; + uint8_t byte2; + uint8_t byte1; + + index = get_volume_index(vol); + volume_hex = tas5805m_volume[index]; + + byte4 = ((volume_hex >> 24) & 0xFF); + byte3 = ((volume_hex >> 16) & 0xFF); + byte2 = ((volume_hex >> 8) & 0xFF); + byte1 = ((volume_hex >> 0) & 0xFF); + + //w 58 00 00 + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + //w 58 7f 8c + snd_soc_write(codec, TAS5805M_REG_7F, TAS5805M_BOOK_8C); + //w 58 00 2a + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_2A); + //w 58 24 xx xx xx xx + snd_soc_write(codec, TAS5805M_REG_24, byte4); + snd_soc_write(codec, TAS5805M_REG_25, byte3); + snd_soc_write(codec, TAS5805M_REG_26, byte2); + snd_soc_write(codec, TAS5805M_REG_27, byte1); + //w 58 28 xx xx xx xx + snd_soc_write(codec, TAS5805M_REG_28, byte4); + snd_soc_write(codec, TAS5805M_REG_29, byte3); + snd_soc_write(codec, TAS5805M_REG_2A, byte2); + snd_soc_write(codec, TAS5805M_REG_2B, byte1); +} + +static int tas5805m_vol_locked_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + + mutex_lock(&tas5805m->lock); + + tas5805m->vol = ucontrol->value.integer.value[0]; + tas5805m_set_volume(codec, tas5805m->vol); + + mutex_unlock(&tas5805m->lock); + + return 0; +} + +static int tas5805m_mute(struct snd_soc_codec *codec, int mute) +{ + u8 reg03_value = 0; + u8 reg35_value = 0; +// struct snd_soc_codec *codec = dai->codec; + + if (mute) { + //mute both left & right channels + reg03_value = 0x0b; + reg35_value = 0x00; + } else { + //unmute + reg03_value = 0x03; + reg35_value = 0x11; + } + + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_REG_7F, TAS5805M_BOOK_00); + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_REG_03, reg03_value); + snd_soc_write(codec, TAS5805M_REG_35, reg35_value); + + return 0; +} + +static int tas5805m_mute_locked_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + + mutex_lock(&tas5805m->lock); + + tas5805m->mute = ucontrol->value.integer.value[0]; + tas5805m_mute(codec, tas5805m->mute); + + mutex_unlock(&tas5805m->lock); + + return 0; +} + +static int tas5805m_mute_locked_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + + mutex_lock(&tas5805m->lock); + ucontrol->value.integer.value[0] = tas5805m->mute; + mutex_unlock(&tas5805m->lock); + + return 0; +} + +static const struct snd_kcontrol_new tas5805m_vol_control[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Volume", + .info = tas5805m_vol_info, + .get = tas5805m_vol_locked_get, + .put = tas5805m_vol_locked_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Maser Volume Mute", + .info = tas5805m_mute_info, + .get = tas5805m_mute_locked_get, + .put = tas5805m_mute_locked_put, + } +}; + +static int tas5805m_snd_probe(struct snd_soc_codec *codec) +{ + int ret; + + ret = snd_soc_add_codec_controls(codec, tas5805m_vol_control, 2); + + return ret; +} + +static struct snd_soc_codec_driver soc_codec_tas5805m = { + .probe = tas5805m_snd_probe, +}; + +static const struct snd_soc_dai_ops tas5805m_dai_ops = { + //.digital_mute = tas5805m_mute, +}; + +static struct snd_soc_dai_driver tas5805m_dai = { + .name = "tas5805m-amplifier", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 8, + .rates = TAS5805M_RATES, + .formats = TAS5805M_FORMATS, + }, + .ops = &tas5805m_dai_ops, +}; + +static int tas5805m_probe(struct device *dev, struct regmap *regmap) +{ + struct tas5805m_priv *tas5805m; + int ret; + + tas5805m = devm_kzalloc(dev, sizeof(struct tas5805m_priv), GFP_KERNEL); + if (!tas5805m) + return -ENOMEM; + + dev_set_drvdata(dev, tas5805m); + tas5805m->regmap = regmap; + tas5805m->vol = 100; //100, -10dB + + mutex_init(&tas5805m->lock); + + ret = + regmap_register_patch(regmap, tas5805m_init_sequence, + ARRAY_SIZE(tas5805m_init_sequence)); + if (ret != 0) { + dev_err(dev, "Failed to initialize TAS5805M: %d\n", ret); + goto err; + + } + + ret = + snd_soc_register_codec(dev, &soc_codec_tas5805m, &tas5805m_dai, 1); + if (ret != 0) { + dev_err(dev, "Failed to register CODEC: %d\n", ret); + goto err; + } + + return 0; + +err: + return ret; + +} + +static int tas5805m_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + struct regmap_config config = tas5805m_regmap; + + regmap = devm_regmap_init_i2c(i2c, &config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return tas5805m_probe(&i2c->dev, regmap); +} + +static int tas5805m_remove(struct device *dev) +{ + snd_soc_unregister_codec(dev); + + return 0; +} + +static int tas5805m_i2c_remove(struct i2c_client *i2c) +{ + tas5805m_remove(&i2c->dev); + + return 0; +} + +static const struct i2c_device_id tas5805m_i2c_id[] = { + {"tas5805",}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, tas5805m_i2c_id); + +#ifdef CONFIG_OF +static const struct of_device_id tas5805m_of_match[] = { + {.compatible = "ti,tas5805",}, + {} +}; + +MODULE_DEVICE_TABLE(of, tas5805m_of_match); +#endif + +static struct i2c_driver tas5805m_i2c_driver = { + .probe = tas5805m_i2c_probe, + .remove = tas5805m_i2c_remove, + .id_table = tas5805m_i2c_id, + .driver = { + .name = TAS5805M_DRV_NAME, + .of_match_table = tas5805m_of_match, + }, +}; + +module_i2c_driver(tas5805m_i2c_driver); + +MODULE_AUTHOR("Andy Liu "); +MODULE_DESCRIPTION("TAS5805M Audio Amplifier Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/amlogic/tas5805.h b/sound/soc/codecs/amlogic/tas5805.h new file mode 100644 index 000000000000..ba6066204b12 --- /dev/null +++ b/sound/soc/codecs/amlogic/tas5805.h @@ -0,0 +1,1880 @@ +#include +static const struct reg_sequence tas5805m_init_sequence[] = { + {0x00, 0x00}, + {0x7f, 0x00}, + {0x03, 0x02}, + {0x01, 0x11}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x29, 0x7c}, + {0x03, 0x02}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x29, 0x00}, + {0x00, 0x00}, + {0x7f, 0x00}, + {0x46, 0x11}, + {0x03, 0x0f}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x66, 0x85}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2a}, + {0x24, 0x00}, + {0x25, 0x28}, + {0x26, 0x7a}, + {0x27, 0x27}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2a}, + {0x28, 0x00}, + {0x29, 0x28}, + {0x2a, 0x7a}, + {0x2b, 0x27}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x0b}, + {0x28, 0x00}, + {0x29, 0x80}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x0b}, + {0x2c, 0x00}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x29}, + {0x18, 0x00}, + {0x19, 0x80}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x29}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x29}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x29}, + {0x24, 0x00}, + {0x25, 0x80}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2a}, + {0x24, 0x00}, + {0x25, 0x28}, + {0x26, 0x7a}, + {0x27, 0x27}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2a}, + {0x28, 0x00}, + {0x29, 0x28}, + {0x2a, 0x7a}, + {0x2b, 0x27}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2a}, + {0x30, 0x00}, + {0x31, 0xe2}, + {0x32, 0xc4}, + {0x33, 0x6b}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x14, 0x00}, + {0x15, 0x80}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x1c, 0x00}, + {0x1d, 0x80}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x2c, 0x00}, + {0x2d, 0x80}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x34, 0x00}, + {0x35, 0x80}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x4c, 0x00}, + {0x4d, 0x80}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x57}, + {0x5f, 0x62}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x60, 0x00}, + {0x61, 0x03}, + {0x62, 0x69}, + {0x63, 0xd0}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x64, 0x00}, + {0x65, 0xce}, + {0x66, 0xc0}, + {0x67, 0x8a}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x68, 0x40}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2c}, + {0x6c, 0x05}, + {0x6d, 0x1f}, + {0x6e, 0x97}, + {0x6f, 0x37}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2d}, + {0x18, 0x7a}, + {0x19, 0xe0}, + {0x1a, 0x68}, + {0x1b, 0xc9}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2d}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0xae}, + {0x1f, 0xc3}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2d}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2d}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2d}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2d}, + {0x2c, 0x00}, + {0x2d, 0x80}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x31}, + {0x48, 0x40}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x32}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x40, 0x00}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x33}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x40, 0x00}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x34}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x40, 0x00}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x35}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x40, 0x00}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x24}, + {0x18, 0x08}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x24}, + {0x2c, 0x08}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x24}, + {0x40, 0x08}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x24}, + {0x54, 0x08}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x24}, + {0x68, 0x08}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x24}, + {0x7c, 0x08}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x25}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x25}, + {0x18, 0x08}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x25}, + {0x2c, 0x08}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x25}, + {0x40, 0x08}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x25}, + {0x54, 0x08}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x25}, + {0x68, 0x08}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x25}, + {0x7c, 0x08}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x26}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x26}, + {0x18, 0x08}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x26}, + {0x2c, 0x08}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x26}, + {0x40, 0x08}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x26}, + {0x54, 0x08}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x26}, + {0x68, 0x08}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x26}, + {0x7c, 0x08}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x27}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x27}, + {0x18, 0x08}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x27}, + {0x2c, 0x08}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x27}, + {0x40, 0x08}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x27}, + {0x54, 0x08}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x27}, + {0x68, 0x08}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x27}, + {0x7c, 0x08}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x28}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x28}, + {0x18, 0x08}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x28}, + {0x2c, 0x08}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x37, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x28}, + {0x40, 0x08}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x28}, + {0x54, 0x08}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x28}, + {0x68, 0x08}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x28}, + {0x7c, 0x08}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x29}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2e}, + {0x08, 0x00}, + {0x09, 0x80}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2e}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x00}, + {0x0f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2e}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x2a}, + {0x48, 0x7f}, + {0x49, 0xff}, + {0x4a, 0xff}, + {0x4b, 0xff}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2d}, + {0x58, 0x00}, + {0x59, 0x06}, + {0x5a, 0xd3}, + {0x5b, 0x72}, + {0x5c, 0x00}, + {0x5d, 0x02}, + {0x5e, 0xbb}, + {0x5f, 0x06}, + {0x60, 0x00}, + {0x61, 0x03}, + {0x62, 0x69}, + {0x63, 0xc5}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x70, 0xf9}, + {0x71, 0xda}, + {0x72, 0xbc}, + {0x73, 0x21}, + {0x74, 0xfc}, + {0x75, 0x58}, + {0x76, 0x8b}, + {0x77, 0x89}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2b}, + {0x34, 0x00}, + {0x35, 0x06}, + {0x36, 0xd3}, + {0x37, 0x72}, + {0x38, 0x00}, + {0x39, 0x02}, + {0x3a, 0xbb}, + {0x3b, 0x06}, + {0x3c, 0x00}, + {0x3d, 0x03}, + {0x3e, 0x69}, + {0x3f, 0xc5}, + {0x40, 0x00}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0xf9}, + {0x4d, 0xda}, + {0x4e, 0xbc}, + {0x4f, 0x21}, + {0x50, 0xfc}, + {0x51, 0x58}, + {0x52, 0x8b}, + {0x53, 0x89}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x2a}, + {0x34, 0x7f}, + {0x35, 0xff}, + {0x36, 0xff}, + {0x37, 0xff}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x40, 0x00}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2d}, + {0x30, 0x00}, + {0x31, 0x06}, + {0x32, 0xd3}, + {0x33, 0x72}, + {0x34, 0x00}, + {0x35, 0x02}, + {0x36, 0xbb}, + {0x37, 0x06}, + {0x38, 0x00}, + {0x39, 0x03}, + {0x3a, 0x69}, + {0x3b, 0xc5}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x40, 0x00}, + {0x41, 0x00}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0xf9}, + {0x49, 0xda}, + {0x4a, 0xbc}, + {0x4b, 0x21}, + {0x4c, 0xfc}, + {0x4d, 0x58}, + {0x4e, 0x8b}, + {0x4f, 0x89}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x2a}, + {0x5c, 0x7f}, + {0x5d, 0xff}, + {0x5e, 0xff}, + {0x5f, 0xff}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x6f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x2a}, + {0x70, 0x7f}, + {0x71, 0xff}, + {0x72, 0xff}, + {0x73, 0xff}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x2b}, + {0x08, 0x00}, + {0x09, 0x00}, + {0x0a, 0x00}, + {0x0b, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x2b}, + {0x0c, 0x7f}, + {0x0d, 0xff}, + {0x0e, 0xff}, + {0x0f, 0xff}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x2b}, + {0x20, 0x7f}, + {0x21, 0xff}, + {0x22, 0xff}, + {0x23, 0xff}, + {0x24, 0x00}, + {0x25, 0x00}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x00}, + {0x2e, 0x00}, + {0x2f, 0x00}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x2e}, + {0x40, 0x7f}, + {0x41, 0xff}, + {0x42, 0xff}, + {0x43, 0xff}, + {0x44, 0x00}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x00}, + {0x4d, 0x00}, + {0x4e, 0x00}, + {0x4f, 0x00}, + {0x50, 0x00}, + {0x51, 0x00}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x00, 0x00}, + {0x7f, 0xaa}, + {0x00, 0x2e}, + {0x54, 0x7f}, + {0x55, 0xff}, + {0x56, 0xff}, + {0x57, 0xff}, + {0x58, 0x00}, + {0x59, 0x00}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x00}, + {0x61, 0x00}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x00}, + {0x67, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2e}, + {0x18, 0x00}, + {0x19, 0x80}, + {0x1a, 0x00}, + {0x1b, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2e}, + {0x1c, 0x40}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x00, 0x00}, + {0x7f, 0x8c}, + {0x00, 0x2e}, + {0x20, 0x40}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, +//Register Tuning + {0x00, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x30, 0x00}, + {0x60, 0x00}, + {0x62, 0x00}, + {0x00, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x4c, 0x30}, + {0x4d, 0x30}, + {0x00, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x02, 0x00}, + {0x00, 0x00}, + {0x7f, 0x00}, + {0x00, 0x00}, + {0x03, 0x03}, + {0x35, 0x11}, +};