WM8904: Add initialization logic

This commit is contained in:
Gregory Nutt 2014-07-19 10:20:19 -06:00
parent a0607ff2a7
commit 89ed7ab558
5 changed files with 466 additions and 31 deletions

View File

@ -320,10 +320,12 @@ menuconfig AUDIO_DEVICES
bool "Audio Device Support"
default n
---help---
Enable support for audio device drivers.
This includes drivers for MP3, WMA and Ogg Vorbis encoding,
decoding, as well as drivers for interfacing with external
DSP chips to perform custom audio functions.
Enable support for audio device drivers. This includes drivers for
MP3, WMA and Ogg Vorbis encoding, decoding, as well as drivers for
interfacing with external DSP chips to perform custom audio functions.
NOTE: All of these drivers depend on support from the audio subsystem
enabled with the AUDIO selection.
if AUDIO_DEVICES
source drivers/audio/Kconfig

View File

@ -6,7 +6,7 @@
config AUDIO_I2SCHAR
bool "I2S character driver (for testing only)"
default n
depends on I2S
depends on I2S && AUDIO
---help---
This selection enables a simple character driver that supports I2S
transfers via a read() and write(). The intent of this driver is to
@ -38,6 +38,7 @@ endif #AUDIO_I2SCHAR
config VS1053
bool "VS1053 codec chip"
default n
depends on AUDIO
---help---
Select to enable support for the VS1053 Audio codec by VLSI Solutions.
This chip provides encoding and decoding of MP3, WMA, AAC and Ogg
@ -86,11 +87,11 @@ endif # VS1053
config AUDIO_WM8904
bool "WM8904 audio chip"
default n
depends on EXPERIMENTAL
depends on AUDIO && EXPERIMENTAL
---help---
Select to enable support for the WM8904 Audio codec by Wolfson
Microelectonics. This chip is a lower level audio chip.. basically
an exotic D-to-A. It includes no builtin support for audion CODECS
an exotic D-to-A. It includes no built-in support for audio CODECS
The WM8904 provides:
- Low power consumption
@ -101,6 +102,9 @@ config AUDIO_WM8904
- Ground-referenced headphone driver
- Ground-referenced line outputs
NOTE: This driver also depends on both I2C and I2S support although
that dependency is not explicit here.
if AUDIO_WM8904
endif # AUDIO_WM8904

View File

@ -6,11 +6,11 @@
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Reference:
* "WM8904 Ultra Low Power CODEC for Portable Audio Applications, Pre-
* References:
* - "WM8904 Ultra Low Power CODEC for Portable Audio Applications, Pre-
* Production", September 2012, Rev 3.3, Wolfson Microelectronics
*
* The framework for this driver is based on Ken Pettit's VS1053 driver.
* - The framework for this driver is based on Ken Pettit's VS1053 driver.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -96,7 +96,7 @@
# define CONFIG_WM8904_WORKER_STACKSIZE 768
#endif
#define WM8904_DUMMY 0xFF
#define WM8904_DUMMY 0xff
#define WM8904_DEFAULT_XTALI 12288000
#define WM8904_DATA_FREQ 20000000
#define WM8904_RST_USECS 2000
@ -199,6 +199,13 @@ static int wm8904_cancelbuffer(FAR struct audio_lowerhalf_s *dev,
static int wm8904_ioctl(FAR struct audio_lowerhalf_s *dev, int cmd,
unsigned long arg);
/* Initialization */
static void wm8904_audio_output(FAR struct wm8904_dev_s *priv);
#if 0 /* Not used */
static void wm8904_audio_input(FAR struct wm8904_dev_s *priv);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
@ -241,11 +248,71 @@ static const struct audio_ops_s g_audioops =
static uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
{
FAR struct i2c_dev_s *i2c = priv->i2c;
uint16_t regval;
#warning Missing logic
audvdbg("Read: %02x -> %04x\n", regaddr, regval);
return regval;
int retries;
/* Try up to three times to read the register */
for (retries = 1; retries <= 3; retries++)
{
struct i2c_msg_s msg[2];
uint8_t data[2];
int ret;
/* Set up to write the address */
msg[0].addr = priv->lower->address;
msg[0].flags = 0;
msg[0].buffer = &regaddr;
msg[0].length = 1;
/* Followed by the read data */
msg[1].addr = priv->lower->address;
msg[1].flags = I2C_M_READ;
msg[1].buffer = data;
msg[1].length = 2;
/* Read the register data. The returned value is the number messages
* completed.
*/
ret = I2C_TRANSFER(priv->i2c, msg, 2);
if (ret < 0)
{
#ifdef CONFIG_I2C_RESET
/* Perhaps the I2C bus is locked up? Try to shake the bus free */
idbg("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
ret = up_i2creset(priv->i2c);
if (ret < 0)
{
idbg("ERROR: up_i2creset failed: %d\n", ret);
break;
}
#else
idbg("ERROR: I2C_TRANSFER failed: %d\n", ret);
#endif
}
else
{
uint16_t regval;
/* The I2C transfer was successful... break out of the loop and
* return the value read.
*/
regval = ((uint16_t)data[0] << 8) | (uint16_t)data[1]
audvdbg("READ: %02x -> %04x\n", regaddr, regval);
return regval;
}
ivdbg("retries=%d regaddr=%04x\n", retries, regaddr);
}
/* No error indication is returned on a failure... just return zero */
return 0;
}
/************************************************************************************
@ -256,18 +323,70 @@ static uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
*
************************************************************************************/
static void wm8904_writereg(FAR struct wm8904_dev_s *priv, uint8_t regaddr, uint16_t regval)
static void wm8904_writereg(FAR struct wm8904_dev_s *priv, uint8_t regaddr,
uint16_t regval)
{
FAR struct i2c_dev_s *i2c = priv->i2c;
int retries;
/* Select the AUDIO_CTRL device on the I2C bus */
/* Try up to three times to read the register */
audvdbg("Write: %02x <- %04x\n", regaddr, regval);
#warning "Missing logic"
for (retries = 1; retries <= 3; retries++)
{
struct i2c_msg_s msg[2];
uint8_t data[2];
int ret;
/* Short delay after a write for WM8904 processing time */
/* REVISIT: Necessary for the WM8904? */
usleep(10);
/* Set up to write the address */
msg[0].addr = priv->lower->address;
msg[0].flags = 0;
msg[0].buffer = &regaddr;
msg[0].length = 1;
/* Followed by the read data */
data[0] = regval >> 8;
data[1] = regval & 0xff;
msg[1].addr = priv->lower->address;
msg[1].flags = I2C_M_NORESTART;
msg[1].buffer = data;
msg[1].length = 2;
/* Read the register data. The returned value is the number messages
* completed.
*/
ret = I2C_TRANSFER(priv->i2c, msg, 2);
if (ret < 0)
{
#ifdef CONFIG_I2C_RESET
/* Perhaps the I2C bus is locked up? Try to shake the bus free */
idbg("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
ret = up_i2creset(priv->i2c);
if (ret < 0)
{
idbg("ERROR: up_i2creset failed: %d\n", ret);
break;
}
#else
idbg("ERROR: I2C_TRANSFER failed: %d\n", ret);
#endif
}
else
{
/* The I2C transfer was successful... break out of the loop and
* return the value read.
*/
audvdbg("Write: %02x <- %04x\n", regaddr, regval);
return;
}
ivdbg("retries=%d regaddr=%04x\n", retries, regaddr);
}
}
/************************************************************************************
@ -1457,6 +1576,190 @@ static int wm8904_release(FAR struct audio_lowerhalf_s *dev)
return OK;
}
/****************************************************************************
* Name: wm8904_audio_output
*
* Description:
* Initialize and configure the WM8904 device as an audio output device.
*
* Input Parameters:
* prive - A reference to the driver state structure
*
* Returned Value:
* None. No failures are detected.
*
****************************************************************************/
static void wm8904_audio_output(FAR struct wm8904_dev_s *priv)
{
uint16_t regval;
/* Bias Control.
* Preserve undocumented default bit.WM8904_DUMMY
*/
regval = WM8904_ISEL_HIGH | WM8904_BIAS_ENA | 0x0010;
wm8904_writereg(priv, WM8904_BIAS_CTRL, regval);
/* VMID Control */
regval = WM8904_VMID_BUF_ENA | WM8904_VMID_RES_NORMAL | WM8904_VMID_ENA;
wm8904_writereg(priv, WM8904_VMID_CTRL, regval);
/* Mic Bias Control 0 */
/* MICDET_ENA=1, MICBIAS_ENA=1 */
regval = WM8904_MICDET_ENA | WM8904_MICBIAS_ENA;
wm8904_writereg(priv, WM8904_MIC_BIAS_CTRL0, regval);
/* Mic Bias Control 1. */
wm8904_writereg(priv, WM8904_MIC_BIAS_CTRL1, 0xc000);
/* Power Management 0 */
regval = WM8904_INL_ENA | WM8904_INR_ENA;
wm8904_writereg(priv, WM8904_PM0, regval);
/* Power Management 2 */
regval = WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA;
wm8904_writereg(priv, WM8904_PM2, regval);
/* Power Management 6 */
/* DACL_ENA=1, DACR_ENA=1, ADCL_ENA=1, ADCR_ENA=1 */
regval = WM8904_DACL_ENA | WM8904_DACR_ENA | WM8904_ADCL_ENA | WM8904_ADCR_ENA;
wm8904_writereg(priv, WM8904_PM6, regval);
/* Clock Rates 0.
*
* This value sets TOCLK_RATE_DIV16=0, TOCLK_RATE_X4=0, and MCLK_DIV=0 while
* preserving the state of some undocumented bits (see wm8904.h).
*/
wm8904_writereg(priv, WM8904_CLKRATE0, 0x845e);
/* Clock Rates 2 */
regval = WM8904_SYSCLK_SRC | WM8904_CLK_SYS_ENA | WM8904_CLK_DSP_ENA;
wm8904_writereg(priv, WM8904_CLKRATE2, regval);
/* Audio Interface 1.
*
* This value sets AIFADC_TDM=0, AIFADC_TDM_CHAN=0, BCLK_DIR=1 while preserving
* the state of some undocumented bits (see wm8904.h).
*/
wm8904_writereg(priv, WM8904_AIF1, 0x404A);
/* Audio Interface 3 */
regval = WM8904_LRCLK_DIR | WM8904_LRCLK_RATE(64);
wm8904_writereg(priv, WM8904_AIF3, regval);
/* DAC Digital 1 */
wm8904_writereg(priv, WM8904_DAC_DIGI1, 0);
/* Analogue Left Input 0 */
/* Analogue Right Input 0 */
regval = WM8904_IN_VOL(5);
wm8904_writereg(priv, WM8904_ANA_LEFT_IN0, regval);
wm8904_writereg(priv, WM8904_ANA_RIGHT_IN0, regval);
/* Analogue Left Input 1 */
wm8904_writereg(priv, WM8904_ANA_LEFT_IN1, 0);
wm8904_writereg(priv, WM8904_ANA_RIGHT_IN1, 0);
/* Analogue OUT1 Right */
regval = WM8904_HPOUT_MUTE | WM8904_HPOUTZC | WM8904_HPOUT_VOL(29);
wm8904_writereg(priv, WM8904_ANA_RIGHT_OUT1, regval);
/* DC Servo 0 */
/* DCS_ENA_CHAN_1=1, DCS_ENA_CHAN_0=1 */
regval = WM8904_DCS_ENA_CHAN_1 | WM8904_DCS_ENA_CHAN_0;
wm8904_writereg(priv, WM8904_DC_SERVO0, regval);
/* Analogue HP 0 */
regval = WM8904_HPL_RMV_SHORT | WM8904_HPL_ENA_OUTP | WM8904_HPL_ENA_DLY | WM8904_HPL_ENA |
WM8904_HPR_RMV_SHORT | WM8904_HPR_ENA_OUTP | WM8904_HPR_ENA_DLY | WM8904_HPR_ENA;
wm8904_writereg(priv, WM8904_ANA_HP0, regval);
/* Charge Pump 0 */
wm8904_writereg(priv, WM8904_CHG_PUMP0, WM8904_CP_ENA);
/* Class W 0 */
regval = WM8904_CP_DYN_PWR | 0x0004;
wm8904_writereg(priv, WM8904_CLASS_W0, regval);
/* FLL Control 1 */
wm8904_writereg(priv, WM8904_FLL_CTRL1, 0);
regval = WM8904_FLL_FRACN_ENA | WM8904_FLL_ENA;
wm8904_writereg(priv, WM8904_FLL_CTRL1, regval);
/* FLL Control 2 */
regval = WM8904_FLL_OUTDIV(8) | WM8904_FLL_FRATIO_DIV16;
wm8904_writereg(priv, WM8904_FLL_CTRL2, regval);
/* FLL Control 3 */
wm8904_writereg(priv, WM8904_FLL_CTRL3, 16384);
/* FLL Control 4 */
regval = WM8904_FLL_N(187) | WM8904_FLL_GAIN_X1;
wm8904_writereg(priv, WM8904_FLL_CTRL4, regval);
wm8904_writereg(priv, WM8904_DUMMY, 0x55AA);
}
/****************************************************************************
* Name: wm8904_audio_input
*
* Description:
* Initialize and configure the WM8904 device as an audio output device
* (Right input only).
*
* Input Parameters:
* prive - A reference to the driver state structure
*
* Returned Value:
* None. No failures are detected.
*
****************************************************************************/
#if 0 /* Not used */
static void wm8904_audio_input(FAR struct wm8904_dev_s *priv)
{
/* Analogue Left Input 0 */
wm8904_writereg(priv, WM8904_ANA_LEFT_IN0, WM8904_INMUTE);
/* Analogue Right Input 0 */
wm8904_writereg(priv, WM8904_ANA_RIGHT_IN0, WM8904_IN_VOL(5));
/* Analogue Left Input 1 */
wm8904_writereg(priv, WM8904_ANA_LEFT_IN1, 0);
/* Analogue Right Input 1 */
wm8904_writereg(priv, WM8904_ANA_RIGHT_IN1, WM8904_IP_SEL_N_IN2L);
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -1485,6 +1788,7 @@ FAR struct audio_lowerhalf_s *
FAR const struct wm8904_lower_s *lower, unsigned int devno)
{
FAR struct wm8904_dev_s *priv;
uint16_t regval;
/* Sanity check */
@ -1527,17 +1831,28 @@ FAR struct audio_lowerhalf_s *
I2C_SETFREQUENCY(i2c, lower->frequency);
I2C_SETADDRESS(i2c, lower->address, 7);
/* Verify the device ID read from the chip */
#warning Missing logic
/* Software reset */
/* Initialize the WM8904 hardware */
#warning Missing logic
wm8904_writereg(priv, WM8904_SWRST, 0);
/* Verify that WM8904 is present and available on this I2C */
regval = wm8904_readreg(priv, WM8904_ID);
if (regval != WM8904_SW_RST_DEV_ID1)
{
auddbg("ERROR: WM8904 not found: ID=%04x\n", regval);
return -ENODEV;
}
WM8904_DUMMY
/* Configure the WM8904 hardware as an audio input device */
wm8904_audio_output(priv);
/* Attach our ISR to this device */
WM8904_ATTACH(lower, wm8904_interrupt, priv);
/* Put the drive in the 'shutdown' status */
/* Put the driver in the 'shutdown' state */
wm8904_shutdown(&priv->dev);
}

View File

@ -57,7 +57,8 @@
/* Registers Addresses ******************************************************/
#define WM8904_SWRST_ID 0x00 /* SW Reset and ID */
#define WM8904_SWRST 0x00 /* SW Reset and ID */
#define WM8904_ID 0x00 /* SW Reset and ID */
#define WM8904_BIAS_CTRL 0x04 /* Bias Control */
#define WM8904_VMID_CTRL 0x05 /* VMID Control */
#define WM8904_MIC_BIAS_CTRL0 0x06 /* Mic Bias Control 0 */
@ -77,7 +78,7 @@
#define WM8904_DAC_VOL_LEFT 0x1e /* DAC Digital Volume Left */
#define WM8904_DAC_VOL_RIGHT 0x1f /* DAC Digital Volume Right */
#define WM8904_DAC_DIGI0 0x20 /* DAC Digital 0 */
#define WM8904_DATA_DIGI1 0x21 /* DAC Digital 1 */
#define WM8904_DAC_DIGI1 0x21 /* DAC Digital 1 */
#define WM8904_ADC_VOL_LEFT 0x24 /* ADC Digital Volume Left */
#define WM8904_ADC_VOL_RIGHT 0x25 /* ADC Digital Volume Right */
#define WM8904_ADC_DIGI 0x26 /* ADC Digital */
@ -156,6 +157,109 @@
#define WM8904_FLL_NCO_TEST0 0xf7 /* FLL NCO Test 0 */
#define WM8904_FLL_NCO_TEST1 0xf8 /* FLL NCO Test 1 */
/* Register Default Values **************************************************/
/* Registers have some undocumented bits set on power up. These probably
* should be retained on writes (?).
*/
#define WM8904_SWRST_DEFAULT 0x8904
#define WM8904_ID_DEFAULT 0x0018
#define WM8904_BIAS_CTRL_DEFAULT 0x0000
#define WM8904_VMID_CTRL_DEFAULT 0x0000
#define WM8904_MIC_BIAS_CTRL0_DEFAULT 0x0000
#define WM8904_MIC_BIAS_CTRL1_DEFAULT 0x0000
#define WM8904_ANALOG_ADC_DEFAULT 0x0001
#define WM8904_PM0_DEFAULT 0x0000
#define WM8904_PM2_DEFAULT 0x0000
#define WM8904_PM3_DEFAULT 0x0000
#define WM8904_PM6_DEFAULT 0x0000
#define WM8904_CLKRATE0_DEFAULT 0x8c5e
#define WM8904_CLKRATE1_DEFAULT 0x0c05
#define WM8904_CLKRATE2_DEFAULT 0x0000
#define WM8904_AIF0_DEFAULT 0x0050
#define WM8904_AIF1_DEFAULT 0x000a
#define WM8904_AIF2_DEFAULT 0x00e4
#define WM8904_AIF3_DEFAULT 0x0040
#define WM8904_DAC_VOL_LEFT_DEFAULT 0x00c0
#define WM8904_DAC_VOL_RIGHT_DEFAULT 0x00c0
#define WM8904_DAC_DIGI0_DEFAULT 0x0000
#define WM8904_DAC_DIGI1_DEFAULT 0x0004
#define WM8904_ADC_VOL_LEFT_DEFAULT 0x00c0
#define WM8904_ADC_VOL_RIGHT_DEFAULT 0x00c0
#define WM8904_ADC_DIGI_DEFAULT 0x0010
#define WM8904_MIC_DIGI_DEFAULT 0x0000
#define WM8904_DRC0_DEFAULT 0x01af
#define WM8904_DRC1_DEFAULT 0x3248
#define WM8904_DRC2_DEFAULT 0x0000
#define WM8904_DRC3_DEFAULT 0x0000
#define WM8904_ANA_LEFT_IN0_DEFAULT 0x0085
#define WM8904_ANA_RIGHT_IN0_DEFAULT 0x0085
#define WM8904_ANA_LEFT_IN1_DEFAULT 0x0044
#define WM8904_ANA_RIGHT_IN1_DEFAULT 0x0044
#define WM8904_ANA_LEFT_OUT1_DEFAULT 0x002d
#define WM8904_ANA_RIGHT_OUT1_DEFAULT 0x002d
#define WM8904_ANA_LEFT_OUT2_DEFAULT 0x0039
#define WM8904_ANA_RIGHT_OUT2_DEFAULT 0x0039
#define WM8904_ANA_OUT12_ZC_DEFAULT 0x0000
#define WM8904_DC_SERVO0_DEFAULT 0x0000
#define WM8904_DC_SERVO2_DEFAULT 0xaaaa
#define WM8904_DC_SERVO4_DEFAULT 0xaaaa
#define WM8904_DC_SERVO5_DEFAULT 0xaaaa
#define WM8904_DC_SERVO6_DEFAULT 0x0000
#define WM8904_DC_SERVO7_DEFAULT 0x0000
#define WM8904_DC_SERVO8_DEFAULT 0x0000
#define WM8904_DC_SERVO9_DEFAULT 0x0000
#define WM8904_DC_SERVO_RDBACK_DEFAULT 0x0000
#define WM8904_ANA_HP0_DEFAULT 0x0000
#define WM8904_ANA_LINEOUT0_DEFAULT 0x0000
#define WM8904_CHG_PUMP0_DEFAULT 0x0000
#define WM8904_CLASS_W0_DEFAULT 0x0000
#define WM8904_WR_SEQ0_DEFAULT 0x0000
#define WM8904_WR_SEQ1_DEFAULT 0x0000
#define WM8904_WR_SEQ2_DEFAULT 0x0000
#define WM8904_WR_SEQ3_DEFAULT 0x0000
#define WM8904_WR_SEQ4_DEFAULT 0x0000
#define WM8904_FLL_CTRL1_DEFAULT 0x0000
#define WM8904_FLL_CTRL2_DEFAULT 0x0007
#define WM8904_FLL_CTRL3_DEFAULT 0x0000
#define WM8904_FLL_CTRL4_DEFAULT 0x2ee0
#define WM8904_FLL_CTRL5_DEFAULT 0x0004
#define WM8904_GPIO_CTRL1_DEFAULT 0x0014
#define WM8904_GPIO_CTRL2_DEFAULT 0x0010
#define WM8904_GPIO_CTRL3_DEFAULT 0x0010
#define WM8904_GPIO_CTRL4_DEFAULT 0x0000
#define WM8904_DIGI_PULLS_DEFAULT 0x0000
#define WM8904_INT_MASK_DEFAULT 0xffff
#define WM8904_INT_POL_DEFAULT 0x0000
#define WM8904_INT_DEBOUNCE_DEFAULT 0x0000
#define WM8904_EQ1_DEFAULT 0x0000
#define WM8904_EQ2_DEFAULT 0x000c
#define WM8904_EQ3_DEFAULT 0x000c
#define WM8904_EQ4_DEFAULT 0x000c
#define WM8904_EQ5_DEFAULT 0x000c
#define WM8904_EQ6_DEFAULT 0x000c
#define WM8904_EQ7_DEFAULT 0x0fca
#define WM8904_EQ8_DEFAULT 0x0400
#define WM8904_EQ9_DEFAULT 0x00d8
#define WM8904_EQ10_DEFAULT 0x1eb5
#define WM8904_EQ11_DEFAULT 0xf145
#define WM8904_EQ12_DEFAULT 0x0b75
#define WM8904_EQ13_DEFAULT 0x01c5
#define WM8904_EQ14_DEFAULT 0x1c54
#define WM8904_EQ15_DEFAULT 0xf373
#define WM8904_EQ16_DEFAULT 0x0a54
#define WM8904_EQ17_DEFAULT 0x0558
#define WM8904_EQ18_DEFAULT 0x168e
#define WM8904_EQ19_DEFAULT 0xf829
#define WM8904_EQ20_DEFAULT 0x07ad
#define WM8904_EQ21_DEFAULT 0x1103
#define WM8904_EQ22_DEFAULT 0x0564
#define WM8904_EQ23_DEFAULT 0x0559
#define WM8904_EQ24_DEFAULT 0x4000
#define WM8904_ADC_TEST_DEFAULT 0x0000
#define WM8904_FLL_NCO_TEST0_DEFAULT 0x0000
#define WM8904_FLL_NCO_TEST1_DEFAULT 0x0019
/* Register Bit Definitions *************************************************/
/* 0x00 SW Reset and ID */

View File

@ -83,6 +83,16 @@
/* Default configuration values */
#ifndef CONFIG_WM8904_I2CFREQUENCY
# define CONFIG_WM8904_I2CFREQUENCY 400000
#endif
#if CONFIG_WM8904_I2CFREQUENCY > 400000
# warning WM8904 I2C frequency cannot exceed 400KHz
# undef CONFIG_WM8904_I2CFREQUENCY
# define CONFIG_WM8904_I2CFREQUENCY 400000
#endif
/* Helper macros ************************************************************/
#define WM8904_ATTACH(s,isr,arg) ((s)->attach(s,isr,arg))