diff --git a/drivers/ifxmodem/audio-settings.c b/drivers/ifxmodem/audio-settings.c index f156cf79..c2753986 100644 --- a/drivers/ifxmodem/audio-settings.c +++ b/drivers/ifxmodem/audio-settings.c @@ -42,11 +42,259 @@ static const char *none_prefix[] = { NULL }; static const char *xprogress_prefix[] = { "+XPROGRESS:", NULL }; +static const char *xdrv_prefix[] = { "+XDRV:", NULL }; + +enum xdrv_destination { + XDRV_DESTINATION_SPEECH_TX = 0, + XDRV_DESTINATION_ANALOG_OUT = 1, + XDRV_DESTINATION_I2SX_TX = 2, + XDRV_DESTINATION_I2SY_TX = 3, + XDRV_DESTINATION_PCM_GENERAL = 4, +}; + +enum xdrv_source { + XDRV_SOURCE_SPEECH_RX = 0, + XDRV_SOURCE_SPEECH_ANALOG_IN = 1, + XDRV_SOURCE_DIGITAL_MIC_IN = 2, + XDRV_SOURCE_I2SX_RX = 3, + XDRV_SOURCE_I2SY_RX = 4, + XDRV_SOURCE_SIMPLE_TONES = 5, +}; + +enum xdrv_sampling_rate { + XDRV_SAMPLING_RATE_8KHZ = 0, + XDRV_SAMPLING_RATE_11KHZ = 1, + XDRV_SAMPLING_RATE_12KHZ = 2, + XDRV_SAMPLING_RATE_16KHZ = 3, + XDRV_SAMPLING_RATE_22KHZ = 4, + XDRV_SAMPLING_RATE_24KHZ = 5, + XDRV_SAMPLING_RATE_32KHZ = 6, + XDRV_SAMPLING_RATE_44KHZ = 7, + XDRV_SAMPLING_RATE_48KHZ = 8, + XDRV_SAMPLING_RATE_96KHZ = 9, + XDRV_SAMPLING_RATE_192KHZ = 10, +}; + +enum xdrv_sampling_width { + XDRV_SAMPLING_WIDTH_16 = 0, + XDRV_SAMPLING_WIDTH_18 = 1, + XDRV_SAMPLING_WIDTH_20 = 2, + XDRV_SAMPLING_WIDTH_24 = 3, + XDRV_SAMPLING_WIDTH_32 = 4, + XDRV_SAMPLING_WIDTH_48 = 5, + XDRV_SAMPLING_WIDTH_64 = 6, +}; + +enum xdrv_i2s_mode { + XDRV_I2S_MODE_MASTER = 0, + XDRV_I2S_MODE_SLAVE = 1, +}; + +enum xdrv_i2s_clock { + XDRV_I2S_CLOCK_0 = 0, + XDRV_I2S_CLOCK_1 = 1, +}; + +enum xdrv_i2s_configuration_mode { + XDRV_I2S_CONFIGURATION_MODE_UPDATE_ALL = 0, + XDRV_I2S_CONFIGURATION_MODE_UPDATE_HW = 1, + XDRV_I2S_CONFIGURATION_MODE_UPDATE_TRANSDUCER = 2, +}; + +enum xdrv_i2s_settings { + XDRV_I2S_SETTINGS_NORMAL = 0, + XDRV_I2S_SETTINGS_SPECIAL1 = 1, + XDRV_I2S_SETTINGS_SPECIAL2 = 2, +}; + +enum xdrv_i2s_transmission_mode { + XDRV_I2S_TRANSMISSION_MODE_PCM = 0, + XDRV_I2S_TRANSMISSION_MODE_NORMAL = 1, + XDRV_IS2_TRANSMISSION_MODE_PCM_BURST = 2, +}; + +enum xdrv_source_transducer { + XDRV_SOURCE_TRANSDUCER_DEFAULT = 0, + XDRV_SOURCE_TRANSDUCER_HANDSET = 1, + XDRV_SOURCE_TRANSDUCER_HEADSET = 2, + XDRV_SOURCE_TRANSDUCER_HF = 3, + XDRV_SOURCE_TRANSDUCER_AUX = 4, + XDRV_SOURCE_TRANSDUCER_TTY = 5, + XDRV_SOURCE_TRANSDUCER_BLUETOOTH = 6, + XDRV_SOURCE_TRANSDUCER_USER_DEFINED_15 = 21, +}; + +enum xdrv_dest_transducer { + XDRV_DEST_TRANSDUCER_DEFAULT = 0, + XDRV_DEST_TRANSDUCER_HANDSET = 1, + XDRV_DEST_TRANSDUCER_HEADSET = 2, + XDRV_DEST_TRANSDUCER_BACKSPEAKER = 3, + XDRV_DEST_TRANSDUCER_TTY = 6, + XDRV_DEST_TRANSDUCER_BLUETOOTH = 7, + XDRV_DEST_TRANSDUCER_USER_DEFINED_15 = 22, +}; + +enum xdrv_audio_mode { + XDRV_AUDIO_MODE_MONO = 0, + XDRV_AUDIO_MODE_DUAL_MONO = 1, + XDRV_AUDIO_MODE_STEREO = 2, + XDRV_AUDIO_MODE_DUAL_MONO_R = 3, + XDRV_AUDIO_MODE_DUAL_MONO_L = 4, +}; struct audio_settings_data { GAtChat *chat; }; +static inline void xdrv_enable_source(GAtChat *chat, enum xdrv_source src) +{ + char buf[256]; + + sprintf(buf, "AT+XDRV=40,2,%i", src); + g_at_chat_send(chat, buf, xdrv_prefix, NULL, NULL, NULL); +} + +static inline void xdrv_disable_source(GAtChat *chat, enum xdrv_source src) +{ + char buf[256]; + + sprintf(buf, "AT+XDRV=40,3,%i", src); + g_at_chat_send(chat, buf, xdrv_prefix, NULL, NULL, NULL); +} + +static inline void xdrv_configure_source(GAtChat *chat, enum xdrv_source src, + enum xdrv_i2s_clock clock, + enum xdrv_i2s_mode master_slave, + enum xdrv_sampling_rate sample_rate, + enum xdrv_sampling_width bits, + enum xdrv_i2s_transmission_mode tx_mode, + enum xdrv_i2s_settings settings, + enum xdrv_audio_mode mode, + enum xdrv_i2s_configuration_mode config_mode, + enum xdrv_source_transducer transducer_mode) +{ + char buf[256]; + int ctx = 0; /* This is always 0 for now */ + + sprintf(buf, "AT+XDRV=40,4,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i", + src, ctx, clock, master_slave, sample_rate, bits, + tx_mode, settings, mode, config_mode, transducer_mode); + g_at_chat_send(chat, buf, xdrv_prefix, NULL, NULL, NULL); +} + +static inline void xdrv_configure_destination(GAtChat *chat, + enum xdrv_destination dest, + enum xdrv_i2s_clock clock, + enum xdrv_i2s_mode master_slave, + enum xdrv_sampling_rate sample_rate, + enum xdrv_sampling_width bits, + enum xdrv_i2s_transmission_mode tx_mode, + enum xdrv_i2s_settings settings, + enum xdrv_audio_mode mode, + enum xdrv_i2s_configuration_mode config_mode, + enum xdrv_dest_transducer transducer_mode) +{ + char buf[256]; + int ctx = 0; /* This is always 0 for now */ + + sprintf(buf, "AT+XDRV=40,5,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i", + dest, ctx, clock, master_slave, sample_rate, bits, + tx_mode, settings, mode, config_mode, transducer_mode); + g_at_chat_send(chat, buf, xdrv_prefix, NULL, NULL, NULL); +} + +static inline void xdrv_set_destination_for_source(GAtChat *chat, + enum xdrv_source src, + enum xdrv_destination dest) +{ + char buf[256]; + + sprintf(buf, "AT+XDRV=40,6,%i,%i", src, dest); + g_at_chat_send(chat, buf, xdrv_prefix, NULL, NULL, NULL); +} + +static inline void xdrv_set_destination_volume(GAtChat *chat, + enum xdrv_destination dest, + int volume) +{ + char buf[256]; + + sprintf(buf, "AT+XDRV=40,8,%i,%i", dest, volume); + g_at_chat_send(chat, buf, xdrv_prefix, NULL, NULL, NULL); +} + +static void send_xdrv_setup_sequence(struct ofono_audio_settings *as) +{ + struct audio_settings_data *asd = ofono_audio_settings_get_data(as); + + /* Mute */ + xdrv_set_destination_volume(asd->chat, XDRV_DESTINATION_I2SX_TX, 0); + xdrv_set_destination_volume(asd->chat, XDRV_DESTINATION_SPEECH_TX, 0); + + xdrv_set_destination_for_source(asd->chat, XDRV_SOURCE_SPEECH_RX, + XDRV_DESTINATION_PCM_GENERAL); + + xdrv_disable_source(asd->chat, XDRV_SOURCE_I2SX_RX); + xdrv_disable_source(asd->chat, XDRV_SOURCE_I2SY_RX); + + xdrv_configure_source(asd->chat, XDRV_SOURCE_I2SX_RX, XDRV_I2S_CLOCK_1, + XDRV_I2S_MODE_MASTER, XDRV_SAMPLING_RATE_48KHZ, + XDRV_SAMPLING_WIDTH_16, + XDRV_I2S_TRANSMISSION_MODE_NORMAL, + XDRV_I2S_SETTINGS_NORMAL, + XDRV_AUDIO_MODE_STEREO, + XDRV_I2S_CONFIGURATION_MODE_UPDATE_ALL, + XDRV_SOURCE_TRANSDUCER_USER_DEFINED_15); + xdrv_configure_destination(asd->chat, XDRV_DESTINATION_I2SX_TX, + XDRV_I2S_CLOCK_1, XDRV_I2S_MODE_MASTER, + XDRV_SAMPLING_RATE_48KHZ, + XDRV_SAMPLING_WIDTH_16, + XDRV_I2S_TRANSMISSION_MODE_NORMAL, + XDRV_I2S_SETTINGS_NORMAL, + XDRV_AUDIO_MODE_STEREO, + XDRV_I2S_CONFIGURATION_MODE_UPDATE_ALL, + XDRV_DEST_TRANSDUCER_USER_DEFINED_15); + + xdrv_configure_source(asd->chat, XDRV_SOURCE_I2SY_RX, XDRV_I2S_CLOCK_0, + XDRV_I2S_MODE_MASTER, XDRV_SAMPLING_RATE_48KHZ, + XDRV_SAMPLING_WIDTH_16, + XDRV_I2S_TRANSMISSION_MODE_NORMAL, + XDRV_I2S_SETTINGS_NORMAL, + XDRV_AUDIO_MODE_STEREO, + XDRV_I2S_CONFIGURATION_MODE_UPDATE_ALL, + XDRV_SOURCE_TRANSDUCER_USER_DEFINED_15); + xdrv_configure_destination(asd->chat, XDRV_DESTINATION_I2SY_TX, + XDRV_I2S_CLOCK_0, XDRV_I2S_MODE_MASTER, + XDRV_SAMPLING_RATE_48KHZ, + XDRV_SAMPLING_WIDTH_16, + XDRV_I2S_TRANSMISSION_MODE_NORMAL, + XDRV_I2S_SETTINGS_NORMAL, + XDRV_AUDIO_MODE_STEREO, + XDRV_I2S_CONFIGURATION_MODE_UPDATE_ALL, + XDRV_DEST_TRANSDUCER_USER_DEFINED_15); + + /* Seems unnecessary + xdrv_set_destination_for_source(asd->chat, XDRV_SOURCE_SPEECH_RX, + XDRV_DESTINATION_PCM_GENERAL); + */ + xdrv_set_destination_for_source(asd->chat, XDRV_SOURCE_I2SX_RX, + XDRV_DESTINATION_SPEECH_TX); + xdrv_set_destination_for_source(asd->chat, XDRV_SOURCE_I2SY_RX, + XDRV_DESTINATION_I2SX_TX); + xdrv_set_destination_for_source(asd->chat, XDRV_SOURCE_SIMPLE_TONES, + XDRV_DESTINATION_I2SX_TX); + + xdrv_enable_source(asd->chat, XDRV_SOURCE_I2SX_RX); + xdrv_enable_source(asd->chat, XDRV_SOURCE_I2SY_RX); + + xdrv_set_destination_for_source(asd->chat, XDRV_SOURCE_SPEECH_RX, + XDRV_DESTINATION_I2SX_TX); + + /* Unmute */ + xdrv_set_destination_volume(asd->chat, XDRV_DESTINATION_I2SX_TX, 66); + xdrv_set_destination_volume(asd->chat, XDRV_DESTINATION_SPEECH_TX, 100); +} + static void xprogress_notify(GAtResult *result, gpointer user_data) { struct ofono_audio_settings *as = user_data; @@ -103,6 +351,8 @@ static void xprogress_support_cb(gboolean ok, GAtResult *result, ofono_audio_settings_register(as); + send_xdrv_setup_sequence(as); + modem = ofono_audio_settings_get_modem(as); setting = ofono_modem_get_string(modem, "AudioSetting");