1b7482f52SPhilipp Zabel /* 2b7482f52SPhilipp Zabel * uda1380.c - Philips UDA1380 ALSA SoC audio driver 3b7482f52SPhilipp Zabel * 4b7482f52SPhilipp Zabel * This program is free software; you can redistribute it and/or modify 5b7482f52SPhilipp Zabel * it under the terms of the GNU General Public License version 2 as 6b7482f52SPhilipp Zabel * published by the Free Software Foundation. 7b7482f52SPhilipp Zabel * 81abd9184SPhilipp Zabel * Copyright (c) 2007-2009 Philipp Zabel <philipp.zabel@gmail.com> 9b7482f52SPhilipp Zabel * 10b7482f52SPhilipp Zabel * Modified by Richard Purdie <richard@openedhand.com> to fit into SoC 11b7482f52SPhilipp Zabel * codec model. 12b7482f52SPhilipp Zabel * 13b7482f52SPhilipp Zabel * Copyright (c) 2005 Giorgio Padrin <giorgio@mandarinlogiq.org> 14b7482f52SPhilipp Zabel * Copyright 2005 Openedhand Ltd. 15b7482f52SPhilipp Zabel */ 16b7482f52SPhilipp Zabel 17b7482f52SPhilipp Zabel #include <linux/module.h> 18b7482f52SPhilipp Zabel #include <linux/init.h> 19b7482f52SPhilipp Zabel #include <linux/types.h> 20b7482f52SPhilipp Zabel #include <linux/slab.h> 21b7482f52SPhilipp Zabel #include <linux/errno.h> 221abd9184SPhilipp Zabel #include <linux/gpio.h> 23b7482f52SPhilipp Zabel #include <linux/delay.h> 24b7482f52SPhilipp Zabel #include <linux/i2c.h> 25ef9e5e5cSPhilipp Zabel #include <linux/workqueue.h> 26b7482f52SPhilipp Zabel #include <sound/core.h> 27b7482f52SPhilipp Zabel #include <sound/control.h> 28b7482f52SPhilipp Zabel #include <sound/initval.h> 29b7482f52SPhilipp Zabel #include <sound/soc.h> 30b7482f52SPhilipp Zabel #include <sound/tlv.h> 311abd9184SPhilipp Zabel #include <sound/uda1380.h> 32b7482f52SPhilipp Zabel 33b7482f52SPhilipp Zabel #include "uda1380.h" 34b7482f52SPhilipp Zabel 351abd9184SPhilipp Zabel /* codec private data */ 361abd9184SPhilipp Zabel struct uda1380_priv { 37f0fba2adSLiam Girdwood struct snd_soc_codec *codec; 381abd9184SPhilipp Zabel unsigned int dac_clk; 391abd9184SPhilipp Zabel struct work_struct work; 40*eaa53216SKuninori Morimoto struct i2c_client *i2c; 411abd9184SPhilipp Zabel }; 421abd9184SPhilipp Zabel 43b7482f52SPhilipp Zabel /* 44b7482f52SPhilipp Zabel * uda1380 register cache 45b7482f52SPhilipp Zabel */ 46b7482f52SPhilipp Zabel static const u16 uda1380_reg[UDA1380_CACHEREGNUM] = { 47b7482f52SPhilipp Zabel 0x0502, 0x0000, 0x0000, 0x3f3f, 48b7482f52SPhilipp Zabel 0x0202, 0x0000, 0x0000, 0x0000, 49b7482f52SPhilipp Zabel 0x0000, 0x0000, 0x0000, 0x0000, 50b7482f52SPhilipp Zabel 0x0000, 0x0000, 0x0000, 0x0000, 51b7482f52SPhilipp Zabel 0x0000, 0xff00, 0x0000, 0x4800, 52b7482f52SPhilipp Zabel 0x0000, 0x0000, 0x0000, 0x0000, 53b7482f52SPhilipp Zabel 0x0000, 0x0000, 0x0000, 0x0000, 54b7482f52SPhilipp Zabel 0x0000, 0x0000, 0x0000, 0x0000, 55b7482f52SPhilipp Zabel 0x0000, 0x8000, 0x0002, 0x0000, 56b7482f52SPhilipp Zabel }; 57b7482f52SPhilipp Zabel 58ef9e5e5cSPhilipp Zabel static unsigned long uda1380_cache_dirty; 59ef9e5e5cSPhilipp Zabel 60b7482f52SPhilipp Zabel /* 61b7482f52SPhilipp Zabel * read uda1380 register cache 62b7482f52SPhilipp Zabel */ 63b7482f52SPhilipp Zabel static inline unsigned int uda1380_read_reg_cache(struct snd_soc_codec *codec, 64b7482f52SPhilipp Zabel unsigned int reg) 65b7482f52SPhilipp Zabel { 66b7482f52SPhilipp Zabel u16 *cache = codec->reg_cache; 67b7482f52SPhilipp Zabel if (reg == UDA1380_RESET) 68b7482f52SPhilipp Zabel return 0; 69b7482f52SPhilipp Zabel if (reg >= UDA1380_CACHEREGNUM) 70b7482f52SPhilipp Zabel return -1; 71b7482f52SPhilipp Zabel return cache[reg]; 72b7482f52SPhilipp Zabel } 73b7482f52SPhilipp Zabel 74b7482f52SPhilipp Zabel /* 75b7482f52SPhilipp Zabel * write uda1380 register cache 76b7482f52SPhilipp Zabel */ 77b7482f52SPhilipp Zabel static inline void uda1380_write_reg_cache(struct snd_soc_codec *codec, 78b7482f52SPhilipp Zabel u16 reg, unsigned int value) 79b7482f52SPhilipp Zabel { 80b7482f52SPhilipp Zabel u16 *cache = codec->reg_cache; 81ef9e5e5cSPhilipp Zabel 82b7482f52SPhilipp Zabel if (reg >= UDA1380_CACHEREGNUM) 83b7482f52SPhilipp Zabel return; 84ef9e5e5cSPhilipp Zabel if ((reg >= 0x10) && (cache[reg] != value)) 85ef9e5e5cSPhilipp Zabel set_bit(reg - 0x10, &uda1380_cache_dirty); 86b7482f52SPhilipp Zabel cache[reg] = value; 87b7482f52SPhilipp Zabel } 88b7482f52SPhilipp Zabel 89b7482f52SPhilipp Zabel /* 90b7482f52SPhilipp Zabel * write to the UDA1380 register space 91b7482f52SPhilipp Zabel */ 92b7482f52SPhilipp Zabel static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, 93b7482f52SPhilipp Zabel unsigned int value) 94b7482f52SPhilipp Zabel { 95*eaa53216SKuninori Morimoto struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); 96b7482f52SPhilipp Zabel u8 data[3]; 97b7482f52SPhilipp Zabel 98b7482f52SPhilipp Zabel /* data is 99b7482f52SPhilipp Zabel * data[0] is register offset 100b7482f52SPhilipp Zabel * data[1] is MS byte 101b7482f52SPhilipp Zabel * data[2] is LS byte 102b7482f52SPhilipp Zabel */ 103b7482f52SPhilipp Zabel data[0] = reg; 104b7482f52SPhilipp Zabel data[1] = (value & 0xff00) >> 8; 105b7482f52SPhilipp Zabel data[2] = value & 0x00ff; 106b7482f52SPhilipp Zabel 107b7482f52SPhilipp Zabel uda1380_write_reg_cache(codec, reg, value); 108b7482f52SPhilipp Zabel 109b7482f52SPhilipp Zabel /* the interpolator & decimator regs must only be written when the 110b7482f52SPhilipp Zabel * codec DAI is active. 111b7482f52SPhilipp Zabel */ 1125c898e74SLars-Peter Clausen if (!snd_soc_codec_is_active(codec) && (reg >= UDA1380_MVOL)) 113b7482f52SPhilipp Zabel return 0; 114b7482f52SPhilipp Zabel pr_debug("uda1380: hw write %x val %x\n", reg, value); 115*eaa53216SKuninori Morimoto if (i2c_master_send(uda1380->i2c, data, 3) == 3) { 116b7482f52SPhilipp Zabel unsigned int val; 117*eaa53216SKuninori Morimoto i2c_master_send(uda1380->i2c, data, 1); 118*eaa53216SKuninori Morimoto i2c_master_recv(uda1380->i2c, data, 2); 119b7482f52SPhilipp Zabel val = (data[0]<<8) | data[1]; 120b7482f52SPhilipp Zabel if (val != value) { 121b7482f52SPhilipp Zabel pr_debug("uda1380: READ BACK VAL %x\n", 122b7482f52SPhilipp Zabel (data[0]<<8) | data[1]); 123b7482f52SPhilipp Zabel return -EIO; 124b7482f52SPhilipp Zabel } 125ef9e5e5cSPhilipp Zabel if (reg >= 0x10) 126ef9e5e5cSPhilipp Zabel clear_bit(reg - 0x10, &uda1380_cache_dirty); 127b7482f52SPhilipp Zabel return 0; 128b7482f52SPhilipp Zabel } else 129b7482f52SPhilipp Zabel return -EIO; 130b7482f52SPhilipp Zabel } 131b7482f52SPhilipp Zabel 1328614d310SVasily Khoruzhick static void uda1380_sync_cache(struct snd_soc_codec *codec) 1338614d310SVasily Khoruzhick { 134*eaa53216SKuninori Morimoto struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); 1358614d310SVasily Khoruzhick int reg; 1368614d310SVasily Khoruzhick u8 data[3]; 1378614d310SVasily Khoruzhick u16 *cache = codec->reg_cache; 1388614d310SVasily Khoruzhick 1398614d310SVasily Khoruzhick /* Sync reg_cache with the hardware */ 1408614d310SVasily Khoruzhick for (reg = 0; reg < UDA1380_MVOL; reg++) { 1418614d310SVasily Khoruzhick data[0] = reg; 1428614d310SVasily Khoruzhick data[1] = (cache[reg] & 0xff00) >> 8; 1438614d310SVasily Khoruzhick data[2] = cache[reg] & 0x00ff; 144*eaa53216SKuninori Morimoto if (i2c_master_send(uda1380->i2c, data, 3) != 3) 1458614d310SVasily Khoruzhick dev_err(codec->dev, "%s: write to reg 0x%x failed\n", 1468614d310SVasily Khoruzhick __func__, reg); 1478614d310SVasily Khoruzhick } 1488614d310SVasily Khoruzhick } 1498614d310SVasily Khoruzhick 1508614d310SVasily Khoruzhick static int uda1380_reset(struct snd_soc_codec *codec) 1518614d310SVasily Khoruzhick { 1528614d310SVasily Khoruzhick struct uda1380_platform_data *pdata = codec->dev->platform_data; 153*eaa53216SKuninori Morimoto struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); 1548614d310SVasily Khoruzhick 1558614d310SVasily Khoruzhick if (gpio_is_valid(pdata->gpio_reset)) { 1568614d310SVasily Khoruzhick gpio_set_value(pdata->gpio_reset, 1); 1578614d310SVasily Khoruzhick mdelay(1); 1588614d310SVasily Khoruzhick gpio_set_value(pdata->gpio_reset, 0); 1598614d310SVasily Khoruzhick } else { 1608614d310SVasily Khoruzhick u8 data[3]; 1618614d310SVasily Khoruzhick 1628614d310SVasily Khoruzhick data[0] = UDA1380_RESET; 1638614d310SVasily Khoruzhick data[1] = 0; 1648614d310SVasily Khoruzhick data[2] = 0; 1658614d310SVasily Khoruzhick 166*eaa53216SKuninori Morimoto if (i2c_master_send(uda1380->i2c, data, 3) != 3) { 1678614d310SVasily Khoruzhick dev_err(codec->dev, "%s: failed\n", __func__); 1688614d310SVasily Khoruzhick return -EIO; 1698614d310SVasily Khoruzhick } 1708614d310SVasily Khoruzhick } 1718614d310SVasily Khoruzhick 1728614d310SVasily Khoruzhick return 0; 1738614d310SVasily Khoruzhick } 174b7482f52SPhilipp Zabel 175ef9e5e5cSPhilipp Zabel static void uda1380_flush_work(struct work_struct *work) 176ef9e5e5cSPhilipp Zabel { 177f0fba2adSLiam Girdwood struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work); 178f0fba2adSLiam Girdwood struct snd_soc_codec *uda1380_codec = uda1380->codec; 179ef9e5e5cSPhilipp Zabel int bit, reg; 180ef9e5e5cSPhilipp Zabel 181984b3f57SAkinobu Mita for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { 182ef9e5e5cSPhilipp Zabel reg = 0x10 + bit; 183ef9e5e5cSPhilipp Zabel pr_debug("uda1380: flush reg %x val %x:\n", reg, 184ef9e5e5cSPhilipp Zabel uda1380_read_reg_cache(uda1380_codec, reg)); 185ef9e5e5cSPhilipp Zabel uda1380_write(uda1380_codec, reg, 186ef9e5e5cSPhilipp Zabel uda1380_read_reg_cache(uda1380_codec, reg)); 187ef9e5e5cSPhilipp Zabel clear_bit(bit, &uda1380_cache_dirty); 188ef9e5e5cSPhilipp Zabel } 189f0fba2adSLiam Girdwood 190ef9e5e5cSPhilipp Zabel } 191ef9e5e5cSPhilipp Zabel 192b7482f52SPhilipp Zabel /* declarations of ALSA reg_elem_REAL controls */ 193b7482f52SPhilipp Zabel static const char *uda1380_deemp[] = { 194b7482f52SPhilipp Zabel "None", 195b7482f52SPhilipp Zabel "32kHz", 196b7482f52SPhilipp Zabel "44.1kHz", 197b7482f52SPhilipp Zabel "48kHz", 198b7482f52SPhilipp Zabel "96kHz", 199b7482f52SPhilipp Zabel }; 200b7482f52SPhilipp Zabel static const char *uda1380_input_sel[] = { 201b7482f52SPhilipp Zabel "Line", 202b7482f52SPhilipp Zabel "Mic + Line R", 203b7482f52SPhilipp Zabel "Line L", 204b7482f52SPhilipp Zabel "Mic", 205b7482f52SPhilipp Zabel }; 206b7482f52SPhilipp Zabel static const char *uda1380_output_sel[] = { 207b7482f52SPhilipp Zabel "DAC", 208b7482f52SPhilipp Zabel "Analog Mixer", 209b7482f52SPhilipp Zabel }; 210b7482f52SPhilipp Zabel static const char *uda1380_spf_mode[] = { 211b7482f52SPhilipp Zabel "Flat", 212b7482f52SPhilipp Zabel "Minimum1", 213b7482f52SPhilipp Zabel "Minimum2", 214b7482f52SPhilipp Zabel "Maximum" 215b7482f52SPhilipp Zabel }; 216b7482f52SPhilipp Zabel static const char *uda1380_capture_sel[] = { 217b7482f52SPhilipp Zabel "ADC", 218b7482f52SPhilipp Zabel "Digital Mixer" 219b7482f52SPhilipp Zabel }; 220b7482f52SPhilipp Zabel static const char *uda1380_sel_ns[] = { 221b7482f52SPhilipp Zabel "3rd-order", 222b7482f52SPhilipp Zabel "5th-order" 223b7482f52SPhilipp Zabel }; 224b7482f52SPhilipp Zabel static const char *uda1380_mix_control[] = { 225b7482f52SPhilipp Zabel "off", 226b7482f52SPhilipp Zabel "PCM only", 227b7482f52SPhilipp Zabel "before sound processing", 228b7482f52SPhilipp Zabel "after sound processing" 229b7482f52SPhilipp Zabel }; 230b7482f52SPhilipp Zabel static const char *uda1380_sdet_setting[] = { 231b7482f52SPhilipp Zabel "3200", 232b7482f52SPhilipp Zabel "4800", 233b7482f52SPhilipp Zabel "9600", 234b7482f52SPhilipp Zabel "19200" 235b7482f52SPhilipp Zabel }; 236b7482f52SPhilipp Zabel static const char *uda1380_os_setting[] = { 237b7482f52SPhilipp Zabel "single-speed", 238b7482f52SPhilipp Zabel "double-speed (no mixing)", 239b7482f52SPhilipp Zabel "quad-speed (no mixing)" 240b7482f52SPhilipp Zabel }; 241b7482f52SPhilipp Zabel 242b7482f52SPhilipp Zabel static const struct soc_enum uda1380_deemp_enum[] = { 2431dbb348dSTakashi Iwai SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, ARRAY_SIZE(uda1380_deemp), 2441dbb348dSTakashi Iwai uda1380_deemp), 2451dbb348dSTakashi Iwai SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, ARRAY_SIZE(uda1380_deemp), 2461dbb348dSTakashi Iwai uda1380_deemp), 247b7482f52SPhilipp Zabel }; 2481dbb348dSTakashi Iwai static SOC_ENUM_SINGLE_DECL(uda1380_input_sel_enum, 2491dbb348dSTakashi Iwai UDA1380_ADC, 2, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ 2501dbb348dSTakashi Iwai static SOC_ENUM_SINGLE_DECL(uda1380_output_sel_enum, 2511dbb348dSTakashi Iwai UDA1380_PM, 7, uda1380_output_sel); /* R02_EN_AVC */ 2521dbb348dSTakashi Iwai static SOC_ENUM_SINGLE_DECL(uda1380_spf_enum, 2531dbb348dSTakashi Iwai UDA1380_MODE, 14, uda1380_spf_mode); /* M */ 2541dbb348dSTakashi Iwai static SOC_ENUM_SINGLE_DECL(uda1380_capture_sel_enum, 2551dbb348dSTakashi Iwai UDA1380_IFACE, 6, uda1380_capture_sel); /* SEL_SOURCE */ 2561dbb348dSTakashi Iwai static SOC_ENUM_SINGLE_DECL(uda1380_sel_ns_enum, 2571dbb348dSTakashi Iwai UDA1380_MIXER, 14, uda1380_sel_ns); /* SEL_NS */ 2581dbb348dSTakashi Iwai static SOC_ENUM_SINGLE_DECL(uda1380_mix_enum, 2591dbb348dSTakashi Iwai UDA1380_MIXER, 12, uda1380_mix_control); /* MIX, MIX_POS */ 2601dbb348dSTakashi Iwai static SOC_ENUM_SINGLE_DECL(uda1380_sdet_enum, 2611dbb348dSTakashi Iwai UDA1380_MIXER, 4, uda1380_sdet_setting); /* SD_VALUE */ 2621dbb348dSTakashi Iwai static SOC_ENUM_SINGLE_DECL(uda1380_os_enum, 2631dbb348dSTakashi Iwai UDA1380_MIXER, 0, uda1380_os_setting); /* OS */ 264b7482f52SPhilipp Zabel 265b7482f52SPhilipp Zabel /* 266b7482f52SPhilipp Zabel * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB) 267b7482f52SPhilipp Zabel */ 268b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(amix_tlv, -4950, 150, 1); 269b7482f52SPhilipp Zabel 270b7482f52SPhilipp Zabel /* 271b7482f52SPhilipp Zabel * from -78 dB in 1 dB steps (3 dB steps, really. LSB are ignored), 272b7482f52SPhilipp Zabel * from -66 dB in 0.5 dB steps (2 dB steps, really) and 273b7482f52SPhilipp Zabel * from -52 dB in 0.25 dB steps 274b7482f52SPhilipp Zabel */ 2755ee0b8f8SLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(mvol_tlv, 276b7482f52SPhilipp Zabel 0, 15, TLV_DB_SCALE_ITEM(-8200, 100, 1), 277b7482f52SPhilipp Zabel 16, 43, TLV_DB_SCALE_ITEM(-6600, 50, 0), 2785ee0b8f8SLars-Peter Clausen 44, 252, TLV_DB_SCALE_ITEM(-5200, 25, 0) 2795ee0b8f8SLars-Peter Clausen ); 280b7482f52SPhilipp Zabel 281b7482f52SPhilipp Zabel /* 282b7482f52SPhilipp Zabel * from -72 dB in 1.5 dB steps (6 dB steps really), 283b7482f52SPhilipp Zabel * from -66 dB in 0.75 dB steps (3 dB steps really), 284b7482f52SPhilipp Zabel * from -60 dB in 0.5 dB steps (2 dB steps really) and 285b7482f52SPhilipp Zabel * from -46 dB in 0.25 dB steps 286b7482f52SPhilipp Zabel */ 2875ee0b8f8SLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(vc_tlv, 288b7482f52SPhilipp Zabel 0, 7, TLV_DB_SCALE_ITEM(-7800, 150, 1), 289b7482f52SPhilipp Zabel 8, 15, TLV_DB_SCALE_ITEM(-6600, 75, 0), 290b7482f52SPhilipp Zabel 16, 43, TLV_DB_SCALE_ITEM(-6000, 50, 0), 2915ee0b8f8SLars-Peter Clausen 44, 228, TLV_DB_SCALE_ITEM(-4600, 25, 0) 2925ee0b8f8SLars-Peter Clausen ); 293b7482f52SPhilipp Zabel 294b7482f52SPhilipp Zabel /* from 0 to 6 dB in 2 dB steps if SPF mode != flat */ 295b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(tr_tlv, 0, 200, 0); 296b7482f52SPhilipp Zabel 297b7482f52SPhilipp Zabel /* from 0 to 24 dB in 2 dB steps, if SPF mode == maximum, otherwise cuts 298b7482f52SPhilipp Zabel * off at 18 dB max) */ 299b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(bb_tlv, 0, 200, 0); 300b7482f52SPhilipp Zabel 301b7482f52SPhilipp Zabel /* from -63 to 24 dB in 0.5 dB steps (-128...48) */ 302b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(dec_tlv, -6400, 50, 1); 303b7482f52SPhilipp Zabel 304b7482f52SPhilipp Zabel /* from 0 to 24 dB in 3 dB steps */ 305b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0); 306b7482f52SPhilipp Zabel 307b7482f52SPhilipp Zabel /* from 0 to 30 dB in 2 dB steps */ 308b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(vga_tlv, 0, 200, 0); 309b7482f52SPhilipp Zabel 310b7482f52SPhilipp Zabel static const struct snd_kcontrol_new uda1380_snd_controls[] = { 311b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Analog Mixer Volume", UDA1380_AMIX, 0, 8, 44, 1, amix_tlv), /* AVCR, AVCL */ 312b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Master Playback Volume", UDA1380_MVOL, 0, 8, 252, 1, mvol_tlv), /* MVCL, MVCR */ 313b7482f52SPhilipp Zabel SOC_SINGLE_TLV("ADC Playback Volume", UDA1380_MIXVOL, 8, 228, 1, vc_tlv), /* VC2 */ 314b7482f52SPhilipp Zabel SOC_SINGLE_TLV("PCM Playback Volume", UDA1380_MIXVOL, 0, 228, 1, vc_tlv), /* VC1 */ 315b7482f52SPhilipp Zabel SOC_ENUM("Sound Processing Filter", uda1380_spf_enum), /* M */ 316b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Tone Control - Treble", UDA1380_MODE, 4, 12, 3, 0, tr_tlv), /* TRL, TRR */ 317b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Tone Control - Bass", UDA1380_MODE, 0, 8, 15, 0, bb_tlv), /* BBL, BBR */ 318b7482f52SPhilipp Zabel /**/ SOC_SINGLE("Master Playback Switch", UDA1380_DEEMP, 14, 1, 1), /* MTM */ 319b7482f52SPhilipp Zabel SOC_SINGLE("ADC Playback Switch", UDA1380_DEEMP, 11, 1, 1), /* MT2 from decimation filter */ 320b7482f52SPhilipp Zabel SOC_ENUM("ADC Playback De-emphasis", uda1380_deemp_enum[0]), /* DE2 */ 321b7482f52SPhilipp Zabel SOC_SINGLE("PCM Playback Switch", UDA1380_DEEMP, 3, 1, 1), /* MT1, from digital data input */ 322b7482f52SPhilipp Zabel SOC_ENUM("PCM Playback De-emphasis", uda1380_deemp_enum[1]), /* DE1 */ 323b7482f52SPhilipp Zabel SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0), /* DA_POL_INV */ 324b7482f52SPhilipp Zabel SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum), /* SEL_NS */ 325b7482f52SPhilipp Zabel SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum), /* MIX_POS, MIX */ 326b7482f52SPhilipp Zabel SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0), /* SDET_ON */ 327b7482f52SPhilipp Zabel SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum), /* SD_VALUE */ 328b7482f52SPhilipp Zabel SOC_ENUM("Oversampling Input", uda1380_os_enum), /* OS */ 329b7482f52SPhilipp Zabel SOC_DOUBLE_S8_TLV("ADC Capture Volume", UDA1380_DEC, -128, 48, dec_tlv), /* ML_DEC, MR_DEC */ 330b7482f52SPhilipp Zabel /**/ SOC_SINGLE("ADC Capture Switch", UDA1380_PGA, 15, 1, 1), /* MT_ADC */ 331b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Line Capture Volume", UDA1380_PGA, 0, 8, 8, 0, pga_tlv), /* PGA_GAINCTRLL, PGA_GAINCTRLR */ 332b7482f52SPhilipp Zabel SOC_SINGLE("ADC Polarity inverting Switch", UDA1380_ADC, 12, 1, 0), /* ADCPOL_INV */ 333b7482f52SPhilipp Zabel SOC_SINGLE_TLV("Mic Capture Volume", UDA1380_ADC, 8, 15, 0, vga_tlv), /* VGA_CTRL */ 334b7482f52SPhilipp Zabel SOC_SINGLE("DC Filter Bypass Switch", UDA1380_ADC, 1, 1, 0), /* SKIP_DCFIL (before decimator) */ 335b7482f52SPhilipp Zabel SOC_SINGLE("DC Filter Enable Switch", UDA1380_ADC, 0, 1, 0), /* EN_DCFIL (at output of decimator) */ 336b7482f52SPhilipp Zabel SOC_SINGLE("AGC Timing", UDA1380_AGC, 8, 7, 0), /* TODO: enum, see table 62 */ 337b7482f52SPhilipp Zabel SOC_SINGLE("AGC Target level", UDA1380_AGC, 2, 3, 1), /* AGC_LEVEL */ 338b7482f52SPhilipp Zabel /* -5.5, -8, -11.5, -14 dBFS */ 339b7482f52SPhilipp Zabel SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0), 340b7482f52SPhilipp Zabel }; 341b7482f52SPhilipp Zabel 342b7482f52SPhilipp Zabel /* Input mux */ 343b7482f52SPhilipp Zabel static const struct snd_kcontrol_new uda1380_input_mux_control = 344b7482f52SPhilipp Zabel SOC_DAPM_ENUM("Route", uda1380_input_sel_enum); 345b7482f52SPhilipp Zabel 346b7482f52SPhilipp Zabel /* Output mux */ 347b7482f52SPhilipp Zabel static const struct snd_kcontrol_new uda1380_output_mux_control = 348b7482f52SPhilipp Zabel SOC_DAPM_ENUM("Route", uda1380_output_sel_enum); 349b7482f52SPhilipp Zabel 350b7482f52SPhilipp Zabel /* Capture mux */ 351b7482f52SPhilipp Zabel static const struct snd_kcontrol_new uda1380_capture_mux_control = 352b7482f52SPhilipp Zabel SOC_DAPM_ENUM("Route", uda1380_capture_sel_enum); 353b7482f52SPhilipp Zabel 354b7482f52SPhilipp Zabel 355b7482f52SPhilipp Zabel static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = { 356b7482f52SPhilipp Zabel SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, 357b7482f52SPhilipp Zabel &uda1380_input_mux_control), 358b7482f52SPhilipp Zabel SND_SOC_DAPM_MUX("Output Mux", SND_SOC_NOPM, 0, 0, 359b7482f52SPhilipp Zabel &uda1380_output_mux_control), 360b7482f52SPhilipp Zabel SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, 361b7482f52SPhilipp Zabel &uda1380_capture_mux_control), 362b7482f52SPhilipp Zabel SND_SOC_DAPM_PGA("Left PGA", UDA1380_PM, 3, 0, NULL, 0), 363b7482f52SPhilipp Zabel SND_SOC_DAPM_PGA("Right PGA", UDA1380_PM, 1, 0, NULL, 0), 364b7482f52SPhilipp Zabel SND_SOC_DAPM_PGA("Mic LNA", UDA1380_PM, 4, 0, NULL, 0), 365b7482f52SPhilipp Zabel SND_SOC_DAPM_ADC("Left ADC", "Left Capture", UDA1380_PM, 2, 0), 366b7482f52SPhilipp Zabel SND_SOC_DAPM_ADC("Right ADC", "Right Capture", UDA1380_PM, 0, 0), 367b7482f52SPhilipp Zabel SND_SOC_DAPM_INPUT("VINM"), 368b7482f52SPhilipp Zabel SND_SOC_DAPM_INPUT("VINL"), 369b7482f52SPhilipp Zabel SND_SOC_DAPM_INPUT("VINR"), 370b7482f52SPhilipp Zabel SND_SOC_DAPM_MIXER("Analog Mixer", UDA1380_PM, 6, 0, NULL, 0), 371b7482f52SPhilipp Zabel SND_SOC_DAPM_OUTPUT("VOUTLHP"), 372b7482f52SPhilipp Zabel SND_SOC_DAPM_OUTPUT("VOUTRHP"), 373b7482f52SPhilipp Zabel SND_SOC_DAPM_OUTPUT("VOUTL"), 374b7482f52SPhilipp Zabel SND_SOC_DAPM_OUTPUT("VOUTR"), 375b7482f52SPhilipp Zabel SND_SOC_DAPM_DAC("DAC", "Playback", UDA1380_PM, 10, 0), 376b7482f52SPhilipp Zabel SND_SOC_DAPM_PGA("HeadPhone Driver", UDA1380_PM, 13, 0, NULL, 0), 377b7482f52SPhilipp Zabel }; 378b7482f52SPhilipp Zabel 37958fa8e45SAxel Lin static const struct snd_soc_dapm_route uda1380_dapm_routes[] = { 380b7482f52SPhilipp Zabel 381b7482f52SPhilipp Zabel /* output mux */ 382b7482f52SPhilipp Zabel {"HeadPhone Driver", NULL, "Output Mux"}, 383b7482f52SPhilipp Zabel {"VOUTR", NULL, "Output Mux"}, 384b7482f52SPhilipp Zabel {"VOUTL", NULL, "Output Mux"}, 385b7482f52SPhilipp Zabel 386b7482f52SPhilipp Zabel {"Analog Mixer", NULL, "VINR"}, 387b7482f52SPhilipp Zabel {"Analog Mixer", NULL, "VINL"}, 388b7482f52SPhilipp Zabel {"Analog Mixer", NULL, "DAC"}, 389b7482f52SPhilipp Zabel 390b7482f52SPhilipp Zabel {"Output Mux", "DAC", "DAC"}, 391b7482f52SPhilipp Zabel {"Output Mux", "Analog Mixer", "Analog Mixer"}, 392b7482f52SPhilipp Zabel 393b7482f52SPhilipp Zabel /* {"DAC", "Digital Mixer", "I2S" } */ 394b7482f52SPhilipp Zabel 395b7482f52SPhilipp Zabel /* headphone driver */ 396b7482f52SPhilipp Zabel {"VOUTLHP", NULL, "HeadPhone Driver"}, 397b7482f52SPhilipp Zabel {"VOUTRHP", NULL, "HeadPhone Driver"}, 398b7482f52SPhilipp Zabel 399b7482f52SPhilipp Zabel /* input mux */ 400b7482f52SPhilipp Zabel {"Left ADC", NULL, "Input Mux"}, 401b7482f52SPhilipp Zabel {"Input Mux", "Mic", "Mic LNA"}, 402b7482f52SPhilipp Zabel {"Input Mux", "Mic + Line R", "Mic LNA"}, 403b7482f52SPhilipp Zabel {"Input Mux", "Line L", "Left PGA"}, 404b7482f52SPhilipp Zabel {"Input Mux", "Line", "Left PGA"}, 405b7482f52SPhilipp Zabel 406b7482f52SPhilipp Zabel /* right input */ 407b7482f52SPhilipp Zabel {"Right ADC", "Mic + Line R", "Right PGA"}, 408b7482f52SPhilipp Zabel {"Right ADC", "Line", "Right PGA"}, 409b7482f52SPhilipp Zabel 410b7482f52SPhilipp Zabel /* inputs */ 411b7482f52SPhilipp Zabel {"Mic LNA", NULL, "VINM"}, 412b7482f52SPhilipp Zabel {"Left PGA", NULL, "VINL"}, 413b7482f52SPhilipp Zabel {"Right PGA", NULL, "VINR"}, 414b7482f52SPhilipp Zabel }; 415b7482f52SPhilipp Zabel 4165b247442SPhilipp Zabel static int uda1380_set_dai_fmt_both(struct snd_soc_dai *codec_dai, 417b7482f52SPhilipp Zabel unsigned int fmt) 418b7482f52SPhilipp Zabel { 419b7482f52SPhilipp Zabel struct snd_soc_codec *codec = codec_dai->codec; 420b7482f52SPhilipp Zabel int iface; 421b7482f52SPhilipp Zabel 422b7482f52SPhilipp Zabel /* set up DAI based upon fmt */ 423b7482f52SPhilipp Zabel iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); 424b7482f52SPhilipp Zabel iface &= ~(R01_SFORI_MASK | R01_SIM | R01_SFORO_MASK); 425b7482f52SPhilipp Zabel 426b7482f52SPhilipp Zabel switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 427b7482f52SPhilipp Zabel case SND_SOC_DAIFMT_I2S: 428b7482f52SPhilipp Zabel iface |= R01_SFORI_I2S | R01_SFORO_I2S; 429b7482f52SPhilipp Zabel break; 430b7482f52SPhilipp Zabel case SND_SOC_DAIFMT_LSB: 4315b247442SPhilipp Zabel iface |= R01_SFORI_LSB16 | R01_SFORO_LSB16; 432b7482f52SPhilipp Zabel break; 433b7482f52SPhilipp Zabel case SND_SOC_DAIFMT_MSB: 4345b247442SPhilipp Zabel iface |= R01_SFORI_MSB | R01_SFORO_MSB; 4355b247442SPhilipp Zabel } 4365b247442SPhilipp Zabel 4375f2a9384SPhilipp Zabel /* DATAI is slave only, so in single-link mode, this has to be slave */ 4385f2a9384SPhilipp Zabel if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) 4395f2a9384SPhilipp Zabel return -EINVAL; 4405b247442SPhilipp Zabel 441810e4425SVasily Khoruzhick uda1380_write_reg_cache(codec, UDA1380_IFACE, iface); 4425b247442SPhilipp Zabel 4435b247442SPhilipp Zabel return 0; 4445b247442SPhilipp Zabel } 4455b247442SPhilipp Zabel 4465b247442SPhilipp Zabel static int uda1380_set_dai_fmt_playback(struct snd_soc_dai *codec_dai, 4475b247442SPhilipp Zabel unsigned int fmt) 4485b247442SPhilipp Zabel { 4495b247442SPhilipp Zabel struct snd_soc_codec *codec = codec_dai->codec; 4505b247442SPhilipp Zabel int iface; 4515b247442SPhilipp Zabel 4525b247442SPhilipp Zabel /* set up DAI based upon fmt */ 4535b247442SPhilipp Zabel iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); 4545b247442SPhilipp Zabel iface &= ~R01_SFORI_MASK; 4555b247442SPhilipp Zabel 4565b247442SPhilipp Zabel switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 4575b247442SPhilipp Zabel case SND_SOC_DAIFMT_I2S: 4585b247442SPhilipp Zabel iface |= R01_SFORI_I2S; 4595b247442SPhilipp Zabel break; 4605b247442SPhilipp Zabel case SND_SOC_DAIFMT_LSB: 4615b247442SPhilipp Zabel iface |= R01_SFORI_LSB16; 4625b247442SPhilipp Zabel break; 4635b247442SPhilipp Zabel case SND_SOC_DAIFMT_MSB: 4645b247442SPhilipp Zabel iface |= R01_SFORI_MSB; 4655b247442SPhilipp Zabel } 4665b247442SPhilipp Zabel 4675f2a9384SPhilipp Zabel /* DATAI is slave only, so this has to be slave */ 4685f2a9384SPhilipp Zabel if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) 4695f2a9384SPhilipp Zabel return -EINVAL; 4705f2a9384SPhilipp Zabel 4715b247442SPhilipp Zabel uda1380_write(codec, UDA1380_IFACE, iface); 4725b247442SPhilipp Zabel 4735b247442SPhilipp Zabel return 0; 4745b247442SPhilipp Zabel } 4755b247442SPhilipp Zabel 4765b247442SPhilipp Zabel static int uda1380_set_dai_fmt_capture(struct snd_soc_dai *codec_dai, 4775b247442SPhilipp Zabel unsigned int fmt) 4785b247442SPhilipp Zabel { 4795b247442SPhilipp Zabel struct snd_soc_codec *codec = codec_dai->codec; 4805b247442SPhilipp Zabel int iface; 4815b247442SPhilipp Zabel 4825b247442SPhilipp Zabel /* set up DAI based upon fmt */ 4835b247442SPhilipp Zabel iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); 4845b247442SPhilipp Zabel iface &= ~(R01_SIM | R01_SFORO_MASK); 4855b247442SPhilipp Zabel 4865b247442SPhilipp Zabel switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 4875b247442SPhilipp Zabel case SND_SOC_DAIFMT_I2S: 4885b247442SPhilipp Zabel iface |= R01_SFORO_I2S; 4895b247442SPhilipp Zabel break; 4905b247442SPhilipp Zabel case SND_SOC_DAIFMT_LSB: 4915b247442SPhilipp Zabel iface |= R01_SFORO_LSB16; 4925b247442SPhilipp Zabel break; 4935b247442SPhilipp Zabel case SND_SOC_DAIFMT_MSB: 4945b247442SPhilipp Zabel iface |= R01_SFORO_MSB; 495b7482f52SPhilipp Zabel } 496b7482f52SPhilipp Zabel 497b7482f52SPhilipp Zabel if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) 498b7482f52SPhilipp Zabel iface |= R01_SIM; 499b7482f52SPhilipp Zabel 500b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_IFACE, iface); 501b7482f52SPhilipp Zabel 502b7482f52SPhilipp Zabel return 0; 503b7482f52SPhilipp Zabel } 504b7482f52SPhilipp Zabel 505ef9e5e5cSPhilipp Zabel static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, 506dee89c4dSMark Brown struct snd_soc_dai *dai) 507b7482f52SPhilipp Zabel { 508e6968a17SMark Brown struct snd_soc_codec *codec = dai->codec; 509b2c812e2SMark Brown struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); 510ef9e5e5cSPhilipp Zabel int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); 511b7482f52SPhilipp Zabel 512ef9e5e5cSPhilipp Zabel switch (cmd) { 513ef9e5e5cSPhilipp Zabel case SNDRV_PCM_TRIGGER_START: 514ef9e5e5cSPhilipp Zabel case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 515ef9e5e5cSPhilipp Zabel uda1380_write_reg_cache(codec, UDA1380_MIXER, 516ef9e5e5cSPhilipp Zabel mixer & ~R14_SILENCE); 5171abd9184SPhilipp Zabel schedule_work(&uda1380->work); 518ef9e5e5cSPhilipp Zabel break; 519ef9e5e5cSPhilipp Zabel case SNDRV_PCM_TRIGGER_STOP: 520ef9e5e5cSPhilipp Zabel case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 521ef9e5e5cSPhilipp Zabel uda1380_write_reg_cache(codec, UDA1380_MIXER, 522ef9e5e5cSPhilipp Zabel mixer | R14_SILENCE); 5231abd9184SPhilipp Zabel schedule_work(&uda1380->work); 524ef9e5e5cSPhilipp Zabel break; 525b7482f52SPhilipp Zabel } 526b7482f52SPhilipp Zabel return 0; 527b7482f52SPhilipp Zabel } 528b7482f52SPhilipp Zabel 529b7482f52SPhilipp Zabel static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, 530dee89c4dSMark Brown struct snd_pcm_hw_params *params, 531dee89c4dSMark Brown struct snd_soc_dai *dai) 532b7482f52SPhilipp Zabel { 533e6968a17SMark Brown struct snd_soc_codec *codec = dai->codec; 534b7482f52SPhilipp Zabel u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); 535b7482f52SPhilipp Zabel 536b7482f52SPhilipp Zabel /* set WSPLL power and divider if running from this clock */ 537b7482f52SPhilipp Zabel if (clk & R00_DAC_CLK) { 538b7482f52SPhilipp Zabel int rate = params_rate(params); 539b7482f52SPhilipp Zabel u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM); 540b7482f52SPhilipp Zabel clk &= ~0x3; /* clear SEL_LOOP_DIV */ 541b7482f52SPhilipp Zabel switch (rate) { 542b7482f52SPhilipp Zabel case 6250 ... 12500: 543b7482f52SPhilipp Zabel clk |= 0x0; 544b7482f52SPhilipp Zabel break; 545b7482f52SPhilipp Zabel case 12501 ... 25000: 546b7482f52SPhilipp Zabel clk |= 0x1; 547b7482f52SPhilipp Zabel break; 548b7482f52SPhilipp Zabel case 25001 ... 50000: 549b7482f52SPhilipp Zabel clk |= 0x2; 550b7482f52SPhilipp Zabel break; 551b7482f52SPhilipp Zabel case 50001 ... 100000: 552b7482f52SPhilipp Zabel clk |= 0x3; 553b7482f52SPhilipp Zabel break; 554b7482f52SPhilipp Zabel } 555b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_PM, R02_PON_PLL | pm); 556b7482f52SPhilipp Zabel } 557b7482f52SPhilipp Zabel 558b7482f52SPhilipp Zabel if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 559b7482f52SPhilipp Zabel clk |= R00_EN_DAC | R00_EN_INT; 560b7482f52SPhilipp Zabel else 561b7482f52SPhilipp Zabel clk |= R00_EN_ADC | R00_EN_DEC; 562b7482f52SPhilipp Zabel 563b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_CLK, clk); 564b7482f52SPhilipp Zabel return 0; 565b7482f52SPhilipp Zabel } 566b7482f52SPhilipp Zabel 567dee89c4dSMark Brown static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, 568dee89c4dSMark Brown struct snd_soc_dai *dai) 569b7482f52SPhilipp Zabel { 570ab64246cSLars-Peter Clausen struct snd_soc_codec *codec = dai->codec; 571b7482f52SPhilipp Zabel u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); 572b7482f52SPhilipp Zabel 573b7482f52SPhilipp Zabel /* shut down WSPLL power if running from this clock */ 574b7482f52SPhilipp Zabel if (clk & R00_DAC_CLK) { 575b7482f52SPhilipp Zabel u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM); 576b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_PM, ~R02_PON_PLL & pm); 577b7482f52SPhilipp Zabel } 578b7482f52SPhilipp Zabel 579b7482f52SPhilipp Zabel if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 580b7482f52SPhilipp Zabel clk &= ~(R00_EN_DAC | R00_EN_INT); 581b7482f52SPhilipp Zabel else 582b7482f52SPhilipp Zabel clk &= ~(R00_EN_ADC | R00_EN_DEC); 583b7482f52SPhilipp Zabel 584b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_CLK, clk); 585b7482f52SPhilipp Zabel } 586b7482f52SPhilipp Zabel 587b7482f52SPhilipp Zabel static int uda1380_set_bias_level(struct snd_soc_codec *codec, 588b7482f52SPhilipp Zabel enum snd_soc_bias_level level) 589b7482f52SPhilipp Zabel { 590b7482f52SPhilipp Zabel int pm = uda1380_read_reg_cache(codec, UDA1380_PM); 5918614d310SVasily Khoruzhick int reg; 5928614d310SVasily Khoruzhick struct uda1380_platform_data *pdata = codec->dev->platform_data; 5938614d310SVasily Khoruzhick 594b7482f52SPhilipp Zabel switch (level) { 595b7482f52SPhilipp Zabel case SND_SOC_BIAS_ON: 596b7482f52SPhilipp Zabel case SND_SOC_BIAS_PREPARE: 5978614d310SVasily Khoruzhick /* ADC, DAC on */ 598b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm); 599b7482f52SPhilipp Zabel break; 600b7482f52SPhilipp Zabel case SND_SOC_BIAS_STANDBY: 6019f061718SLars-Peter Clausen if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { 6028614d310SVasily Khoruzhick if (gpio_is_valid(pdata->gpio_power)) { 6038614d310SVasily Khoruzhick gpio_set_value(pdata->gpio_power, 1); 6048e3dce4dSVasily Khoruzhick mdelay(1); 6058614d310SVasily Khoruzhick uda1380_reset(codec); 6068614d310SVasily Khoruzhick } 6078614d310SVasily Khoruzhick 6088614d310SVasily Khoruzhick uda1380_sync_cache(codec); 6098614d310SVasily Khoruzhick } 610b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_PM, 0x0); 611b7482f52SPhilipp Zabel break; 6128614d310SVasily Khoruzhick case SND_SOC_BIAS_OFF: 6138614d310SVasily Khoruzhick if (!gpio_is_valid(pdata->gpio_power)) 6148614d310SVasily Khoruzhick break; 6158614d310SVasily Khoruzhick 6168614d310SVasily Khoruzhick gpio_set_value(pdata->gpio_power, 0); 6178614d310SVasily Khoruzhick 6188614d310SVasily Khoruzhick /* Mark mixer regs cache dirty to sync them with 6198614d310SVasily Khoruzhick * codec regs on power on. 6208614d310SVasily Khoruzhick */ 6218614d310SVasily Khoruzhick for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++) 6228614d310SVasily Khoruzhick set_bit(reg - 0x10, &uda1380_cache_dirty); 623b7482f52SPhilipp Zabel } 624b7482f52SPhilipp Zabel return 0; 625b7482f52SPhilipp Zabel } 626b7482f52SPhilipp Zabel 627b7482f52SPhilipp Zabel #define UDA1380_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 628b7482f52SPhilipp Zabel SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ 629b7482f52SPhilipp Zabel SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) 630b7482f52SPhilipp Zabel 63185e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops uda1380_dai_ops = { 6326335d055SEric Miao .hw_params = uda1380_pcm_hw_params, 6336335d055SEric Miao .shutdown = uda1380_pcm_shutdown, 63465ec1cd1SMark Brown .trigger = uda1380_trigger, 6356335d055SEric Miao .set_fmt = uda1380_set_dai_fmt_both, 6366335d055SEric Miao }; 6376335d055SEric Miao 63885e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops uda1380_dai_ops_playback = { 6396335d055SEric Miao .hw_params = uda1380_pcm_hw_params, 6406335d055SEric Miao .shutdown = uda1380_pcm_shutdown, 64165ec1cd1SMark Brown .trigger = uda1380_trigger, 6426335d055SEric Miao .set_fmt = uda1380_set_dai_fmt_playback, 6436335d055SEric Miao }; 6446335d055SEric Miao 64585e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops uda1380_dai_ops_capture = { 6466335d055SEric Miao .hw_params = uda1380_pcm_hw_params, 6476335d055SEric Miao .shutdown = uda1380_pcm_shutdown, 64865ec1cd1SMark Brown .trigger = uda1380_trigger, 6496335d055SEric Miao .set_fmt = uda1380_set_dai_fmt_capture, 6506335d055SEric Miao }; 6516335d055SEric Miao 652f0fba2adSLiam Girdwood static struct snd_soc_dai_driver uda1380_dai[] = { 653b7482f52SPhilipp Zabel { 654f0fba2adSLiam Girdwood .name = "uda1380-hifi", 655b7482f52SPhilipp Zabel .playback = { 656b7482f52SPhilipp Zabel .stream_name = "Playback", 657b7482f52SPhilipp Zabel .channels_min = 1, 658b7482f52SPhilipp Zabel .channels_max = 2, 659b7482f52SPhilipp Zabel .rates = UDA1380_RATES, 660b7482f52SPhilipp Zabel .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 661b7482f52SPhilipp Zabel .capture = { 662b7482f52SPhilipp Zabel .stream_name = "Capture", 663b7482f52SPhilipp Zabel .channels_min = 1, 664b7482f52SPhilipp Zabel .channels_max = 2, 665b7482f52SPhilipp Zabel .rates = UDA1380_RATES, 666b7482f52SPhilipp Zabel .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 6676335d055SEric Miao .ops = &uda1380_dai_ops, 668b7482f52SPhilipp Zabel }, 669b7482f52SPhilipp Zabel { /* playback only - dual interface */ 670f0fba2adSLiam Girdwood .name = "uda1380-hifi-playback", 671b7482f52SPhilipp Zabel .playback = { 672b7482f52SPhilipp Zabel .stream_name = "Playback", 673b7482f52SPhilipp Zabel .channels_min = 1, 674b7482f52SPhilipp Zabel .channels_max = 2, 675b7482f52SPhilipp Zabel .rates = UDA1380_RATES, 676b7482f52SPhilipp Zabel .formats = SNDRV_PCM_FMTBIT_S16_LE, 677b7482f52SPhilipp Zabel }, 6786335d055SEric Miao .ops = &uda1380_dai_ops_playback, 679b7482f52SPhilipp Zabel }, 680b7482f52SPhilipp Zabel { /* capture only - dual interface*/ 681f0fba2adSLiam Girdwood .name = "uda1380-hifi-capture", 682b7482f52SPhilipp Zabel .capture = { 683b7482f52SPhilipp Zabel .stream_name = "Capture", 684b7482f52SPhilipp Zabel .channels_min = 1, 685b7482f52SPhilipp Zabel .channels_max = 2, 686b7482f52SPhilipp Zabel .rates = UDA1380_RATES, 687b7482f52SPhilipp Zabel .formats = SNDRV_PCM_FMTBIT_S16_LE, 688b7482f52SPhilipp Zabel }, 6896335d055SEric Miao .ops = &uda1380_dai_ops_capture, 690b7482f52SPhilipp Zabel }, 691b7482f52SPhilipp Zabel }; 692b7482f52SPhilipp Zabel 693f0fba2adSLiam Girdwood static int uda1380_probe(struct snd_soc_codec *codec) 694b7482f52SPhilipp Zabel { 695f0fba2adSLiam Girdwood struct uda1380_platform_data *pdata =codec->dev->platform_data; 696f0fba2adSLiam Girdwood struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); 697f0fba2adSLiam Girdwood int ret; 698b7482f52SPhilipp Zabel 6998614d310SVasily Khoruzhick uda1380->codec = codec; 700b7482f52SPhilipp Zabel 701222e728cSLars-Peter Clausen if (!gpio_is_valid(pdata->gpio_power)) { 702f0fba2adSLiam Girdwood ret = uda1380_reset(codec); 70368020db8SAxel Lin if (ret) 704222e728cSLars-Peter Clausen return ret; 7058614d310SVasily Khoruzhick } 706b7482f52SPhilipp Zabel 707f0fba2adSLiam Girdwood INIT_WORK(&uda1380->work, uda1380_flush_work); 708f0fba2adSLiam Girdwood 709b7482f52SPhilipp Zabel /* set clock input */ 7101abd9184SPhilipp Zabel switch (pdata->dac_clk) { 711b7482f52SPhilipp Zabel case UDA1380_DAC_CLK_SYSCLK: 7128614d310SVasily Khoruzhick uda1380_write_reg_cache(codec, UDA1380_CLK, 0); 713b7482f52SPhilipp Zabel break; 714b7482f52SPhilipp Zabel case UDA1380_DAC_CLK_WSPLL: 7158614d310SVasily Khoruzhick uda1380_write_reg_cache(codec, UDA1380_CLK, 7168614d310SVasily Khoruzhick R00_DAC_CLK); 717b7482f52SPhilipp Zabel break; 718b7482f52SPhilipp Zabel } 719b7482f52SPhilipp Zabel 7201abd9184SPhilipp Zabel return 0; 7211abd9184SPhilipp Zabel } 722b7482f52SPhilipp Zabel 723a180ba45SBhumika Goyal static const struct snd_soc_codec_driver soc_codec_dev_uda1380 = { 724f0fba2adSLiam Girdwood .probe = uda1380_probe, 725f0fba2adSLiam Girdwood .read = uda1380_read_reg_cache, 726f0fba2adSLiam Girdwood .write = uda1380_write, 727f0fba2adSLiam Girdwood .set_bias_level = uda1380_set_bias_level, 728e8125f04SLars-Peter Clausen .suspend_bias_off = true, 729e8125f04SLars-Peter Clausen 730f0fba2adSLiam Girdwood .reg_cache_size = ARRAY_SIZE(uda1380_reg), 731f0fba2adSLiam Girdwood .reg_word_size = sizeof(u16), 732f0fba2adSLiam Girdwood .reg_cache_default = uda1380_reg, 733f0fba2adSLiam Girdwood .reg_cache_step = 1, 73458fa8e45SAxel Lin 73568509edeSKuninori Morimoto .component_driver = { 73658fa8e45SAxel Lin .controls = uda1380_snd_controls, 73758fa8e45SAxel Lin .num_controls = ARRAY_SIZE(uda1380_snd_controls), 73858fa8e45SAxel Lin .dapm_widgets = uda1380_dapm_widgets, 73958fa8e45SAxel Lin .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), 74058fa8e45SAxel Lin .dapm_routes = uda1380_dapm_routes, 74158fa8e45SAxel Lin .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes), 74268509edeSKuninori Morimoto }, 743f0fba2adSLiam Girdwood }; 744f0fba2adSLiam Girdwood 7457a79e94eSBill Pemberton static int uda1380_i2c_probe(struct i2c_client *i2c, 74688fc39d7SJean Delvare const struct i2c_device_id *id) 747b7482f52SPhilipp Zabel { 748222e728cSLars-Peter Clausen struct uda1380_platform_data *pdata = i2c->dev.platform_data; 7491abd9184SPhilipp Zabel struct uda1380_priv *uda1380; 750b7482f52SPhilipp Zabel int ret; 751b7482f52SPhilipp Zabel 752222e728cSLars-Peter Clausen if (!pdata) 753222e728cSLars-Peter Clausen return -EINVAL; 754222e728cSLars-Peter Clausen 7556ce91ad4SAxel Lin uda1380 = devm_kzalloc(&i2c->dev, sizeof(struct uda1380_priv), 7566ce91ad4SAxel Lin GFP_KERNEL); 7571abd9184SPhilipp Zabel if (uda1380 == NULL) 7581abd9184SPhilipp Zabel return -ENOMEM; 7591abd9184SPhilipp Zabel 760222e728cSLars-Peter Clausen if (gpio_is_valid(pdata->gpio_reset)) { 761222e728cSLars-Peter Clausen ret = devm_gpio_request_one(&i2c->dev, pdata->gpio_reset, 762222e728cSLars-Peter Clausen GPIOF_OUT_INIT_LOW, "uda1380 reset"); 763222e728cSLars-Peter Clausen if (ret) 764222e728cSLars-Peter Clausen return ret; 765222e728cSLars-Peter Clausen } 766222e728cSLars-Peter Clausen 767222e728cSLars-Peter Clausen if (gpio_is_valid(pdata->gpio_power)) { 768222e728cSLars-Peter Clausen ret = devm_gpio_request_one(&i2c->dev, pdata->gpio_power, 769222e728cSLars-Peter Clausen GPIOF_OUT_INIT_LOW, "uda1380 power"); 770222e728cSLars-Peter Clausen if (ret) 771222e728cSLars-Peter Clausen return ret; 772222e728cSLars-Peter Clausen } 773222e728cSLars-Peter Clausen 7741abd9184SPhilipp Zabel i2c_set_clientdata(i2c, uda1380); 775*eaa53216SKuninori Morimoto uda1380->i2c = i2c; 776b7482f52SPhilipp Zabel 777f0fba2adSLiam Girdwood ret = snd_soc_register_codec(&i2c->dev, 778f0fba2adSLiam Girdwood &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); 779b7482f52SPhilipp Zabel return ret; 780b7482f52SPhilipp Zabel } 781b7482f52SPhilipp Zabel 7827a79e94eSBill Pemberton static int uda1380_i2c_remove(struct i2c_client *i2c) 783b7482f52SPhilipp Zabel { 784f0fba2adSLiam Girdwood snd_soc_unregister_codec(&i2c->dev); 785b7482f52SPhilipp Zabel return 0; 786b7482f52SPhilipp Zabel } 787b7482f52SPhilipp Zabel 78888fc39d7SJean Delvare static const struct i2c_device_id uda1380_i2c_id[] = { 78988fc39d7SJean Delvare { "uda1380", 0 }, 79088fc39d7SJean Delvare { } 79188fc39d7SJean Delvare }; 79288fc39d7SJean Delvare MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); 793b7482f52SPhilipp Zabel 794ea22a26eSJavier Martinez Canillas static const struct of_device_id uda1380_of_match[] = { 795ea22a26eSJavier Martinez Canillas { .compatible = "nxp,uda1380", }, 796ea22a26eSJavier Martinez Canillas { } 797ea22a26eSJavier Martinez Canillas }; 798ea22a26eSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, uda1380_of_match); 799ea22a26eSJavier Martinez Canillas 800b7482f52SPhilipp Zabel static struct i2c_driver uda1380_i2c_driver = { 801b7482f52SPhilipp Zabel .driver = { 802f0fba2adSLiam Girdwood .name = "uda1380-codec", 803ea22a26eSJavier Martinez Canillas .of_match_table = uda1380_of_match, 804b7482f52SPhilipp Zabel }, 80588fc39d7SJean Delvare .probe = uda1380_i2c_probe, 8067a79e94eSBill Pemberton .remove = uda1380_i2c_remove, 80788fc39d7SJean Delvare .id_table = uda1380_i2c_id, 808b7482f52SPhilipp Zabel }; 809b7482f52SPhilipp Zabel 8104a5cf132SKuninori Morimoto module_i2c_driver(uda1380_i2c_driver); 81164089b84SMark Brown 812b7482f52SPhilipp Zabel MODULE_AUTHOR("Giorgio Padrin"); 813b7482f52SPhilipp Zabel MODULE_DESCRIPTION("Audio support for codec Philips UDA1380"); 814b7482f52SPhilipp Zabel MODULE_LICENSE("GPL"); 815