mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-12-25 04:43:04 +00:00
133 lines
3.7 KiB
Python
133 lines
3.7 KiB
Python
|
#!/usr/bin/env python3
|
||
|
# SPDX-License-Identifier: MIT
|
||
|
import sys, pathlib
|
||
|
import time
|
||
|
sys.path.append(str(pathlib.Path(__file__).resolve().parents[1]))
|
||
|
|
||
|
# audio_capture.py -- capture audio on jack microphone input (on M1 macs with cs42l83)
|
||
|
#
|
||
|
# sample usage with sox: (recoding can be loud!)
|
||
|
#
|
||
|
# ./audio_capture.py | sox -t raw -r 48000 -c 1 -e signed-int -b 32 -L - OUTPUT_FILE
|
||
|
|
||
|
from m1n1.setup import *
|
||
|
from m1n1.hw.dart import DART, DARTRegs
|
||
|
from m1n1.hw.i2c import I2C
|
||
|
from m1n1.hw.pmgr import PMGR
|
||
|
from m1n1.hw.nco import NCO
|
||
|
from m1n1.hw.admac import *
|
||
|
from m1n1.hw.mca import *
|
||
|
|
||
|
p.pmgr_adt_clocks_enable("/arm-io/i2c2")
|
||
|
p.pmgr_adt_clocks_enable("/arm-io/admac-sio")
|
||
|
p.pmgr_adt_clocks_enable("/arm-io/dart-sio")
|
||
|
p.pmgr_adt_clocks_enable("/arm-io/mca-switch")
|
||
|
p.pmgr_adt_clocks_enable("/arm-io/mca3")
|
||
|
|
||
|
# reset AUDIO_P
|
||
|
PS_AUDIO_P = PMGR(u).regs[0].PS4[10]
|
||
|
PS_AUDIO_P.set(DEV_DISABLE=1)
|
||
|
PS_AUDIO_P.set(RESET=1)
|
||
|
PS_AUDIO_P.set(RESET=0)
|
||
|
PS_AUDIO_P.set(DEV_DISABLE=0)
|
||
|
|
||
|
dart_base, _ = u.adt["/arm-io/dart-sio"].get_reg(0)
|
||
|
dart = DART(iface, DARTRegs(u, dart_base), util=u)
|
||
|
dart.initialize()
|
||
|
|
||
|
cl_no = 2
|
||
|
|
||
|
admac = ADMAC(u, "/arm-io/admac-sio", dart, debug=True)
|
||
|
dmachan = admac.chans[4*cl_no+1]
|
||
|
dmachan.buswidth = E_BUSWIDTH.W_32BIT
|
||
|
dmachan.framesize = E_FRAME.F_1_WORD
|
||
|
|
||
|
nco = NCO(u, "/arm-io/nco")
|
||
|
nco[cl_no].set_rate(6000000)
|
||
|
nco[cl_no].enable()
|
||
|
|
||
|
mca_switch1_base = u.adt["/arm-io/mca-switch"].get_reg(1)[0]
|
||
|
mca_cl_base = u.adt["/arm-io/mca-switch"].get_reg(0)[0] + 0x4000*cl_no
|
||
|
cl = MCACluster(u, mca_cl_base)
|
||
|
|
||
|
regs, serdes = cl.regs, cl.rxa
|
||
|
|
||
|
regs.SYNCGEN_STATUS.set(EN=0)
|
||
|
regs.SYNCGEN_MCLK_SEL.val =(1 + cl_no)
|
||
|
regs.SYNCGEN_HI_PERIOD.val = 0 # period minus one
|
||
|
regs.SYNCGEN_LO_PERIOD.val = 0x7b # period minus one
|
||
|
|
||
|
serdes.STATUS.set(EN=0)
|
||
|
serdes.CONF.set(
|
||
|
NSLOTS=0,
|
||
|
SLOT_WIDTH=E_SLOT_WIDTH.W_32BIT,
|
||
|
BCLK_POL=1,
|
||
|
UNK1=1, UNK2=1,
|
||
|
SYNC_SEL=(1 + cl_no)
|
||
|
)
|
||
|
serdes.UNK1.val = 0x4
|
||
|
|
||
|
serdes.BITDELAY.val = 1
|
||
|
|
||
|
serdes.CHANMASK[0].val = 0xffff_ffff
|
||
|
serdes.CHANMASK[1].val = 0xffff_fffe
|
||
|
|
||
|
regs.PORT_ENABLES.set(CLOCK1=1, CLOCK2=1, DATA=0)
|
||
|
regs.PORT_CLK_SEL.set(SEL=(cl_no + 1))
|
||
|
regs.MCLK_STATUS.set(EN=1)
|
||
|
regs.SYNCGEN_STATUS.set(EN=1)
|
||
|
|
||
|
cs42l_addr = 0x48
|
||
|
i2c2 = I2C(u, "/arm-io/i2c2")
|
||
|
def cs42l_write(regaddr, val):
|
||
|
i2c2.write_reg(cs42l_addr, 0x0, [regaddr >> 8])
|
||
|
i2c2.write_reg(cs42l_addr, regaddr & 0xff, [val])
|
||
|
|
||
|
p.write32(0x23d1f002c, 0x76a02)
|
||
|
p.write32(0x23d1f002c, 0x76a03) # take jack codec out of reset
|
||
|
|
||
|
cs42l_write(0x1009, 0x0) # FS_int = MCLK/250
|
||
|
cs42l_write(0x1101, 0x7a) # power on
|
||
|
cs42l_write(0x1103, 0x22) # power on ring sense
|
||
|
cs42l_write(0x1107, 0x1) # SCLK present
|
||
|
cs42l_write(0x1121, 0xa6) # Headset Switch Control
|
||
|
cs42l_write(0x1129, 0x1) # Headset Clamp Disable
|
||
|
cs42l_write(0x1205, 0x7c) # FSYNC period
|
||
|
cs42l_write(0x1207, 0x20) # ASP Clock Configuration
|
||
|
cs42l_write(0x1208, 0x12) # BITDELAY = 1
|
||
|
cs42l_write(0x120c, 0x1) # SCLK_PREDIV = div-by-2
|
||
|
cs42l_write(0x150a, 0x55) # PLL
|
||
|
cs42l_write(0x151b, 0x1) # PLL
|
||
|
cs42l_write(0x1501, 0x1) # power on PLL
|
||
|
cs42l_write(0x1b70, 0xc3) # HSBIAS sense
|
||
|
cs42l_write(0x1b71, 0xe0) # v-- headset
|
||
|
cs42l_write(0x1b73, 0xc0)
|
||
|
cs42l_write(0x1b74, 0x1f)
|
||
|
cs42l_write(0x1b75, 0xb6)
|
||
|
cs42l_write(0x1b76, 0x8f)
|
||
|
cs42l_write(0x1b79, 0x0)
|
||
|
cs42l_write(0x1b7a, 0xfc)
|
||
|
cs42l_write(0x1c03, 0xc0) # HSBIAS
|
||
|
cs42l_write(0x2506, 0xc) # ASP TX samp. rate
|
||
|
cs42l_write(0x2609, 0x4c) # SRC output samp. rate
|
||
|
cs42l_write(0x2901, 0x1) # ASP TX enable & size
|
||
|
cs42l_write(0x2902, 0x1) # ASP TX channel enable
|
||
|
|
||
|
time.sleep(0.01)
|
||
|
|
||
|
cs42l_write(0x1201, 0x1) # transition to PLL clock
|
||
|
|
||
|
# drain garbled samples (why are they garbled? i am not sure)
|
||
|
time.sleep(0.5)
|
||
|
|
||
|
dmachan.submit(buflen=0x4000)
|
||
|
dmachan.enable()
|
||
|
|
||
|
p.write32(mca_switch1_base + 0x8000*cl_no, 0x24800)
|
||
|
serdes.STATUS.set(EN=1)
|
||
|
|
||
|
while True:
|
||
|
while dmachan.can_submit():
|
||
|
dmachan.submit(buflen=0x4000)
|
||
|
sys.stdout.buffer.write(dmachan.poll())
|