/*
* uda1380.c - Philips UDA1380 ALSA SoC audio driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Copyright (c) 2007-2009 Philipp Zabel <philipp.zabel@gmail.com>
*
* Modified by Richard Purdie <richard@openedhand.com> to fit into SoC
* codec model.
*
* Copyright (c) 2005 Giorgio Padrin <giorgio@mandarinlogiq.org>
* Copyright 2005 Openedhand Ltd.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/workqueue.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include <sound/uda1380.h>
#include "uda1380.h"
static struct snd_soc_codec *uda1380_codec;
/* codec private data */
struct uda1380_priv {
struct snd_soc_codec codec;
u16 reg_cache[UDA1380_CACHEREGNUM];
unsigned int dac_clk;
struct work_struct work;
};
/*
* uda1380 register cache
*/
static const u16 uda1380_reg[UDA1380_CACHEREGNUM] = {
0x0502, 0x0000, 0x0000, 0x3f3f,
0x0202, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0xff00, 0x0000, 0x4800,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x8000, 0x0002, 0x0000,
};
static unsigned long uda1380_cache_dirty;
/*
* read uda1380 register cache
*/
static inline unsigned int uda1380_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg == UDA1380_RESET)
return 0;
if (reg >= UDA1380_CACHEREGNUM)
return -1;
return cache[reg];
}
/*
* write uda1380 register cache
*/
static inline void uda1380_write_reg_cache(struct snd_soc_codec *codec,
u16 reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
if (reg >= UDA1380_CACHEREGNUM)
return;
if ((reg >= 0x10) && (cache[reg] != value))
set_bit(reg - 0x10, &uda1380_cache_dirty);
cache[reg] = value;
}
/*
* write to the UDA1380 register space
*/
static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[3];
/* data is
* data[0] is register offset
* data[1] is MS byte
* data[2] is LS byte
*/
data[0] = reg;
data[1] = (value & 0xff00) >> 8;
data[2] = value & 0x00ff;
uda1380_write_reg_cache(codec, reg, value);
/* the interpolator & decimator regs must only be written when the
* codec DAI is active.
*/
if (!codec->active && (reg >= UDA1380_MVOL))
return 0;
pr_debug("uda1380: hw write %x val %x\n", reg, value);
if (codec->hw_write(codec->control_data, data, 3) == 3) {
unsigned int val;
i2c_master_send(codec->control_data, data, 1);
i2c_master_recv(codec->control_data, data, 2);
val = (data[0]<<8) | data[1];
if (val != value) {
pr_debug("uda1380: READ BACK VAL %x\n",
(data[0]<<8) | data[1]);
return -EIO;
}
if (reg >= 0x10)
clear_bit(reg - 0x10, &uda1380_cache_dirty);
return 0;
} else
return -EIO;
}
#define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0)
static void uda1380_flush_work(struct work_struct *work)
{
int bit, reg;
for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
reg = 0x10 + bit;
pr_debug("uda1380: flush reg %x val %x:\n", reg,
uda1380_read_reg_cache(uda1380_codec, reg));
uda1380_write(uda1380_codec, reg,
uda1380_read_reg_cache(uda1380_codec, reg));
clear_bit(bit, &uda1380_cache_dirty);
}
}
/* declarations of ALSA reg_elem_REAL controls */
static const char *uda1380_deemp[] = {
"None",
"32kHz",
"44.1kHz",
"48kHz",
"96kHz",
};
static const char *uda1380_input_sel[] = {
"Line",
"Mic + Line R",
"Line L",
"Mic",
};
static const char *uda1380_output_sel[] = {
"DAC",
"Analog Mixer",
};
static const char *uda1380_spf_mode[] = {
"Flat",
"Minimum1",
"Minimum2",
"M