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; 408614d310SVasily Khoruzhick void *control_data; 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 { 95b7482f52SPhilipp Zabel u8 data[3]; 96b7482f52SPhilipp Zabel 97b7482f52SPhilipp Zabel /* data is 98b7482f52SPhilipp Zabel * data[0] is register offset 99b7482f52SPhilipp Zabel * data[1] is MS byte 100b7482f52SPhilipp Zabel * data[2] is LS byte 101b7482f52SPhilipp Zabel */ 102b7482f52SPhilipp Zabel data[0] = reg; 103b7482f52SPhilipp Zabel data[1] = (value & 0xff00) >> 8; 104b7482f52SPhilipp Zabel data[2] = value & 0x00ff; 105b7482f52SPhilipp Zabel 106b7482f52SPhilipp Zabel uda1380_write_reg_cache(codec, reg, value); 107b7482f52SPhilipp Zabel 108b7482f52SPhilipp Zabel /* the interpolator & decimator regs must only be written when the 109b7482f52SPhilipp Zabel * codec DAI is active. 110b7482f52SPhilipp Zabel */ 111b7482f52SPhilipp Zabel if (!codec->active && (reg >= UDA1380_MVOL)) 112b7482f52SPhilipp Zabel return 0; 113b7482f52SPhilipp Zabel pr_debug("uda1380: hw write %x val %x\n", reg, value); 114b7482f52SPhilipp Zabel if (codec->hw_write(codec->control_data, data, 3) == 3) { 115b7482f52SPhilipp Zabel unsigned int val; 116b7482f52SPhilipp Zabel i2c_master_send(codec->control_data, data, 1); 117b7482f52SPhilipp Zabel i2c_master_recv(codec->control_data, data, 2); 118b7482f52SPhilipp Zabel val = (data[0]<<8) | data[1]; 119b7482f52SPhilipp Zabel if (val != value) { 120b7482f52SPhilipp Zabel pr_debug("uda1380: READ BACK VAL %x\n", 121b7482f52SPhilipp Zabel (data[0]<<8) | data[1]); 122b7482f52SPhilipp Zabel return -EIO; 123b7482f52SPhilipp Zabel } 124ef9e5e5cSPhilipp Zabel if (reg >= 0x10) 125ef9e5e5cSPhilipp Zabel clear_bit(reg - 0x10, &uda1380_cache_dirty); 126b7482f52SPhilipp Zabel return 0; 127b7482f52SPhilipp Zabel } else 128b7482f52SPhilipp Zabel return -EIO; 129b7482f52SPhilipp Zabel } 130b7482f52SPhilipp Zabel 1318614d310SVasily Khoruzhick static void uda1380_sync_cache(struct snd_soc_codec *codec) 1328614d310SVasily Khoruzhick { 1338614d310SVasily Khoruzhick int reg; 1348614d310SVasily Khoruzhick u8 data[3]; 1358614d310SVasily Khoruzhick u16 *cache = codec->reg_cache; 1368614d310SVasily Khoruzhick 1378614d310SVasily Khoruzhick /* Sync reg_cache with the hardware */ 1388614d310SVasily Khoruzhick for (reg = 0; reg < UDA1380_MVOL; reg++) { 1398614d310SVasily Khoruzhick data[0] = reg; 1408614d310SVasily Khoruzhick data[1] = (cache[reg] & 0xff00) >> 8; 1418614d310SVasily Khoruzhick data[2] = cache[reg] & 0x00ff; 1428614d310SVasily Khoruzhick if (codec->hw_write(codec->control_data, data, 3) != 3) 1438614d310SVasily Khoruzhick dev_err(codec->dev, "%s: write to reg 0x%x failed\n", 1448614d310SVasily Khoruzhick __func__, reg); 1458614d310SVasily Khoruzhick } 1468614d310SVasily Khoruzhick } 1478614d310SVasily Khoruzhick 1488614d310SVasily Khoruzhick static int uda1380_reset(struct snd_soc_codec *codec) 1498614d310SVasily Khoruzhick { 1508614d310SVasily Khoruzhick struct uda1380_platform_data *pdata = codec->dev->platform_data; 1518614d310SVasily Khoruzhick 1528614d310SVasily Khoruzhick if (gpio_is_valid(pdata->gpio_reset)) { 1538614d310SVasily Khoruzhick gpio_set_value(pdata->gpio_reset, 1); 1548614d310SVasily Khoruzhick mdelay(1); 1558614d310SVasily Khoruzhick gpio_set_value(pdata->gpio_reset, 0); 1568614d310SVasily Khoruzhick } else { 1578614d310SVasily Khoruzhick u8 data[3]; 1588614d310SVasily Khoruzhick 1598614d310SVasily Khoruzhick data[0] = UDA1380_RESET; 1608614d310SVasily Khoruzhick data[1] = 0; 1618614d310SVasily Khoruzhick data[2] = 0; 1628614d310SVasily Khoruzhick 1638614d310SVasily Khoruzhick if (codec->hw_write(codec->control_data, data, 3) != 3) { 1648614d310SVasily Khoruzhick dev_err(codec->dev, "%s: failed\n", __func__); 1658614d310SVasily Khoruzhick return -EIO; 1668614d310SVasily Khoruzhick } 1678614d310SVasily Khoruzhick } 1688614d310SVasily Khoruzhick 1698614d310SVasily Khoruzhick return 0; 1708614d310SVasily Khoruzhick } 171b7482f52SPhilipp Zabel 172ef9e5e5cSPhilipp Zabel static void uda1380_flush_work(struct work_struct *work) 173ef9e5e5cSPhilipp Zabel { 174f0fba2adSLiam Girdwood struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work); 175f0fba2adSLiam Girdwood struct snd_soc_codec *uda1380_codec = uda1380->codec; 176ef9e5e5cSPhilipp Zabel int bit, reg; 177ef9e5e5cSPhilipp Zabel 178984b3f57SAkinobu Mita for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { 179ef9e5e5cSPhilipp Zabel reg = 0x10 + bit; 180ef9e5e5cSPhilipp Zabel pr_debug("uda1380: flush reg %x val %x:\n", reg, 181ef9e5e5cSPhilipp Zabel uda1380_read_reg_cache(uda1380_codec, reg)); 182ef9e5e5cSPhilipp Zabel uda1380_write(uda1380_codec, reg, 183ef9e5e5cSPhilipp Zabel uda1380_read_reg_cache(uda1380_codec, reg)); 184ef9e5e5cSPhilipp Zabel clear_bit(bit, &uda1380_cache_dirty); 185ef9e5e5cSPhilipp Zabel } 186f0fba2adSLiam Girdwood 187ef9e5e5cSPhilipp Zabel } 188ef9e5e5cSPhilipp Zabel 189b7482f52SPhilipp Zabel /* declarations of ALSA reg_elem_REAL controls */ 190b7482f52SPhilipp Zabel static const char *uda1380_deemp[] = { 191b7482f52SPhilipp Zabel "None", 192b7482f52SPhilipp Zabel "32kHz", 193b7482f52SPhilipp Zabel "44.1kHz", 194b7482f52SPhilipp Zabel "48kHz", 195b7482f52SPhilipp Zabel "96kHz", 196b7482f52SPhilipp Zabel }; 197b7482f52SPhilipp Zabel static const char *uda1380_input_sel[] = { 198b7482f52SPhilipp Zabel "Line", 199b7482f52SPhilipp Zabel "Mic + Line R", 200b7482f52SPhilipp Zabel "Line L", 201b7482f52SPhilipp Zabel "Mic", 202b7482f52SPhilipp Zabel }; 203b7482f52SPhilipp Zabel static const char *uda1380_output_sel[] = { 204b7482f52SPhilipp Zabel "DAC", 205b7482f52SPhilipp Zabel "Analog Mixer", 206b7482f52SPhilipp Zabel }; 207b7482f52SPhilipp Zabel static const char *uda1380_spf_mode[] = { 208b7482f52SPhilipp Zabel "Flat", 209b7482f52SPhilipp Zabel "Minimum1", 210b7482f52SPhilipp Zabel "Minimum2", 211b7482f52SPhilipp Zabel "Maximum" 212b7482f52SPhilipp Zabel }; 213b7482f52SPhilipp Zabel static const char *uda1380_capture_sel[] = { 214b7482f52SPhilipp Zabel "ADC", 215b7482f52SPhilipp Zabel "Digital Mixer" 216b7482f52SPhilipp Zabel }; 217b7482f52SPhilipp Zabel static const char *uda1380_sel_ns[] = { 218b7482f52SPhilipp Zabel "3rd-order", 219b7482f52SPhilipp Zabel "5th-order" 220b7482f52SPhilipp Zabel }; 221b7482f52SPhilipp Zabel static const char *uda1380_mix_control[] = { 222b7482f52SPhilipp Zabel "off", 223b7482f52SPhilipp Zabel "PCM only", 224b7482f52SPhilipp Zabel "before sound processing", 225b7482f52SPhilipp Zabel "after sound processing" 226b7482f52SPhilipp Zabel }; 227b7482f52SPhilipp Zabel static const char *uda1380_sdet_setting[] = { 228b7482f52SPhilipp Zabel "3200", 229b7482f52SPhilipp Zabel "4800", 230b7482f52SPhilipp Zabel "9600", 231b7482f52SPhilipp Zabel "19200" 232b7482f52SPhilipp Zabel }; 233b7482f52SPhilipp Zabel static const char *uda1380_os_setting[] = { 234b7482f52SPhilipp Zabel "single-speed", 235b7482f52SPhilipp Zabel "double-speed (no mixing)", 236b7482f52SPhilipp Zabel "quad-speed (no mixing)" 237b7482f52SPhilipp Zabel }; 238b7482f52SPhilipp Zabel 239b7482f52SPhilipp Zabel static const struct soc_enum uda1380_deemp_enum[] = { 240b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, 5, uda1380_deemp), 241b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, 5, uda1380_deemp), 242b7482f52SPhilipp Zabel }; 243b7482f52SPhilipp Zabel static const struct soc_enum uda1380_input_sel_enum = 244b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_ADC, 2, 4, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ 245b7482f52SPhilipp Zabel static const struct soc_enum uda1380_output_sel_enum = 246b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_PM, 7, 2, uda1380_output_sel); /* R02_EN_AVC */ 247b7482f52SPhilipp Zabel static const struct soc_enum uda1380_spf_enum = 248b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_MODE, 14, 4, uda1380_spf_mode); /* M */ 249b7482f52SPhilipp Zabel static const struct soc_enum uda1380_capture_sel_enum = 250b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_IFACE, 6, 2, uda1380_capture_sel); /* SEL_SOURCE */ 251b7482f52SPhilipp Zabel static const struct soc_enum uda1380_sel_ns_enum = 252b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_MIXER, 14, 2, uda1380_sel_ns); /* SEL_NS */ 253b7482f52SPhilipp Zabel static const struct soc_enum uda1380_mix_enum = 254b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_MIXER, 12, 4, uda1380_mix_control); /* MIX, MIX_POS */ 255b7482f52SPhilipp Zabel static const struct soc_enum uda1380_sdet_enum = 256b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_MIXER, 4, 4, uda1380_sdet_setting); /* SD_VALUE */ 257b7482f52SPhilipp Zabel static const struct soc_enum uda1380_os_enum = 258b7482f52SPhilipp Zabel SOC_ENUM_SINGLE(UDA1380_MIXER, 0, 3, uda1380_os_setting); /* OS */ 259b7482f52SPhilipp Zabel 260b7482f52SPhilipp Zabel /* 261b7482f52SPhilipp Zabel * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB) 262b7482f52SPhilipp Zabel */ 263b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(amix_tlv, -4950, 150, 1); 264b7482f52SPhilipp Zabel 265b7482f52SPhilipp Zabel /* 266b7482f52SPhilipp Zabel * from -78 dB in 1 dB steps (3 dB steps, really. LSB are ignored), 267b7482f52SPhilipp Zabel * from -66 dB in 0.5 dB steps (2 dB steps, really) and 268b7482f52SPhilipp Zabel * from -52 dB in 0.25 dB steps 269b7482f52SPhilipp Zabel */ 270b7482f52SPhilipp Zabel static const unsigned int mvol_tlv[] = { 271b7482f52SPhilipp Zabel TLV_DB_RANGE_HEAD(3), 272b7482f52SPhilipp Zabel 0, 15, TLV_DB_SCALE_ITEM(-8200, 100, 1), 273b7482f52SPhilipp Zabel 16, 43, TLV_DB_SCALE_ITEM(-6600, 50, 0), 274b7482f52SPhilipp Zabel 44, 252, TLV_DB_SCALE_ITEM(-5200, 25, 0), 275b7482f52SPhilipp Zabel }; 276b7482f52SPhilipp Zabel 277b7482f52SPhilipp Zabel /* 278b7482f52SPhilipp Zabel * from -72 dB in 1.5 dB steps (6 dB steps really), 279b7482f52SPhilipp Zabel * from -66 dB in 0.75 dB steps (3 dB steps really), 280b7482f52SPhilipp Zabel * from -60 dB in 0.5 dB steps (2 dB steps really) and 281b7482f52SPhilipp Zabel * from -46 dB in 0.25 dB steps 282b7482f52SPhilipp Zabel */ 283b7482f52SPhilipp Zabel static const unsigned int vc_tlv[] = { 284b7482f52SPhilipp Zabel TLV_DB_RANGE_HEAD(4), 285b7482f52SPhilipp Zabel 0, 7, TLV_DB_SCALE_ITEM(-7800, 150, 1), 286b7482f52SPhilipp Zabel 8, 15, TLV_DB_SCALE_ITEM(-6600, 75, 0), 287b7482f52SPhilipp Zabel 16, 43, TLV_DB_SCALE_ITEM(-6000, 50, 0), 288b7482f52SPhilipp Zabel 44, 228, TLV_DB_SCALE_ITEM(-4600, 25, 0), 289b7482f52SPhilipp Zabel }; 290b7482f52SPhilipp Zabel 291b7482f52SPhilipp Zabel /* from 0 to 6 dB in 2 dB steps if SPF mode != flat */ 292b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(tr_tlv, 0, 200, 0); 293b7482f52SPhilipp Zabel 294b7482f52SPhilipp Zabel /* from 0 to 24 dB in 2 dB steps, if SPF mode == maximum, otherwise cuts 295b7482f52SPhilipp Zabel * off at 18 dB max) */ 296b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(bb_tlv, 0, 200, 0); 297b7482f52SPhilipp Zabel 298b7482f52SPhilipp Zabel /* from -63 to 24 dB in 0.5 dB steps (-128...48) */ 299b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(dec_tlv, -6400, 50, 1); 300b7482f52SPhilipp Zabel 301b7482f52SPhilipp Zabel /* from 0 to 24 dB in 3 dB steps */ 302b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0); 303b7482f52SPhilipp Zabel 304b7482f52SPhilipp Zabel /* from 0 to 30 dB in 2 dB steps */ 305b7482f52SPhilipp Zabel static DECLARE_TLV_DB_SCALE(vga_tlv, 0, 200, 0); 306b7482f52SPhilipp Zabel 307b7482f52SPhilipp Zabel static const struct snd_kcontrol_new uda1380_snd_controls[] = { 308b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Analog Mixer Volume", UDA1380_AMIX, 0, 8, 44, 1, amix_tlv), /* AVCR, AVCL */ 309b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Master Playback Volume", UDA1380_MVOL, 0, 8, 252, 1, mvol_tlv), /* MVCL, MVCR */ 310b7482f52SPhilipp Zabel SOC_SINGLE_TLV("ADC Playback Volume", UDA1380_MIXVOL, 8, 228, 1, vc_tlv), /* VC2 */ 311b7482f52SPhilipp Zabel SOC_SINGLE_TLV("PCM Playback Volume", UDA1380_MIXVOL, 0, 228, 1, vc_tlv), /* VC1 */ 312b7482f52SPhilipp Zabel SOC_ENUM("Sound Processing Filter", uda1380_spf_enum), /* M */ 313b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Tone Control - Treble", UDA1380_MODE, 4, 12, 3, 0, tr_tlv), /* TRL, TRR */ 314b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Tone Control - Bass", UDA1380_MODE, 0, 8, 15, 0, bb_tlv), /* BBL, BBR */ 315b7482f52SPhilipp Zabel /**/ SOC_SINGLE("Master Playback Switch", UDA1380_DEEMP, 14, 1, 1), /* MTM */ 316b7482f52SPhilipp Zabel SOC_SINGLE("ADC Playback Switch", UDA1380_DEEMP, 11, 1, 1), /* MT2 from decimation filter */ 317b7482f52SPhilipp Zabel SOC_ENUM("ADC Playback De-emphasis", uda1380_deemp_enum[0]), /* DE2 */ 318b7482f52SPhilipp Zabel SOC_SINGLE("PCM Playback Switch", UDA1380_DEEMP, 3, 1, 1), /* MT1, from digital data input */ 319b7482f52SPhilipp Zabel SOC_ENUM("PCM Playback De-emphasis", uda1380_deemp_enum[1]), /* DE1 */ 320b7482f52SPhilipp Zabel SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0), /* DA_POL_INV */ 321b7482f52SPhilipp Zabel SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum), /* SEL_NS */ 322b7482f52SPhilipp Zabel SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum), /* MIX_POS, MIX */ 323b7482f52SPhilipp Zabel SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0), /* SDET_ON */ 324b7482f52SPhilipp Zabel SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum), /* SD_VALUE */ 325b7482f52SPhilipp Zabel SOC_ENUM("Oversampling Input", uda1380_os_enum), /* OS */ 326b7482f52SPhilipp Zabel SOC_DOUBLE_S8_TLV("ADC Capture Volume", UDA1380_DEC, -128, 48, dec_tlv), /* ML_DEC, MR_DEC */ 327b7482f52SPhilipp Zabel /**/ SOC_SINGLE("ADC Capture Switch", UDA1380_PGA, 15, 1, 1), /* MT_ADC */ 328b7482f52SPhilipp Zabel SOC_DOUBLE_TLV("Line Capture Volume", UDA1380_PGA, 0, 8, 8, 0, pga_tlv), /* PGA_GAINCTRLL, PGA_GAINCTRLR */ 329b7482f52SPhilipp Zabel SOC_SINGLE("ADC Polarity inverting Switch", UDA1380_ADC, 12, 1, 0), /* ADCPOL_INV */ 330b7482f52SPhilipp Zabel SOC_SINGLE_TLV("Mic Capture Volume", UDA1380_ADC, 8, 15, 0, vga_tlv), /* VGA_CTRL */ 331b7482f52SPhilipp Zabel SOC_SINGLE("DC Filter Bypass Switch", UDA1380_ADC, 1, 1, 0), /* SKIP_DCFIL (before decimator) */ 332b7482f52SPhilipp Zabel SOC_SINGLE("DC Filter Enable Switch", UDA1380_ADC, 0, 1, 0), /* EN_DCFIL (at output of decimator) */ 333b7482f52SPhilipp Zabel SOC_SINGLE("AGC Timing", UDA1380_AGC, 8, 7, 0), /* TODO: enum, see table 62 */ 334b7482f52SPhilipp Zabel SOC_SINGLE("AGC Target level", UDA1380_AGC, 2, 3, 1), /* AGC_LEVEL */ 335b7482f52SPhilipp Zabel /* -5.5, -8, -11.5, -14 dBFS */ 336b7482f52SPhilipp Zabel SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0), 337b7482f52SPhilipp Zabel }; 338b7482f52SPhilipp Zabel 339b7482f52SPhilipp Zabel /* Input mux */ 340b7482f52SPhilipp Zabel static const struct snd_kcontrol_new uda1380_input_mux_control = 341b7482f52SPhilipp Zabel SOC_DAPM_ENUM("Route", uda1380_input_sel_enum); 342b7482f52SPhilipp Zabel 343b7482f52SPhilipp Zabel /* Output mux */ 344b7482f52SPhilipp Zabel static const struct snd_kcontrol_new uda1380_output_mux_control = 345b7482f52SPhilipp Zabel SOC_DAPM_ENUM("Route", uda1380_output_sel_enum); 346b7482f52SPhilipp Zabel 347b7482f52SPhilipp Zabel /* Capture mux */ 348b7482f52SPhilipp Zabel static const struct snd_kcontrol_new uda1380_capture_mux_control = 349b7482f52SPhilipp Zabel SOC_DAPM_ENUM("Route", uda1380_capture_sel_enum); 350b7482f52SPhilipp Zabel 351b7482f52SPhilipp Zabel 352b7482f52SPhilipp Zabel static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = { 353b7482f52SPhilipp Zabel SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, 354b7482f52SPhilipp Zabel &uda1380_input_mux_control), 355b7482f52SPhilipp Zabel SND_SOC_DAPM_MUX("Output Mux", SND_SOC_NOPM, 0, 0, 356b7482f52SPhilipp Zabel &uda1380_output_mux_control), 357b7482f52SPhilipp Zabel SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, 358b7482f52SPhilipp Zabel &uda1380_capture_mux_control), 359b7482f52SPhilipp Zabel SND_SOC_DAPM_PGA("Left PGA", UDA1380_PM, 3, 0, NULL, 0), 360b7482f52SPhilipp Zabel SND_SOC_DAPM_PGA("Right PGA", UDA1380_PM, 1, 0, NULL, 0), 361b7482f52SPhilipp Zabel SND_SOC_DAPM_PGA("Mic LNA", UDA1380_PM, 4, 0, NULL, 0), 362b7482f52SPhilipp Zabel SND_SOC_DAPM_ADC("Left ADC", "Left Capture", UDA1380_PM, 2, 0), 363b7482f52SPhilipp Zabel SND_SOC_DAPM_ADC("Right ADC", "Right Capture", UDA1380_PM, 0, 0), 364b7482f52SPhilipp Zabel SND_SOC_DAPM_INPUT("VINM"), 365b7482f52SPhilipp Zabel SND_SOC_DAPM_INPUT("VINL"), 366b7482f52SPhilipp Zabel SND_SOC_DAPM_INPUT("VINR"), 367b7482f52SPhilipp Zabel SND_SOC_DAPM_MIXER("Analog Mixer", UDA1380_PM, 6, 0, NULL, 0), 368b7482f52SPhilipp Zabel SND_SOC_DAPM_OUTPUT("VOUTLHP"), 369b7482f52SPhilipp Zabel SND_SOC_DAPM_OUTPUT("VOUTRHP"), 370b7482f52SPhilipp Zabel SND_SOC_DAPM_OUTPUT("VOUTL"), 371b7482f52SPhilipp Zabel SND_SOC_DAPM_OUTPUT("VOUTR"), 372b7482f52SPhilipp Zabel SND_SOC_DAPM_DAC("DAC", "Playback", UDA1380_PM, 10, 0), 373b7482f52SPhilipp Zabel SND_SOC_DAPM_PGA("HeadPhone Driver", UDA1380_PM, 13, 0, NULL, 0), 374b7482f52SPhilipp Zabel }; 375b7482f52SPhilipp Zabel 37658fa8e45SAxel Lin static const struct snd_soc_dapm_route uda1380_dapm_routes[] = { 377b7482f52SPhilipp Zabel 378b7482f52SPhilipp Zabel /* output mux */ 379b7482f52SPhilipp Zabel {"HeadPhone Driver", NULL, "Output Mux"}, 380b7482f52SPhilipp Zabel {"VOUTR", NULL, "Output Mux"}, 381b7482f52SPhilipp Zabel {"VOUTL", NULL, "Output Mux"}, 382b7482f52SPhilipp Zabel 383b7482f52SPhilipp Zabel {"Analog Mixer", NULL, "VINR"}, 384b7482f52SPhilipp Zabel {"Analog Mixer", NULL, "VINL"}, 385b7482f52SPhilipp Zabel {"Analog Mixer", NULL, "DAC"}, 386b7482f52SPhilipp Zabel 387b7482f52SPhilipp Zabel {"Output Mux", "DAC", "DAC"}, 388b7482f52SPhilipp Zabel {"Output Mux", "Analog Mixer", "Analog Mixer"}, 389b7482f52SPhilipp Zabel 390b7482f52SPhilipp Zabel /* {"DAC", "Digital Mixer", "I2S" } */ 391b7482f52SPhilipp Zabel 392b7482f52SPhilipp Zabel /* headphone driver */ 393b7482f52SPhilipp Zabel {"VOUTLHP", NULL, "HeadPhone Driver"}, 394b7482f52SPhilipp Zabel {"VOUTRHP", NULL, "HeadPhone Driver"}, 395b7482f52SPhilipp Zabel 396b7482f52SPhilipp Zabel /* input mux */ 397b7482f52SPhilipp Zabel {"Left ADC", NULL, "Input Mux"}, 398b7482f52SPhilipp Zabel {"Input Mux", "Mic", "Mic LNA"}, 399b7482f52SPhilipp Zabel {"Input Mux", "Mic + Line R", "Mic LNA"}, 400b7482f52SPhilipp Zabel {"Input Mux", "Line L", "Left PGA"}, 401b7482f52SPhilipp Zabel {"Input Mux", "Line", "Left PGA"}, 402b7482f52SPhilipp Zabel 403b7482f52SPhilipp Zabel /* right input */ 404b7482f52SPhilipp Zabel {"Right ADC", "Mic + Line R", "Right PGA"}, 405b7482f52SPhilipp Zabel {"Right ADC", "Line", "Right PGA"}, 406b7482f52SPhilipp Zabel 407b7482f52SPhilipp Zabel /* inputs */ 408b7482f52SPhilipp Zabel {"Mic LNA", NULL, "VINM"}, 409b7482f52SPhilipp Zabel {"Left PGA", NULL, "VINL"}, 410b7482f52SPhilipp Zabel {"Right PGA", NULL, "VINR"}, 411b7482f52SPhilipp Zabel }; 412b7482f52SPhilipp Zabel 4135b247442SPhilipp Zabel static int uda1380_set_dai_fmt_both(struct snd_soc_dai *codec_dai, 414b7482f52SPhilipp Zabel unsigned int fmt) 415b7482f52SPhilipp Zabel { 416b7482f52SPhilipp Zabel struct snd_soc_codec *codec = codec_dai->codec; 417b7482f52SPhilipp Zabel int iface; 418b7482f52SPhilipp Zabel 419b7482f52SPhilipp Zabel /* set up DAI based upon fmt */ 420b7482f52SPhilipp Zabel iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); 421b7482f52SPhilipp Zabel iface &= ~(R01_SFORI_MASK | R01_SIM | R01_SFORO_MASK); 422b7482f52SPhilipp Zabel 423b7482f52SPhilipp Zabel switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 424b7482f52SPhilipp Zabel case SND_SOC_DAIFMT_I2S: 425b7482f52SPhilipp Zabel iface |= R01_SFORI_I2S | R01_SFORO_I2S; 426b7482f52SPhilipp Zabel break; 427b7482f52SPhilipp Zabel case SND_SOC_DAIFMT_LSB: 4285b247442SPhilipp Zabel iface |= R01_SFORI_LSB16 | R01_SFORO_LSB16; 429b7482f52SPhilipp Zabel break; 430b7482f52SPhilipp Zabel case SND_SOC_DAIFMT_MSB: 4315b247442SPhilipp Zabel iface |= R01_SFORI_MSB | R01_SFORO_MSB; 4325b247442SPhilipp Zabel } 4335b247442SPhilipp Zabel 4345f2a9384SPhilipp Zabel /* DATAI is slave only, so in single-link mode, this has to be slave */ 4355f2a9384SPhilipp Zabel if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) 4365f2a9384SPhilipp Zabel return -EINVAL; 4375b247442SPhilipp Zabel 4385b247442SPhilipp Zabel uda1380_write(codec, UDA1380_IFACE, iface); 4395b247442SPhilipp Zabel 4405b247442SPhilipp Zabel return 0; 4415b247442SPhilipp Zabel } 4425b247442SPhilipp Zabel 4435b247442SPhilipp Zabel static int uda1380_set_dai_fmt_playback(struct snd_soc_dai *codec_dai, 4445b247442SPhilipp Zabel unsigned int fmt) 4455b247442SPhilipp Zabel { 4465b247442SPhilipp Zabel struct snd_soc_codec *codec = codec_dai->codec; 4475b247442SPhilipp Zabel int iface; 4485b247442SPhilipp Zabel 4495b247442SPhilipp Zabel /* set up DAI based upon fmt */ 4505b247442SPhilipp Zabel iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); 4515b247442SPhilipp Zabel iface &= ~R01_SFORI_MASK; 4525b247442SPhilipp Zabel 4535b247442SPhilipp Zabel switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 4545b247442SPhilipp Zabel case SND_SOC_DAIFMT_I2S: 4555b247442SPhilipp Zabel iface |= R01_SFORI_I2S; 4565b247442SPhilipp Zabel break; 4575b247442SPhilipp Zabel case SND_SOC_DAIFMT_LSB: 4585b247442SPhilipp Zabel iface |= R01_SFORI_LSB16; 4595b247442SPhilipp Zabel break; 4605b247442SPhilipp Zabel case SND_SOC_DAIFMT_MSB: 4615b247442SPhilipp Zabel iface |= R01_SFORI_MSB; 4625b247442SPhilipp Zabel } 4635b247442SPhilipp Zabel 4645f2a9384SPhilipp Zabel /* DATAI is slave only, so this has to be slave */ 4655f2a9384SPhilipp Zabel if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) 4665f2a9384SPhilipp Zabel return -EINVAL; 4675f2a9384SPhilipp Zabel 4685b247442SPhilipp Zabel uda1380_write(codec, UDA1380_IFACE, iface); 4695b247442SPhilipp Zabel 4705b247442SPhilipp Zabel return 0; 4715b247442SPhilipp Zabel } 4725b247442SPhilipp Zabel 4735b247442SPhilipp Zabel static int uda1380_set_dai_fmt_capture(struct snd_soc_dai *codec_dai, 4745b247442SPhilipp Zabel unsigned int fmt) 4755b247442SPhilipp Zabel { 4765b247442SPhilipp Zabel struct snd_soc_codec *codec = codec_dai->codec; 4775b247442SPhilipp Zabel int iface; 4785b247442SPhilipp Zabel 4795b247442SPhilipp Zabel /* set up DAI based upon fmt */ 4805b247442SPhilipp Zabel iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); 4815b247442SPhilipp Zabel iface &= ~(R01_SIM | R01_SFORO_MASK); 4825b247442SPhilipp Zabel 4835b247442SPhilipp Zabel switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 4845b247442SPhilipp Zabel case SND_SOC_DAIFMT_I2S: 4855b247442SPhilipp Zabel iface |= R01_SFORO_I2S; 4865b247442SPhilipp Zabel break; 4875b247442SPhilipp Zabel case SND_SOC_DAIFMT_LSB: 4885b247442SPhilipp Zabel iface |= R01_SFORO_LSB16; 4895b247442SPhilipp Zabel break; 4905b247442SPhilipp Zabel case SND_SOC_DAIFMT_MSB: 4915b247442SPhilipp Zabel iface |= R01_SFORO_MSB; 492b7482f52SPhilipp Zabel } 493b7482f52SPhilipp Zabel 494b7482f52SPhilipp Zabel if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) 495b7482f52SPhilipp Zabel iface |= R01_SIM; 496b7482f52SPhilipp Zabel 497b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_IFACE, iface); 498b7482f52SPhilipp Zabel 499b7482f52SPhilipp Zabel return 0; 500b7482f52SPhilipp Zabel } 501b7482f52SPhilipp Zabel 502ef9e5e5cSPhilipp Zabel static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, 503dee89c4dSMark Brown struct snd_soc_dai *dai) 504b7482f52SPhilipp Zabel { 505e6968a17SMark Brown struct snd_soc_codec *codec = dai->codec; 506b2c812e2SMark Brown struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); 507ef9e5e5cSPhilipp Zabel int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); 508b7482f52SPhilipp Zabel 509ef9e5e5cSPhilipp Zabel switch (cmd) { 510ef9e5e5cSPhilipp Zabel case SNDRV_PCM_TRIGGER_START: 511ef9e5e5cSPhilipp Zabel case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 512ef9e5e5cSPhilipp Zabel uda1380_write_reg_cache(codec, UDA1380_MIXER, 513ef9e5e5cSPhilipp Zabel mixer & ~R14_SILENCE); 5141abd9184SPhilipp Zabel schedule_work(&uda1380->work); 515ef9e5e5cSPhilipp Zabel break; 516ef9e5e5cSPhilipp Zabel case SNDRV_PCM_TRIGGER_STOP: 517ef9e5e5cSPhilipp Zabel case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 518ef9e5e5cSPhilipp Zabel uda1380_write_reg_cache(codec, UDA1380_MIXER, 519ef9e5e5cSPhilipp Zabel mixer | R14_SILENCE); 5201abd9184SPhilipp Zabel schedule_work(&uda1380->work); 521ef9e5e5cSPhilipp Zabel break; 522b7482f52SPhilipp Zabel } 523b7482f52SPhilipp Zabel return 0; 524b7482f52SPhilipp Zabel } 525b7482f52SPhilipp Zabel 526b7482f52SPhilipp Zabel static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, 527dee89c4dSMark Brown struct snd_pcm_hw_params *params, 528dee89c4dSMark Brown struct snd_soc_dai *dai) 529b7482f52SPhilipp Zabel { 530e6968a17SMark Brown struct snd_soc_codec *codec = dai->codec; 531b7482f52SPhilipp Zabel u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); 532b7482f52SPhilipp Zabel 533b7482f52SPhilipp Zabel /* set WSPLL power and divider if running from this clock */ 534b7482f52SPhilipp Zabel if (clk & R00_DAC_CLK) { 535b7482f52SPhilipp Zabel int rate = params_rate(params); 536b7482f52SPhilipp Zabel u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM); 537b7482f52SPhilipp Zabel clk &= ~0x3; /* clear SEL_LOOP_DIV */ 538b7482f52SPhilipp Zabel switch (rate) { 539b7482f52SPhilipp Zabel case 6250 ... 12500: 540b7482f52SPhilipp Zabel clk |= 0x0; 541b7482f52SPhilipp Zabel break; 542b7482f52SPhilipp Zabel case 12501 ... 25000: 543b7482f52SPhilipp Zabel clk |= 0x1; 544b7482f52SPhilipp Zabel break; 545b7482f52SPhilipp Zabel case 25001 ... 50000: 546b7482f52SPhilipp Zabel clk |= 0x2; 547b7482f52SPhilipp Zabel break; 548b7482f52SPhilipp Zabel case 50001 ... 100000: 549b7482f52SPhilipp Zabel clk |= 0x3; 550b7482f52SPhilipp Zabel break; 551b7482f52SPhilipp Zabel } 552b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_PM, R02_PON_PLL | pm); 553b7482f52SPhilipp Zabel } 554b7482f52SPhilipp Zabel 555b7482f52SPhilipp Zabel if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 556b7482f52SPhilipp Zabel clk |= R00_EN_DAC | R00_EN_INT; 557b7482f52SPhilipp Zabel else 558b7482f52SPhilipp Zabel clk |= R00_EN_ADC | R00_EN_DEC; 559b7482f52SPhilipp Zabel 560b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_CLK, clk); 561b7482f52SPhilipp Zabel return 0; 562b7482f52SPhilipp Zabel } 563b7482f52SPhilipp Zabel 564dee89c4dSMark Brown static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, 565dee89c4dSMark Brown struct snd_soc_dai *dai) 566b7482f52SPhilipp Zabel { 567b7482f52SPhilipp Zabel struct snd_soc_pcm_runtime *rtd = substream->private_data; 568f0fba2adSLiam Girdwood struct snd_soc_codec *codec = rtd->codec; 569b7482f52SPhilipp Zabel u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); 570b7482f52SPhilipp Zabel 571b7482f52SPhilipp Zabel /* shut down WSPLL power if running from this clock */ 572b7482f52SPhilipp Zabel if (clk & R00_DAC_CLK) { 573b7482f52SPhilipp Zabel u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM); 574b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_PM, ~R02_PON_PLL & pm); 575b7482f52SPhilipp Zabel } 576b7482f52SPhilipp Zabel 577b7482f52SPhilipp Zabel if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 578b7482f52SPhilipp Zabel clk &= ~(R00_EN_DAC | R00_EN_INT); 579b7482f52SPhilipp Zabel else 580b7482f52SPhilipp Zabel clk &= ~(R00_EN_ADC | R00_EN_DEC); 581b7482f52SPhilipp Zabel 582b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_CLK, clk); 583b7482f52SPhilipp Zabel } 584b7482f52SPhilipp Zabel 585b7482f52SPhilipp Zabel static int uda1380_set_bias_level(struct snd_soc_codec *codec, 586b7482f52SPhilipp Zabel enum snd_soc_bias_level level) 587b7482f52SPhilipp Zabel { 588b7482f52SPhilipp Zabel int pm = uda1380_read_reg_cache(codec, UDA1380_PM); 5898614d310SVasily Khoruzhick int reg; 5908614d310SVasily Khoruzhick struct uda1380_platform_data *pdata = codec->dev->platform_data; 5918614d310SVasily Khoruzhick 592ce6120ccSLiam Girdwood if (codec->dapm.bias_level == level) 5938614d310SVasily Khoruzhick return 0; 594b7482f52SPhilipp Zabel 595b7482f52SPhilipp Zabel switch (level) { 596b7482f52SPhilipp Zabel case SND_SOC_BIAS_ON: 597b7482f52SPhilipp Zabel case SND_SOC_BIAS_PREPARE: 5988614d310SVasily Khoruzhick /* ADC, DAC on */ 599b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm); 600b7482f52SPhilipp Zabel break; 601b7482f52SPhilipp Zabel case SND_SOC_BIAS_STANDBY: 602ce6120ccSLiam Girdwood if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { 6038614d310SVasily Khoruzhick if (gpio_is_valid(pdata->gpio_power)) { 6048614d310SVasily Khoruzhick gpio_set_value(pdata->gpio_power, 1); 6058e3dce4dSVasily Khoruzhick mdelay(1); 6068614d310SVasily Khoruzhick uda1380_reset(codec); 6078614d310SVasily Khoruzhick } 6088614d310SVasily Khoruzhick 6098614d310SVasily Khoruzhick uda1380_sync_cache(codec); 6108614d310SVasily Khoruzhick } 611b7482f52SPhilipp Zabel uda1380_write(codec, UDA1380_PM, 0x0); 612b7482f52SPhilipp Zabel break; 6138614d310SVasily Khoruzhick case SND_SOC_BIAS_OFF: 6148614d310SVasily Khoruzhick if (!gpio_is_valid(pdata->gpio_power)) 6158614d310SVasily Khoruzhick break; 6168614d310SVasily Khoruzhick 6178614d310SVasily Khoruzhick gpio_set_value(pdata->gpio_power, 0); 6188614d310SVasily Khoruzhick 6198614d310SVasily Khoruzhick /* Mark mixer regs cache dirty to sync them with 6208614d310SVasily Khoruzhick * codec regs on power on. 6218614d310SVasily Khoruzhick */ 6228614d310SVasily Khoruzhick for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++) 6238614d310SVasily Khoruzhick set_bit(reg - 0x10, &uda1380_cache_dirty); 624b7482f52SPhilipp Zabel } 625ce6120ccSLiam Girdwood codec->dapm.bias_level = level; 626b7482f52SPhilipp Zabel return 0; 627b7482f52SPhilipp Zabel } 628b7482f52SPhilipp Zabel 629b7482f52SPhilipp Zabel #define UDA1380_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 630b7482f52SPhilipp Zabel SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ 631b7482f52SPhilipp Zabel SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) 632b7482f52SPhilipp Zabel 63385e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops uda1380_dai_ops = { 6346335d055SEric Miao .hw_params = uda1380_pcm_hw_params, 6356335d055SEric Miao .shutdown = uda1380_pcm_shutdown, 63665ec1cd1SMark Brown .trigger = uda1380_trigger, 6376335d055SEric Miao .set_fmt = uda1380_set_dai_fmt_both, 6386335d055SEric Miao }; 6396335d055SEric Miao 64085e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops uda1380_dai_ops_playback = { 6416335d055SEric Miao .hw_params = uda1380_pcm_hw_params, 6426335d055SEric Miao .shutdown = uda1380_pcm_shutdown, 64365ec1cd1SMark Brown .trigger = uda1380_trigger, 6446335d055SEric Miao .set_fmt = uda1380_set_dai_fmt_playback, 6456335d055SEric Miao }; 6466335d055SEric Miao 64785e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops uda1380_dai_ops_capture = { 6486335d055SEric Miao .hw_params = uda1380_pcm_hw_params, 6496335d055SEric Miao .shutdown = uda1380_pcm_shutdown, 65065ec1cd1SMark Brown .trigger = uda1380_trigger, 6516335d055SEric Miao .set_fmt = uda1380_set_dai_fmt_capture, 6526335d055SEric Miao }; 6536335d055SEric Miao 654f0fba2adSLiam Girdwood static struct snd_soc_dai_driver uda1380_dai[] = { 655b7482f52SPhilipp Zabel { 656f0fba2adSLiam Girdwood .name = "uda1380-hifi", 657b7482f52SPhilipp Zabel .playback = { 658b7482f52SPhilipp Zabel .stream_name = "Playback", 659b7482f52SPhilipp Zabel .channels_min = 1, 660b7482f52SPhilipp Zabel .channels_max = 2, 661b7482f52SPhilipp Zabel .rates = UDA1380_RATES, 662b7482f52SPhilipp Zabel .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 663b7482f52SPhilipp Zabel .capture = { 664b7482f52SPhilipp Zabel .stream_name = "Capture", 665b7482f52SPhilipp Zabel .channels_min = 1, 666b7482f52SPhilipp Zabel .channels_max = 2, 667b7482f52SPhilipp Zabel .rates = UDA1380_RATES, 668b7482f52SPhilipp Zabel .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 6696335d055SEric Miao .ops = &uda1380_dai_ops, 670b7482f52SPhilipp Zabel }, 671b7482f52SPhilipp Zabel { /* playback only - dual interface */ 672f0fba2adSLiam Girdwood .name = "uda1380-hifi-playback", 673b7482f52SPhilipp Zabel .playback = { 674b7482f52SPhilipp Zabel .stream_name = "Playback", 675b7482f52SPhilipp Zabel .channels_min = 1, 676b7482f52SPhilipp Zabel .channels_max = 2, 677b7482f52SPhilipp Zabel .rates = UDA1380_RATES, 678b7482f52SPhilipp Zabel .formats = SNDRV_PCM_FMTBIT_S16_LE, 679b7482f52SPhilipp Zabel }, 6806335d055SEric Miao .ops = &uda1380_dai_ops_playback, 681b7482f52SPhilipp Zabel }, 682b7482f52SPhilipp Zabel { /* capture only - dual interface*/ 683f0fba2adSLiam Girdwood .name = "uda1380-hifi-capture", 684b7482f52SPhilipp Zabel .capture = { 685b7482f52SPhilipp Zabel .stream_name = "Capture", 686b7482f52SPhilipp Zabel .channels_min = 1, 687b7482f52SPhilipp Zabel .channels_max = 2, 688b7482f52SPhilipp Zabel .rates = UDA1380_RATES, 689b7482f52SPhilipp Zabel .formats = SNDRV_PCM_FMTBIT_S16_LE, 690b7482f52SPhilipp Zabel }, 6916335d055SEric Miao .ops = &uda1380_dai_ops_capture, 692b7482f52SPhilipp Zabel }, 693b7482f52SPhilipp Zabel }; 694b7482f52SPhilipp Zabel 69584b315eeSLars-Peter Clausen static int uda1380_suspend(struct snd_soc_codec *codec) 696b7482f52SPhilipp Zabel { 697b7482f52SPhilipp Zabel uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); 698b7482f52SPhilipp Zabel return 0; 699b7482f52SPhilipp Zabel } 700b7482f52SPhilipp Zabel 701f0fba2adSLiam Girdwood static int uda1380_resume(struct snd_soc_codec *codec) 702b7482f52SPhilipp Zabel { 703b7482f52SPhilipp Zabel uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 704b7482f52SPhilipp Zabel return 0; 705b7482f52SPhilipp Zabel } 706b7482f52SPhilipp Zabel 707f0fba2adSLiam Girdwood static int uda1380_probe(struct snd_soc_codec *codec) 708b7482f52SPhilipp Zabel { 709f0fba2adSLiam Girdwood struct uda1380_platform_data *pdata =codec->dev->platform_data; 710f0fba2adSLiam Girdwood struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); 711f0fba2adSLiam Girdwood int ret; 712b7482f52SPhilipp Zabel 7138614d310SVasily Khoruzhick uda1380->codec = codec; 714b7482f52SPhilipp Zabel 7158614d310SVasily Khoruzhick codec->hw_write = (hw_write_t)i2c_master_send; 7168614d310SVasily Khoruzhick codec->control_data = uda1380->control_data; 7178614d310SVasily Khoruzhick 7188614d310SVasily Khoruzhick if (!pdata) 719f0fba2adSLiam Girdwood return -EINVAL; 720ef9e5e5cSPhilipp Zabel 7218614d310SVasily Khoruzhick if (gpio_is_valid(pdata->gpio_reset)) { 72268020db8SAxel Lin ret = gpio_request_one(pdata->gpio_reset, GPIOF_OUT_INIT_LOW, 72368020db8SAxel Lin "uda1380 reset"); 724f0fba2adSLiam Girdwood if (ret) 7258614d310SVasily Khoruzhick goto err_out; 7268614d310SVasily Khoruzhick } 7278614d310SVasily Khoruzhick 7288614d310SVasily Khoruzhick if (gpio_is_valid(pdata->gpio_power)) { 72968020db8SAxel Lin ret = gpio_request_one(pdata->gpio_power, GPIOF_OUT_INIT_LOW, 73068020db8SAxel Lin "uda1380 power"); 7318614d310SVasily Khoruzhick if (ret) 73268020db8SAxel Lin goto err_free_gpio; 7338614d310SVasily Khoruzhick } else { 734f0fba2adSLiam Girdwood ret = uda1380_reset(codec); 73568020db8SAxel Lin if (ret) 73668020db8SAxel Lin goto err_free_gpio; 7378614d310SVasily Khoruzhick } 738b7482f52SPhilipp Zabel 739f0fba2adSLiam Girdwood INIT_WORK(&uda1380->work, uda1380_flush_work); 740f0fba2adSLiam Girdwood 741b7482f52SPhilipp Zabel /* power on device */ 742b7482f52SPhilipp Zabel uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 743b7482f52SPhilipp Zabel /* set clock input */ 7441abd9184SPhilipp Zabel switch (pdata->dac_clk) { 745b7482f52SPhilipp Zabel case UDA1380_DAC_CLK_SYSCLK: 7468614d310SVasily Khoruzhick uda1380_write_reg_cache(codec, UDA1380_CLK, 0); 747b7482f52SPhilipp Zabel break; 748b7482f52SPhilipp Zabel case UDA1380_DAC_CLK_WSPLL: 7498614d310SVasily Khoruzhick uda1380_write_reg_cache(codec, UDA1380_CLK, 7508614d310SVasily Khoruzhick R00_DAC_CLK); 751b7482f52SPhilipp Zabel break; 752b7482f52SPhilipp Zabel } 753b7482f52SPhilipp Zabel 7541abd9184SPhilipp Zabel return 0; 7551abd9184SPhilipp Zabel 75668020db8SAxel Lin err_free_gpio: 7578614d310SVasily Khoruzhick if (gpio_is_valid(pdata->gpio_reset)) 7588614d310SVasily Khoruzhick gpio_free(pdata->gpio_reset); 7598614d310SVasily Khoruzhick err_out: 7601abd9184SPhilipp Zabel return ret; 7611abd9184SPhilipp Zabel } 7621abd9184SPhilipp Zabel 763f0fba2adSLiam Girdwood /* power down chip */ 764f0fba2adSLiam Girdwood static int uda1380_remove(struct snd_soc_codec *codec) 7651abd9184SPhilipp Zabel { 7661abd9184SPhilipp Zabel struct uda1380_platform_data *pdata =codec->dev->platform_data; 7671abd9184SPhilipp Zabel 768f0fba2adSLiam Girdwood uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); 7691abd9184SPhilipp Zabel 7701abd9184SPhilipp Zabel gpio_free(pdata->gpio_reset); 7711abd9184SPhilipp Zabel gpio_free(pdata->gpio_power); 7721abd9184SPhilipp Zabel 773f0fba2adSLiam Girdwood return 0; 7741abd9184SPhilipp Zabel } 775b7482f52SPhilipp Zabel 776f0fba2adSLiam Girdwood static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { 777f0fba2adSLiam Girdwood .probe = uda1380_probe, 778f0fba2adSLiam Girdwood .remove = uda1380_remove, 779f0fba2adSLiam Girdwood .suspend = uda1380_suspend, 780f0fba2adSLiam Girdwood .resume = uda1380_resume, 781f0fba2adSLiam Girdwood .read = uda1380_read_reg_cache, 782f0fba2adSLiam Girdwood .write = uda1380_write, 783f0fba2adSLiam Girdwood .set_bias_level = uda1380_set_bias_level, 784f0fba2adSLiam Girdwood .reg_cache_size = ARRAY_SIZE(uda1380_reg), 785f0fba2adSLiam Girdwood .reg_word_size = sizeof(u16), 786f0fba2adSLiam Girdwood .reg_cache_default = uda1380_reg, 787f0fba2adSLiam Girdwood .reg_cache_step = 1, 78858fa8e45SAxel Lin 78958fa8e45SAxel Lin .controls = uda1380_snd_controls, 79058fa8e45SAxel Lin .num_controls = ARRAY_SIZE(uda1380_snd_controls), 79158fa8e45SAxel Lin .dapm_widgets = uda1380_dapm_widgets, 79258fa8e45SAxel Lin .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), 79358fa8e45SAxel Lin .dapm_routes = uda1380_dapm_routes, 79458fa8e45SAxel Lin .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes), 795f0fba2adSLiam Girdwood }; 796f0fba2adSLiam Girdwood 797*06b2bd23SFabio Estevam #if IS_ENABLED(CONFIG_I2C) 7987a79e94eSBill Pemberton static int uda1380_i2c_probe(struct i2c_client *i2c, 79988fc39d7SJean Delvare const struct i2c_device_id *id) 800b7482f52SPhilipp Zabel { 8011abd9184SPhilipp Zabel struct uda1380_priv *uda1380; 802b7482f52SPhilipp Zabel int ret; 803b7482f52SPhilipp Zabel 8046ce91ad4SAxel Lin uda1380 = devm_kzalloc(&i2c->dev, sizeof(struct uda1380_priv), 8056ce91ad4SAxel Lin GFP_KERNEL); 8061abd9184SPhilipp Zabel if (uda1380 == NULL) 8071abd9184SPhilipp Zabel return -ENOMEM; 8081abd9184SPhilipp Zabel 8091abd9184SPhilipp Zabel i2c_set_clientdata(i2c, uda1380); 8108614d310SVasily Khoruzhick uda1380->control_data = i2c; 811b7482f52SPhilipp Zabel 812f0fba2adSLiam Girdwood ret = snd_soc_register_codec(&i2c->dev, 813f0fba2adSLiam Girdwood &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); 814b7482f52SPhilipp Zabel return ret; 815b7482f52SPhilipp Zabel } 816b7482f52SPhilipp Zabel 8177a79e94eSBill Pemberton static int uda1380_i2c_remove(struct i2c_client *i2c) 818b7482f52SPhilipp Zabel { 819f0fba2adSLiam Girdwood snd_soc_unregister_codec(&i2c->dev); 820b7482f52SPhilipp Zabel return 0; 821b7482f52SPhilipp Zabel } 822b7482f52SPhilipp Zabel 82388fc39d7SJean Delvare static const struct i2c_device_id uda1380_i2c_id[] = { 82488fc39d7SJean Delvare { "uda1380", 0 }, 82588fc39d7SJean Delvare { } 82688fc39d7SJean Delvare }; 82788fc39d7SJean Delvare MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); 828b7482f52SPhilipp Zabel 829b7482f52SPhilipp Zabel static struct i2c_driver uda1380_i2c_driver = { 830b7482f52SPhilipp Zabel .driver = { 831f0fba2adSLiam Girdwood .name = "uda1380-codec", 832b7482f52SPhilipp Zabel .owner = THIS_MODULE, 833b7482f52SPhilipp Zabel }, 83488fc39d7SJean Delvare .probe = uda1380_i2c_probe, 8357a79e94eSBill Pemberton .remove = uda1380_i2c_remove, 83688fc39d7SJean Delvare .id_table = uda1380_i2c_id, 837b7482f52SPhilipp Zabel }; 838b7482f52SPhilipp Zabel #endif 839b7482f52SPhilipp Zabel 840c9b3a40fSTakashi Iwai static int __init uda1380_modinit(void) 84164089b84SMark Brown { 842ef149770SAxel Lin int ret = 0; 843*06b2bd23SFabio Estevam #if IS_ENABLED(CONFIG_I2C) 8441abd9184SPhilipp Zabel ret = i2c_add_driver(&uda1380_i2c_driver); 8451abd9184SPhilipp Zabel if (ret != 0) 8461abd9184SPhilipp Zabel pr_err("Failed to register UDA1380 I2C driver: %d\n", ret); 8471abd9184SPhilipp Zabel #endif 848ef149770SAxel Lin return ret; 84964089b84SMark Brown } 85064089b84SMark Brown module_init(uda1380_modinit); 85164089b84SMark Brown 85264089b84SMark Brown static void __exit uda1380_exit(void) 85364089b84SMark Brown { 854*06b2bd23SFabio Estevam #if IS_ENABLED(CONFIG_I2C) 8551abd9184SPhilipp Zabel i2c_del_driver(&uda1380_i2c_driver); 8561abd9184SPhilipp Zabel #endif 85764089b84SMark Brown } 85864089b84SMark Brown module_exit(uda1380_exit); 85964089b84SMark Brown 860b7482f52SPhilipp Zabel MODULE_AUTHOR("Giorgio Padrin"); 861b7482f52SPhilipp Zabel MODULE_DESCRIPTION("Audio support for codec Philips UDA1380"); 862b7482f52SPhilipp Zabel MODULE_LICENSE("GPL"); 863