/*
* 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/tlv.h>
#include <sound/uda1380.h>
#include "uda1380.h"
/* codec private data */
struct uda1380_priv {
struct snd_soc_codec *codec;
unsigned int dac_clk;
struct work_struct work;
void *control_data;
};
/*
* 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;
}
static void uda1380_sync_cache(struct snd_soc_codec *codec)
{
int reg;
u8 data[3];
u16 *cache = codec->reg_cache;
/* Sync reg_cache with the hardware */
for (reg = 0; reg < UDA1380_MVOL; reg++) {
data[0] = reg;
data[1] = (cache[reg] & 0xff00) >> 8;
data[2] = cache[reg] & 0x00ff;
if (codec->hw_write(codec->control_data, data, 3) != 3)
dev_err(codec->dev, "%s: write to reg 0x%x failed\n",
__func__, reg);
}
}
static int uda1380_reset(struct snd_soc_codec *codec)
{
struct uda1380_platform_data *pdata = codec->dev->platform_data;
if (gpio_is_valid(pdata->gpio_reset)) {
gpio_set_value(pdata->gpio_reset, 1);
mdelay(1);
gpio_set_value(pdata->gpio_reset, 0);
} else {
u8 data[3];
data[0] = UDA1380_RESET;
data[1] = 0;
data[2] = 0;
if