mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
rk30 phone: add TI aic3262 codec driver
This commit is contained in:
@@ -262,6 +262,7 @@ CONFIG_SPI_FPGA_GPIO_IRQ_NUM=0
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_TEST_POWER=y
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_AIC3262_CODEC=y
|
||||
CONFIG_REGULATOR=y
|
||||
CONFIG_MEDIA_SUPPORT=y
|
||||
CONFIG_VIDEO_DEV=y
|
||||
@@ -294,8 +295,10 @@ CONFIG_SND=y
|
||||
CONFIG_SND_SOC=y
|
||||
CONFIG_SND_RK29_SOC=y
|
||||
CONFIG_SND_I2S_DMA_EVENT_STATIC=y
|
||||
CONFIG_SND_RK29_SOC_RT5631=y
|
||||
|
||||
CONFIG_SND_RK29_SOC_AIC3262=y
|
||||
CONFIG_SND_RK29_CODEC_SOC_SLAVE=y
|
||||
CONFIG_SND_SOC_TLV320AIC326X=y
|
||||
CONFIG_HID_A4TECH=y
|
||||
CONFIG_HID_ACRUX=y
|
||||
CONFIG_HID_ACRUX_FF=y
|
||||
|
||||
@@ -1319,6 +1319,15 @@ static struct i2c_board_info __initdata i2c0_info[] = {
|
||||
.flags = 0,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_SND_SOC_TLV320AIC326X)
|
||||
{
|
||||
.type = "tlv320aic3262",
|
||||
.addr = 0x18,
|
||||
.flags = 0,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_SND_SOC_RT5631)
|
||||
{
|
||||
.type = "rt5631",
|
||||
|
||||
@@ -233,6 +233,11 @@ config TWL6030_PWM
|
||||
Say yes here if you want support for TWL6030 PWM.
|
||||
This is used to control charging LED brightness.
|
||||
|
||||
config AIC3262_CODEC
|
||||
bool "Support TI Codec Aic3262"
|
||||
select MFD_CORE
|
||||
default n
|
||||
|
||||
config MFD_STMPE
|
||||
bool "Support STMicroelectronics STMPE"
|
||||
depends on I2C=y && GENERIC_HARDIRQS
|
||||
|
||||
@@ -43,6 +43,7 @@ obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
|
||||
obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
|
||||
obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o
|
||||
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
|
||||
obj-$(CONFIG_AIC3262_CODEC) += tlv320aic3262-core.o tlv320aic3262-irq.o
|
||||
|
||||
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
|
||||
|
||||
|
||||
680
drivers/mfd/tlv320aic3262-core.c
Normal file
680
drivers/mfd/tlv320aic3262-core.c
Normal file
File diff suppressed because it is too large
Load Diff
204
drivers/mfd/tlv320aic3262-irq.c
Normal file
204
drivers/mfd/tlv320aic3262-irq.c
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/mfd/tlv320aic3262-core.h>
|
||||
#include <linux/mfd/tlv320aic3262-registers.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
struct aic3262_irq_data {
|
||||
int mask;
|
||||
int status;
|
||||
};
|
||||
|
||||
static struct aic3262_irq_data aic3262_irqs[] = {
|
||||
{
|
||||
.mask = AIC3262_HEADSET_IN_MASK,
|
||||
.status = AIC3262_HEADSET_PLUG_UNPLUG_INT,
|
||||
},
|
||||
{
|
||||
.mask = AIC3262_BUTTON_PRESS_MASK,
|
||||
.status = AIC3262_BUTTON_PRESS_INT,
|
||||
},
|
||||
{
|
||||
.mask = AIC3262_DAC_DRC_THRES_MASK,
|
||||
.status = AIC3262_LEFT_DRC_THRES_INT | AIC3262_RIGHT_DRC_THRES_INT,
|
||||
},
|
||||
{
|
||||
.mask = AIC3262_AGC_NOISE_MASK,
|
||||
.status = AIC3262_LEFT_AGC_NOISE_INT | AIC3262_RIGHT_AGC_NOISE_INT,
|
||||
},
|
||||
{
|
||||
.mask = AIC3262_OVER_CURRENT_MASK,
|
||||
.status = AIC3262_LEFT_OUTPUT_DRIVER_OVERCURRENT_INT
|
||||
| AIC3262_RIGHT_OUTPUT_DRIVER_OVERCURRENT_INT,
|
||||
},
|
||||
{
|
||||
.mask = AIC3262_OVERFLOW_MASK,
|
||||
.status = AIC3262_LEFT_DAC_OVERFLOW_INT | AIC3262_RIGHT_DAC_OVERFLOW_INT
|
||||
| AIC3262_MINIDSP_D_BARREL_SHIFT_OVERFLOW_INT | AIC3262_LEFT_ADC_OVERFLOW_INT
|
||||
| AIC3262_RIGHT_ADC_OVERFLOW_INT | AIC3262_MINIDSP_D_BARREL_SHIFT_OVERFLOW_INT,
|
||||
},
|
||||
{
|
||||
.mask = AIC3262_SPK_OVERCURRENT_MASK,
|
||||
.status = AIC3262_SPK_OVER_CURRENT_INT,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
struct aic3262_gpio_data {
|
||||
|
||||
};
|
||||
|
||||
static inline struct aic3262_irq_data *irq_to_aic3262_irq(struct aic3262 *aic3262,
|
||||
int irq)
|
||||
{
|
||||
return &aic3262_irqs[irq - aic3262->irq_base];
|
||||
}
|
||||
|
||||
static void aic3262_irq_lock(struct irq_data *data)
|
||||
{
|
||||
struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
|
||||
|
||||
mutex_lock(&aic3262->irq_lock);
|
||||
}
|
||||
|
||||
static void aic3262_irq_sync_unlock(struct irq_data *data)
|
||||
{
|
||||
struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
|
||||
|
||||
/* write back to hardware any change in irq mask */
|
||||
if (aic3262->irq_masks_cur != aic3262->irq_masks_cache) {
|
||||
aic3262->irq_masks_cache = aic3262->irq_masks_cur;
|
||||
aic3262_reg_write(aic3262, AIC3262_INT1_CNTL,
|
||||
aic3262->irq_masks_cur);
|
||||
}
|
||||
|
||||
mutex_unlock(&aic3262->irq_lock);
|
||||
}
|
||||
|
||||
static void aic3262_irq_unmask(struct irq_data *data)
|
||||
{
|
||||
struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
|
||||
struct aic3262_irq_data *irq_data = irq_to_aic3262_irq(aic3262, data->irq);
|
||||
|
||||
aic3262->irq_masks_cur |= irq_data->mask;
|
||||
}
|
||||
|
||||
static void aic3262_irq_mask(struct irq_data *data)
|
||||
{
|
||||
struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
|
||||
struct aic3262_irq_data *irq_data = irq_to_aic3262_irq(aic3262, data->irq);
|
||||
|
||||
aic3262->irq_masks_cur &= ~irq_data->mask;
|
||||
}
|
||||
|
||||
static struct irq_chip aic3262_irq_chip = {
|
||||
.name = "tlv320aic3262",
|
||||
.irq_bus_lock = aic3262_irq_lock,
|
||||
.irq_bus_sync_unlock = aic3262_irq_sync_unlock,
|
||||
.irq_mask = aic3262_irq_mask,
|
||||
.irq_unmask = aic3262_irq_unmask,
|
||||
};
|
||||
|
||||
static irqreturn_t aic3262_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct aic3262 *aic3262 = data;
|
||||
u8 status[4];
|
||||
int i=0;
|
||||
// Reading the sticky bit registers acknowledges the interrupt to the device */
|
||||
aic3262_bulk_read(aic3262, AIC3262_INT_STICKY_FLAG1, 4, status);
|
||||
|
||||
/* report */
|
||||
if(status[2] & aic3262_irqs[AIC3262_IRQ_HEADSET_DETECT].status) // 0
|
||||
{
|
||||
handle_nested_irq(aic3262->irq_base);
|
||||
|
||||
}
|
||||
if(status[2] & aic3262_irqs[AIC3262_IRQ_BUTTON_PRESS].status) // 1
|
||||
handle_nested_irq(aic3262->irq_base + 1);
|
||||
if(status[2] & aic3262_irqs[AIC3262_IRQ_DAC_DRC].status) // 2
|
||||
handle_nested_irq(aic3262->irq_base + 2);
|
||||
if(status[3] & aic3262_irqs[AIC3262_IRQ_AGC_NOISE].status) // 3
|
||||
handle_nested_irq(aic3262->irq_base + 3);
|
||||
if(status[2] & aic3262_irqs[AIC3262_IRQ_OVER_CURRENT].status) // 4
|
||||
handle_nested_irq(aic3262->irq_base + 4);
|
||||
if(status[0] & aic3262_irqs[AIC3262_IRQ_OVERFLOW_EVENT].status) // 5
|
||||
handle_nested_irq(aic3262->irq_base + 5);
|
||||
if(status[3] & aic3262_irqs[AIC3262_IRQ_SPEAKER_OVER_TEMP].status) // 6
|
||||
handle_nested_irq(aic3262->irq_base + 6);
|
||||
|
||||
/* ack unmasked irqs */
|
||||
/* No need to acknowledge the interrupt on AIC3262 */
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int aic3262_irq_init(struct aic3262 *aic3262)
|
||||
{
|
||||
int cur_irq, ret;
|
||||
|
||||
mutex_init(&aic3262->irq_lock);
|
||||
|
||||
/* mask the individual interrupt sources */
|
||||
aic3262->irq_masks_cur = 0x0;
|
||||
aic3262->irq_masks_cache = 0x0;
|
||||
aic3262_reg_write(aic3262, AIC3262_INT1_CNTL, 0x0);
|
||||
|
||||
if (!aic3262->irq) {
|
||||
dev_warn(aic3262->dev,
|
||||
"no interrupt specified, no interrupts\n");
|
||||
aic3262->irq_base = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!aic3262->irq_base) {
|
||||
dev_err(aic3262->dev,
|
||||
"no interrupt base specified, no interrupts\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Register them with genirq */
|
||||
for (cur_irq = aic3262->irq_base;
|
||||
cur_irq < aic3262->irq_base + ARRAY_SIZE(aic3262_irqs);
|
||||
cur_irq++) {
|
||||
irq_set_chip_data(cur_irq, aic3262);
|
||||
irq_set_chip_and_handler(cur_irq, &aic3262_irq_chip,
|
||||
handle_edge_irq);
|
||||
irq_set_nested_thread(cur_irq, 1);
|
||||
|
||||
/* ARM needs us to explicitly flag the IRQ as valid
|
||||
* and will set them noprobe when we do so. */
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(cur_irq, IRQF_VALID);
|
||||
#else
|
||||
set_irq_noprobe(cur_irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(aic3262->irq, NULL, aic3262_irq_thread,
|
||||
IRQF_TRIGGER_RISING,
|
||||
"tlv320aic3262", aic3262);
|
||||
if (ret) {
|
||||
dev_err(aic3262->dev, "failed to request IRQ %d: %d\n",
|
||||
aic3262->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(aic3262_irq_init);
|
||||
|
||||
void aic3262_irq_exit(struct aic3262 *aic3262)
|
||||
{
|
||||
if (aic3262->irq)
|
||||
free_irq(aic3262->irq, aic3262);
|
||||
}
|
||||
EXPORT_SYMBOL(aic3262_irq_exit);
|
||||
256
include/linux/mfd/tlv320aic3262-core.h
Normal file
256
include/linux/mfd/tlv320aic3262-core.h
Normal file
@@ -0,0 +1,256 @@
|
||||
#ifndef __MFD_AIC3262_CORE_H__
|
||||
#define __MFD_AIC3262_CORE_H__
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/core.h>
|
||||
enum aic3262_type {
|
||||
TLV320AIC3262 = 0,
|
||||
};
|
||||
|
||||
|
||||
#define AIC3262_IRQ_HEADSET_DETECT 0
|
||||
#define AIC3262_IRQ_BUTTON_PRESS 1
|
||||
#define AIC3262_IRQ_DAC_DRC 2
|
||||
#define AIC3262_IRQ_AGC_NOISE 3
|
||||
#define AIC3262_IRQ_OVER_CURRENT 4
|
||||
#define AIC3262_IRQ_OVERFLOW_EVENT 5
|
||||
#define AIC3262_IRQ_SPEAKER_OVER_TEMP 6
|
||||
|
||||
#define AIC3262_GPIO1 7
|
||||
#define AIC3262_GPIO2 8
|
||||
#define AIC3262_GPI1 9
|
||||
#define AIC3262_GPI2 10
|
||||
#define AIC3262_GPO1 11
|
||||
|
||||
typedef union aic326x_reg_union {
|
||||
struct aic326x_reg{
|
||||
u8 offset;
|
||||
u8 page;
|
||||
u8 book;
|
||||
u8 reserved;
|
||||
}aic326x_register;
|
||||
unsigned int aic326x_register_int;
|
||||
}aic326x_reg_union;
|
||||
|
||||
|
||||
/**************************** ************************************/
|
||||
|
||||
/*
|
||||
*****************************************************************************
|
||||
* Structures Definitions
|
||||
*****************************************************************************
|
||||
*/
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* @struct aic3262_setup_data |
|
||||
* i2c specific data setup for AIC3262.
|
||||
* @field unsigned short |i2c_address |
|
||||
* Unsigned short for i2c address.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
struct aic3262_setup_data {
|
||||
unsigned short i2c_address;
|
||||
};
|
||||
|
||||
/* GPIO API */
|
||||
#define AIC3262_NUM_GPIO 5 // include 2 GPI and 1 GPO pins
|
||||
enum {
|
||||
AIC3262_GPIO1_FUNC_DISABLED = 0,
|
||||
AIC3262_GPIO1_FUNC_INPUT = 1,
|
||||
AIC3262_GPIO1_FUNC_OUTPUT = 3,
|
||||
AIC3262_GPIO1_FUNC_CLOCK_OUTPUT = 4,
|
||||
AIC3262_GPIO1_FUNC_INT1_OUTPUT = 5,
|
||||
AIC3262_GPIO1_FUNC_INT2_OUTPUT = 6,
|
||||
AIC3262_GPIO1_FUNC_ADC_MOD_CLK_OUTPUT = 10,
|
||||
AIC3262_GPIO1_FUNC_SAR_ADC_INTERRUPT = 12,
|
||||
AIC3262_GPIO1_FUNC_ASI1_DATA_OUTPUT = 15,
|
||||
AIC3262_GPIO1_FUNC_ASI1_WCLK = 16,
|
||||
AIC3262_GPIO1_FUNC_ASI1_BCLK = 17,
|
||||
AIC3262_GPIO1_FUNC_ASI2_WCLK = 18,
|
||||
AIC3262_GPIO1_FUNC_ASI2_BCLK = 19,
|
||||
AIC3262_GPIO1_FUNC_ASI3_WCLK = 20,
|
||||
AIC3262_GPIO1_FUNC_ASI3_BCLK = 21
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
AIC3262_GPIO2_FUNC_DISABLED = 0,
|
||||
AIC3262_GPIO2_FUNC_INPUT = 1,
|
||||
AIC3262_GPIO2_FUNC_OUTPUT = 3,
|
||||
AIC3262_GPIO2_FUNC_CLOCK_OUTPUT = 4,
|
||||
AIC3262_GPIO2_FUNC_INT1_OUTPUT = 5,
|
||||
AIC3262_GPIO2_FUNC_INT2_OUTPUT = 6,
|
||||
AIC3262_GPIO2_FUNC_ADC_MOD_CLK_OUTPUT = 10,
|
||||
AIC3262_GPIO2_FUNC_SAR_ADC_INTERRUPT = 12,
|
||||
AIC3262_GPIO2_FUNC_ASI1_DATA_OUTPUT = 15,
|
||||
AIC3262_GPIO2_FUNC_ASI1_WCLK = 16,
|
||||
AIC3262_GPIO2_FUNC_ASI1_BCLK = 17,
|
||||
AIC3262_GPIO2_FUNC_ASI2_WCLK = 18,
|
||||
AIC3262_GPIO2_FUNC_ASI2_BCLK = 19,
|
||||
AIC3262_GPIO2_FUNC_ASI3_WCLK = 20,
|
||||
AIC3262_GPIO2_FUNC_ASI3_BCLK = 21
|
||||
};
|
||||
enum {
|
||||
AIC3262_GPO1_FUNC_DISABLED = 0,
|
||||
AIC3262_GPO1_FUNC_MSO_OUTPUT_FOR_SPI = 1,
|
||||
AIC3262_GPO1_FUNC_GENERAL_PURPOSE_OUTPUT= 2,
|
||||
AIC3262_GPO1_FUNC_CLOCK_OUTPUT = 3,
|
||||
AIC3262_GPO1_FUNC_INT1_OUTPUT = 4,
|
||||
AIC3262_GPO1_FUNC_INT2_OUTPUT = 5,
|
||||
AIC3262_GPO1_FUNC_ADC_MOD_CLK_OUTPUT = 7,
|
||||
AIC3262_GPO1_FUNC_SAR_ADC_INTERRUPT = 12,
|
||||
AIC3262_GPO1_FUNC_ASI1_DATA_OUTPUT = 15,
|
||||
};
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* @struct aic3262_configs |
|
||||
* AIC3262 initialization data which has register offset and register
|
||||
* value.
|
||||
* @field u8 | book_no |
|
||||
* AIC3262 Book Number Offsets required for initialization..
|
||||
* @field u16 | reg_offset |
|
||||
* AIC3262 Register offsets required for initialization..
|
||||
* @field u8 | reg_val |
|
||||
* value to set the AIC3262 register to initialize the AIC3262.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
struct aic3262_configs {
|
||||
u8 book_no;
|
||||
u16 reg_offset;
|
||||
u8 reg_val;
|
||||
};
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* @struct aic3262_rate_divs |
|
||||
* Setting up the values to get different freqencies
|
||||
*
|
||||
* @field u32 | mclk |
|
||||
* Master clock
|
||||
* @field u32 | rate |
|
||||
* sample rate
|
||||
* @field u8 | p_val |
|
||||
* value of p in PLL
|
||||
* @field u32 | pll_j |
|
||||
* value for pll_j
|
||||
* @field u32 | pll_d |
|
||||
* value for pll_d
|
||||
* @field u32 | dosr |
|
||||
* value to store dosr
|
||||
* @field u32 | ndac |
|
||||
* value for ndac
|
||||
* @field u32 | mdac |
|
||||
* value for mdac
|
||||
* @field u32 | aosr |
|
||||
* value for aosr
|
||||
* @field u32 | nadc |
|
||||
* value for nadc
|
||||
* @field u32 | madc |
|
||||
* value for madc
|
||||
* @field u32 | blck_N |
|
||||
* value for block N
|
||||
*/
|
||||
struct aic3262 {
|
||||
struct mutex io_lock;
|
||||
struct mutex irq_lock;
|
||||
|
||||
enum aic3262_type type;
|
||||
|
||||
struct device *dev;
|
||||
int (*read_dev)(struct aic3262 *aic3262, unsigned int reg,
|
||||
int bytes, void *dest);
|
||||
int (*write_dev)(struct aic3262 *aic3262, unsigned int reg,
|
||||
int bytes, const void *src);
|
||||
|
||||
void *control_data;
|
||||
|
||||
// int gpio_base;
|
||||
|
||||
unsigned int irq;
|
||||
unsigned int irq_base;
|
||||
|
||||
u8 irq_masks_cur;
|
||||
u8 irq_masks_cache;
|
||||
|
||||
/* Used over suspend/resume */
|
||||
bool suspended;
|
||||
|
||||
u8 book_no;
|
||||
u8 page_no;
|
||||
};
|
||||
|
||||
struct aic3262_gpio_setup
|
||||
{
|
||||
u8 used; // GPIO, GPI and GPO is used in the board, used = 1 else 0
|
||||
u8 in; // GPIO is used as input, in = 1 else in = 0. GPI in = 1, GPO in = 0
|
||||
unsigned int in_reg; // if GPIO is input, register to write the mask to.
|
||||
u8 in_reg_bitmask; // bitmask for 'value' to be written into in_reg
|
||||
u8 in_reg_shift; // bits to shift to write 'value' into in_reg
|
||||
u8 value; // value to be written gpio_control_reg if GPIO is output, in_reg if its input
|
||||
};
|
||||
struct aic3262_pdata {
|
||||
unsigned int audio_mclk1;
|
||||
unsigned int audio_mclk2;
|
||||
unsigned int gpio_irq; /* whether AIC3262 interrupts the host AP on a GPIO pin of AP */
|
||||
unsigned int gpio_reset; /* is the codec being reset by a gpio [host] pin, if yes provide the number. */
|
||||
struct aic3262_gpio_setup *gpio;/* all gpio configuration */
|
||||
int naudint_irq; /* audio interrupt */
|
||||
unsigned int irq_base;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static inline int aic3262_request_irq(struct aic3262 *aic3262, int irq,
|
||||
irq_handler_t handler, unsigned long irqflags,const char *name,
|
||||
void *data)
|
||||
{
|
||||
if (!aic3262->irq_base)
|
||||
return -EINVAL;
|
||||
|
||||
return request_threaded_irq(aic3262->irq_base + irq, NULL, handler,
|
||||
irqflags, name, data);
|
||||
}
|
||||
|
||||
static inline void aic3262_free_irq(struct aic3262 *aic3262, int irq,
|
||||
void *data)
|
||||
{
|
||||
if (!aic3262->irq_base)
|
||||
return;
|
||||
|
||||
free_irq(aic3262->irq_base + irq, data);
|
||||
}
|
||||
|
||||
/* Device I/O API */
|
||||
int aic3262_reg_read(struct aic3262 *aic3262, unsigned int reg);
|
||||
int aic3262_reg_write(struct aic3262 *aic3262, unsigned int reg,
|
||||
unsigned char val);
|
||||
int aic3262_set_bits(struct aic3262 *aic3262, unsigned int reg,
|
||||
unsigned char mask, unsigned char val);
|
||||
int aic3262_bulk_read(struct aic3262 *aic3262, unsigned int reg,
|
||||
int count, u8 *buf);
|
||||
int aic3262_bulk_write(struct aic3262 *aic3262, unsigned int reg,
|
||||
int count, const u8 *buf);
|
||||
|
||||
|
||||
/* Helper to save on boilerplate */
|
||||
/*static inline int aic3262_request_irq(struct aic3262 *aic3262, int irq,
|
||||
irq_handler_t handler, const char *name,
|
||||
void *data)
|
||||
{
|
||||
if (!aic3262->irq_base)
|
||||
return -EINVAL;
|
||||
return request_threaded_irq(aic3262->irq_base + irq, NULL, handler,
|
||||
IRQF_TRIGGER_RISING, name,
|
||||
data);
|
||||
}
|
||||
static inline void aic3262_free_irq(struct aic3262 *aic3262, int irq, void *data)
|
||||
{
|
||||
if (!aic3262->irq_base)
|
||||
return;
|
||||
free_irq(aic3262->irq_base + irq, data);
|
||||
}
|
||||
*/
|
||||
int aic3262_irq_init(struct aic3262 *aic3262);
|
||||
void aic3262_irq_exit(struct aic3262 *aic3262);
|
||||
|
||||
#endif
|
||||
301
include/linux/mfd/tlv320aic3262-registers.h
Normal file
301
include/linux/mfd/tlv320aic3262-registers.h
Normal file
@@ -0,0 +1,301 @@
|
||||
|
||||
#ifndef __MFD_AIC3262_REGISTERS_H__
|
||||
#define __MFD_AIC3262_REGISTERS_H__
|
||||
/*typedef union aic326x_reg_union {
|
||||
struct aic326x_reg{
|
||||
u8 reserved;
|
||||
u8 book;
|
||||
u8 page;
|
||||
u8 offset;
|
||||
}aic326x_register;
|
||||
unsigned int aic326x_register_int;
|
||||
}aic326x_reg_union;*/
|
||||
#define MAKE_REG(book, page, offset) (unsigned int)((book << 16)|(page << 8)|offset)
|
||||
|
||||
/* ****************** Book 0 Registers **************************************/
|
||||
|
||||
/* ****************** Page 0 Registers **************************************/
|
||||
#define AIC3262_PAGE_SEL_REG MAKE_REG(0,0,0)
|
||||
#define AIC3262_RESET_REG MAKE_REG(0,0,1)
|
||||
#define AIC3262_REV_PG_ID MAKE_REG(0,0,2)
|
||||
#define AIC3262_REV_MASK (0b01110000)
|
||||
#define AIC3262_REV_SHIFT 4
|
||||
#define AIC3262_PG_MASK (0b00000111)
|
||||
#define AIC3262_PG_SHIFT 0
|
||||
#define AIC3262_DAC_ADC_CLKIN_REG MAKE_REG(0,0,4)
|
||||
#define AIC3262_PLL_CLKIN_REG MAKE_REG(0,0,5)
|
||||
#define AIC3262_PLL_CLKIN_MASK (0b00111100)
|
||||
#define AIC3262_PLL_CLKIN_SHIFT 2
|
||||
#define AIC3262_PLL_CLKIN_MCLK1 0
|
||||
#define AIC3262_PLL_CLKIN_BCLK1 1
|
||||
#define AIC3262_PLL_CLKIN_GPIO1 2
|
||||
#define AIC3262_PLL_CLKIN_DIN1 3
|
||||
#define AIC3262_PLL_CLKIN_BCLK2 4
|
||||
#define AIC3262_PLL_CLKIN_GPI1 5
|
||||
#define AIC3262_PLL_CLKIN_HF_REF_CLK 6
|
||||
#define AIC3262_PLL_CLKIN_GPIO2 7
|
||||
#define AIC3262_PLL_CLKIN_GPI2 8
|
||||
#define AIC3262_PLL_CLKIN_MCLK2 9
|
||||
#define AIC3262_CLK_VAL_MASK 0x7f
|
||||
#define AIC3262_PLL_CLK_RANGE_REG MAKE_REG(0,0,5)
|
||||
#define AIC3262_PLL_PR_POW_REG MAKE_REG(0,0,6)
|
||||
#define AIC3262_PLL_PVAL_MASK 0x70
|
||||
#define AIC3262_PLL_RVAL_MASK 0x0F
|
||||
|
||||
#define AIC3262_ENABLE_CLK_MASK 0x80
|
||||
#define AIC3262_ENABLE_CLK 0x80
|
||||
|
||||
|
||||
#define AIC3262_PLL_J_REG MAKE_REG(0,0,7)
|
||||
#define AIC3262_JVAL_MASK 0x3f
|
||||
#define AIC3262_PLL_D_MSB MAKE_REG(0,0,8)
|
||||
#define AIC3262_DVAL_MSB_MASK 0xf
|
||||
#define AIC3262_DVAL_LSB_MASK 0xff
|
||||
#define AIC3262_PLL_D_LSB MAKE_REG(0,0,9)
|
||||
#define AIC3262_PLL_CKIN_DIV MAKE_REG(0,0,10)
|
||||
|
||||
#define AIC3262_NDAC_DIV_POW_REG MAKE_REG(0,0,11)
|
||||
#define AIC3262_MDAC_DIV_POW_REG MAKE_REG(0,0,12)
|
||||
#define AIC3262_DOSR_MSB_REG MAKE_REG(0,0,13)
|
||||
#define AIC3262_DOSR_MSB_MASK 0x3
|
||||
#define AIC3262_DOSR_LSB_REG MAKE_REG(0,0,14)
|
||||
#define AIC3262_DOSR_LSB_MASK 0xFF
|
||||
|
||||
#define AIC3262_NADC_DIV_POW_REG MAKE_REG(0,0,18)
|
||||
#define AIC3262_MADC_DIV_POW_REG MAKE_REG(0,0,19)
|
||||
#define AIC3262_AOSR_REG MAKE_REG(0,0,20)
|
||||
#define AIC3262_CLKOUT_MUX MAKE_REG(0,0,21)
|
||||
#define AIC3262_CLKOUT_MDIV_VAL MAKE_REG(0,0,22)
|
||||
#define AIC3262_TIMER_REG MAKE_REG(0,0,23)
|
||||
|
||||
#define AIC3262_LF_CLK_CNTL MAKE_REG(0,0,24)
|
||||
#define AIC3262_HF_CLK_CNTL_R1 MAKE_REG(0,0,25)
|
||||
#define AIC3262_HF_CLK_CNTL_R2 MAKE_REG(0,0,26)
|
||||
#define AIC3262_HF_CLK_CNTL_R3 MAKE_REG(0,0,27)
|
||||
#define AIC3262_HF_CLK_CNTL_R4 MAKE_REG(0,0,28)
|
||||
#define AIC3262_HF_CLK_TRIM_R1 MAKE_REG(0,0,29)
|
||||
#define AIC3262_HF_CLK_TRIM_R2 MAKE_REG(0,0,30)
|
||||
#define AIC3262_HF_CLK_TRIM_R3 MAKE_REG(0,0,31)
|
||||
#define AIC3262_HF_CLK_TRIM_R4 MAKE_REG(0,0,32)
|
||||
#define AIC3262_LDAC_POWER_MASK 0x80
|
||||
#define AIC3262_RDAC_POWER_MASK 0x08
|
||||
#define AIC3262_DAC_FLAG MAKE_REG(0,0,37)
|
||||
#define AIC3262_ADC_FLAG MAKE_REG(0,0,36)
|
||||
#define AIC3262_JACK_WITH_STEREO_HS (0b00000010)
|
||||
#define AIC3262_JACK_WITH_MIC (0b00110000)
|
||||
#define AIC3262_HEADSET_NOT_INSERTED (0b00000011)
|
||||
|
||||
#define AIC3262_INT_STICKY_FLAG1 MAKE_REG(0,0,42)
|
||||
#define AIC3262_LEFT_DAC_OVERFLOW_INT 0x80
|
||||
#define AIC3262_RIGHT_DAC_OVERFLOW_INT 0x40
|
||||
#define AIC3262_MINIDSP_D_BARREL_SHIFT_OVERFLOW_INT 0x20
|
||||
#define AIC3262_LEFT_ADC_OVERFLOW_INT 0x08
|
||||
#define AIC3262_RIGHT_ADC_OVERFLOW_INT 0x04
|
||||
#define AIC3262_MINIDSP_A_BARREL_SHIFT_OVERFLOW_INT 0x02
|
||||
#define AIC3262_INT_STICKY_FLAG2 MAKE_REG(0,0,44)
|
||||
#define AIC3262_LEFT_OUTPUT_DRIVER_OVERCURRENT_INT 0x80
|
||||
#define AIC3262_RIGHT_OUTPUT_DRIVER_OVERCURRENT_INT 0x40
|
||||
#define AIC3262_BUTTON_PRESS_INT 0x20
|
||||
#define AIC3262_HEADSET_PLUG_UNPLUG_INT 0x10
|
||||
#define AIC3262_LEFT_DRC_THRES_INT 0x08
|
||||
#define AIC3262_RIGHT_DRC_THRES_INT 0x04
|
||||
#define AIC3262_MINIDSP_D_STD_INT 0x02
|
||||
#define AIC3262_RIGHT_DRC_AUX_INT 0x01
|
||||
#define AIC3262_INT_STICKY_FLAG3 MAKE_REG(0,0,45)
|
||||
#define AIC3262_SPK_OVER_CURRENT_INT 0x80
|
||||
#define AIC3262_LEFT_AGC_NOISE_INT 0x40
|
||||
#define AIC3262_RIGHT_AGC_NOISE_INT 0x20
|
||||
#define AIC3262_INT1_CNTL MAKE_REG(0,0,48)
|
||||
#define AIC3262_HEADSET_IN_MASK 0x80
|
||||
#define AIC3262_BUTTON_PRESS_MASK 0x40
|
||||
#define AIC3262_DAC_DRC_THRES_MASK 0x20
|
||||
#define AIC3262_AGC_NOISE_MASK 0x10
|
||||
#define AIC3262_OVER_CURRENT_MASK 0x08
|
||||
#define AIC3262_OVERFLOW_MASK 0x04
|
||||
#define AIC3262_SPK_OVERCURRENT_MASK 0x02
|
||||
#define AIC3262_INT2_CNTL MAKE_REG(0,0,49)
|
||||
#define AIC3262_INT_FMT MAKE_REG(0,0,51)
|
||||
|
||||
#define AIC3262_DAC_PRB MAKE_REG(0,0,60)
|
||||
#define AIC3262_ADC_PRB MAKE_REG(0,0,61)
|
||||
#define AIC3262_PASI_DAC_DP_SETUP MAKE_REG(0,0,63)
|
||||
|
||||
#define AIC3262_DAC_MVOL_CONF MAKE_REG(0,0,64)
|
||||
#define AIC3262_DAC_LR_MUTE_MASK 0xc
|
||||
#define AIC3262_DAC_LR_MUTE 0xc
|
||||
|
||||
#define AIC3262_DAC_LVOL MAKE_REG(0,0,65)
|
||||
#define AIC3262_DAC_RVOL MAKE_REG(0,0,66)
|
||||
#define AIC3262_HP_DETECT MAKE_REG(0,0,67)
|
||||
#define AIC3262_DRC_CNTL_R1 MAKE_REG(0,0,68)
|
||||
#define AIC3262_DRC_CNTL_R2 MAKE_REG(0,0,69)
|
||||
#define AIC3262_DRC_CNTL_R3 MAKE_REG(0,0,70)
|
||||
#define AIC3262_BEEP_CNTL_R1 MAKE_REG(0,0,71)
|
||||
#define AIC3262_BEEP_CNTL_R2 MAKE_REG(0,0,72)
|
||||
|
||||
#define AIC3262_ADC_CHANNEL_POW MAKE_REG(0,0,81)
|
||||
#define AIC3262_ADC_FINE_GAIN MAKE_REG(0,0,82)
|
||||
#define AIC3262_LADC_VOL MAKE_REG(0,0,83)
|
||||
#define AIC3262_RADC_VOL MAKE_REG(0,0,84)
|
||||
#define AIC3262_ADC_PHASE MAKE_REG(0,0,85)
|
||||
|
||||
#define AIC3262_LAGC_CNTL MAKE_REG(0,0,86)
|
||||
#define AIC3262_LAGC_CNTL_R2 MAKE_REG(0,0,87)
|
||||
#define AIC3262_LAGC_CNTL_R3 MAKE_REG(0,0,88)
|
||||
#define AIC3262_LAGC_CNTL_R4 MAKE_REG(0,0,89)
|
||||
#define AIC3262_LAGC_CNTL_R5 MAKE_REG(0,0,90)
|
||||
#define AIC3262_LAGC_CNTL_R6 MAKE_REG(0,0,91)
|
||||
#define AIC3262_LAGC_CNTL_R7 MAKE_REG(0,0,92)
|
||||
#define AIC3262_LAGC_CNTL_R8 MAKE_REG(0,0,93)
|
||||
|
||||
#define AIC3262_RAGC_CNTL MAKE_REG(0,0,94)
|
||||
#define AIC3262_RAGC_CNTL_R2 MAKE_REG(0,0,95)
|
||||
#define AIC3262_RAGC_CNTL_R3 MAKE_REG(0,0,96)
|
||||
#define AIC3262_RAGC_CNTL_R4 MAKE_REG(0,0,97)
|
||||
#define AIC3262_RAGC_CNTL_R5 MAKE_REG(0,0,98)
|
||||
#define AIC3262_RAGC_CNTL_R6 MAKE_REG(0,0,99)
|
||||
#define AIC3262_RAGC_CNTL_R7 MAKE_REG(0,0,100)
|
||||
#define AIC3262_RAGC_CNTL_R8 MAKE_REG(0,0,101)
|
||||
#define AIC3262_MINIDSP_ACCESS_CTRL MAKE_REG(0,0,121)
|
||||
/* ****************** Page 1 Registers **************************************/
|
||||
#define AIC3262_PAGE_1 128
|
||||
|
||||
#define AIC3262_POWER_CONF MAKE_REG(0,1, 1)
|
||||
|
||||
#define AIC3262_AVDD_TO_DVDD_MASK (0b00001000)
|
||||
#define AIC3262_AVDD_TO_DVDD 0x8
|
||||
#define AIC3262_EXT_ANALOG_SUPPLY_MASK (0b00001000)
|
||||
#define AIC3262_EXT_ANALOG_SUPPLY_OFF 0x4
|
||||
|
||||
#define AIC3262_LDAC_PTM MAKE_REG(0,1, 3)
|
||||
#define AIC3262_RDAC_PTM MAKE_REG(0,1, 4)
|
||||
#define AIC3262_CM_REG MAKE_REG(0,1, 8)
|
||||
#define AIC3262_HP_CTL MAKE_REG(0,1, 9)
|
||||
#define AIC3262_HP_DEPOP MAKE_REG(0,1, 11)
|
||||
#define AIC3262_RECV_DEPOP MAKE_REG(0,1, 12)
|
||||
#define AIC3262_MA_CNTL MAKE_REG(0,1, 17)
|
||||
#define AIC3262_LADC_PGA_MAL_VOL MAKE_REG(0,1, 18)
|
||||
#define AIC3262_RADC_PGA_MAR_VOL MAKE_REG(0,1, 19)
|
||||
|
||||
|
||||
#define AIC3262_LINE_AMP_CNTL_R1 MAKE_REG(0,1, 22)
|
||||
#define AIC3262_LINE_AMP_CNTL_R2 MAKE_REG(0,1, 23)
|
||||
|
||||
#define AIC3262_HP_AMP_CNTL_R1 MAKE_REG(0,1, 27)
|
||||
#define AIC3262_HP_AMP_CNTL_R2 MAKE_REG(0,1, 28)
|
||||
#define AIC3262_HP_AMP_CNTL_R3 MAKE_REG(0,1, 29)
|
||||
|
||||
#define AIC3262_HPL_VOL MAKE_REG(0,1, 31)
|
||||
#define AIC3262_HPR_VOL MAKE_REG(0,1, 32)
|
||||
#define AIC3262_INT1_SEL_L MAKE_REG(0,1, 34)
|
||||
#define AIC3262_CHARGE_PUMP_CNTL MAKE_REG(0,1, 35)
|
||||
#define AIC3262_RAMP_CNTL_R1 MAKE_REG(0,1, 36)
|
||||
#define AIC3262_RAMP_CNTL_R2 MAKE_REG(0,1, 37)
|
||||
#define AIC3262_IN1L_SEL_RM MAKE_REG(0,1, 38)
|
||||
#define AIC3262_IN1R_SEL_RM MAKE_REG(0,1, 39)
|
||||
#define AIC3262_REC_AMP_CNTL_R5 MAKE_REG(0,1, 40)
|
||||
#define AIC3262_RAMPR_VOL MAKE_REG(0,1, 41)
|
||||
#define AIC3262_RAMP_TIME_CNTL MAKE_REG(0,1, 42)
|
||||
#define AIC3262_SPK_AMP_CNTL_R1 MAKE_REG(0,1, 45)
|
||||
#define AIC3262_SPK_AMP_CNTL_R2 MAKE_REG(0,1, 46)
|
||||
#define AIC3262_SPK_AMP_CNTL_R3 MAKE_REG(0,1, 47)
|
||||
#define AIC3262_SPK_AMP_CNTL_R4 MAKE_REG(0,1, 48)
|
||||
#define AIC3262_MIC_BIAS_CNTL MAKE_REG(0,1, 51)
|
||||
|
||||
#define AIC3262_LMIC_PGA_PIN MAKE_REG(0,1, 52)
|
||||
#define AIC3262_LMIC_PGA_PM_IN4 MAKE_REG(0,1, 53)
|
||||
#define AIC3262_LMIC_PGA_MIN MAKE_REG(0,1, 54)
|
||||
#define AIC3262_RMIC_PGA_PIN MAKE_REG(0,1, 55)
|
||||
#define AIC3262_RMIC_PGA_PM_IN4 MAKE_REG(0,1, 56)
|
||||
#define AIC3262_RMIC_PGA_MIN MAKE_REG(0,1, 57)
|
||||
#define AIC3262_HP_FLAG MAKE_REG(0,1,66)
|
||||
#define AIC3262_SPKL_POWER_MASK 0x2
|
||||
#define AIC3262_SPKR_POWER_MASK 0x1
|
||||
#define AIC3262_HPL_POWER_MASK 0x20
|
||||
#define AIC3262_HPR_POWER_MASK 0x10
|
||||
/* MIC PGA Gain Registers */
|
||||
#define AIC3262_MICL_PGA MAKE_REG(0,1, 59)
|
||||
#define AIC3262_MICR_PGA MAKE_REG(0,1, 60)
|
||||
#define AIC3262_HEADSET_TUNING1_REG MAKE_REG(0,1, 119)
|
||||
#define AIC3262_HEADSET_DETECTOR_PULSE_MASK (0b11000000)
|
||||
#define AIC3262_HEADSET_DETECTOR_PULSE_RESET (0B10000000)
|
||||
#define AIC3262_MIC_PWR_DLY MAKE_REG(0,1, 121)
|
||||
#define AIC3262_REF_PWR_DLY MAKE_REG(0,1, 122)
|
||||
#define AIC3262_CHIP_REF_PWR_ON_MASK 0x4
|
||||
#define AIC3262_CHIP_REF_PWR_ON 0x4
|
||||
/* ****************** Page 4 Registers **************************************/
|
||||
#define AIC3262_PAGE_4 512
|
||||
#define AIC3262_ASI1_BUS_FMT MAKE_REG(0,4, 1)
|
||||
#define AIC3262_ASI_SELECTION_MASK (0b1100000)
|
||||
#define AIC3262_ASI_DATA_WORD_LENGTH_MASK (0b0011000)
|
||||
#define AIC3262_ASI_BCLK_N_MASK (0b01111111)
|
||||
#define AIC3262_ASI1_LCH_OFFSET MAKE_REG(0,4, 2)
|
||||
#define AIC3262_ASI1_RCH_OFFSET MAKE_REG(0,4, 3)
|
||||
#define AIC3262_ASI1_CHNL_SETUP MAKE_REG(0,4, 4)
|
||||
#define AIC3262_ASI1_MULTI_CH_SETUP_R1 MAKE_REG(0,4, 5)
|
||||
#define AIC3262_ASI1_MULTI_CH_SETUP_R2 MAKE_REG(0,4, 6)
|
||||
#define AIC3262_ASI1_ADC_INPUT_CNTL MAKE_REG(0,4, 7)
|
||||
#define AIC3262_ASI1_DAC_OUT_CNTL MAKE_REG(0,4, 8)
|
||||
#define AIC3262_ASI1_ADC_OUT_TRISTATE MAKE_REG(0,4, 9)
|
||||
#define AIC3262_ASI1_BWCLK_CNTL_REG MAKE_REG(0,4, 10)
|
||||
#define AIC3262_ASI1_BCLK_N_CNTL MAKE_REG(0,4, 11)
|
||||
#define AIC3262_ASI1_BCLK_N MAKE_REG(0,4, 12)
|
||||
#define AIC3262_ASI1_WCLK_N MAKE_REG(0,4, 13)
|
||||
#define AIC3262_ASI1_BWCLK_OUT_CNTL MAKE_REG(0,4, 14)
|
||||
#define AIC3262_ASI1_DOUT_CNTL MAKE_REG(0,4, 15)
|
||||
#define AIC3262_ASI2_BUS_FMT MAKE_REG(0,4, 17)
|
||||
#define AIC3262_ASI2_LCH_OFFSET MAKE_REG(0,4, 18)
|
||||
#define AIC3262_ASI2_ADC_INPUT_CNTL MAKE_REG(0,4, 23)
|
||||
#define AIC3262_ASI2_DAC_OUT_CNTL MAKE_REG(0,4, 24)
|
||||
#define AIC3262_ASI2_BWCLK_CNTL_REG MAKE_REG(0,4, 26)
|
||||
#define AIC3262_ASI2_BCLK_N_CNTL MAKE_REG(0,4, 27)
|
||||
#define AIC3262_ASI2_BCLK_N MAKE_REG(0,4, 28)
|
||||
#define AIC3262_ASI2_WCLK_N MAKE_REG(0,4, 29)
|
||||
#define AIC3262_ASI2_BWCLK_OUT_CNTL MAKE_REG(0,4, 30)
|
||||
#define AIC3262_ASI2_DOUT_CNTL MAKE_REG(0,4, 31)
|
||||
#define AIC3262_ASI3_BUS_FMT MAKE_REG(0,4, 33)
|
||||
#define AIC3262_ASI3_LCH_OFFSET MAKE_REG(0,4, 34)
|
||||
#define AIC3262_ASI3_ADC_INPUT_CNTL MAKE_REG(0,4, 39)
|
||||
#define AIC3262_ASI3_DAC_OUT_CNTL MAKE_REG(0,4, 40)
|
||||
#define AIC3262_ASI3_BWCLK_CNTL_REG MAKE_REG(0,4, 42)
|
||||
#define AIC3262_ASI3_BCLK_N_CNTL MAKE_REG(0,4, 43)
|
||||
#define AIC3262_ASI3_BCLK_N MAKE_REG(0,4, 44)
|
||||
#define AIC3262_ASI3_WCLK_N MAKE_REG(0,4, 45)
|
||||
#define AIC3262_ASI3_BWCLK_OUT_CNTL MAKE_REG(0,4, 46)
|
||||
#define AIC3262_ASI3_DOUT_CNTL MAKE_REG(0,4, 47)
|
||||
#define AIC3262_DMIC_INPUT_CNTL MAKE_REG(0,4, 101)
|
||||
#define AIC3262_GPIO1_IO_CNTL MAKE_REG(0,4, 86)
|
||||
#define AIC3262_GPIO_D6_D2 (0b01111100)
|
||||
#define AIC3262_GPIO_D2_SHIFT (2)
|
||||
#define AIC3262_GPIO_D1_SHIFT (1)
|
||||
#define AIC3262_GPIO_D4_SHIFT (4)
|
||||
#define AIC3262_GPIO2_IO_CNTL MAKE_REG(0,4, 87)
|
||||
#define AIC3262_GPI1_EN MAKE_REG(0,4, 91)
|
||||
#define AIC3262_GPI1_D2_D1 (0b00000110)
|
||||
#define AIC3262_GPI2_D5_D4 (0b00110000)
|
||||
#define AIC3262_GPI2_EN MAKE_REG(0, 4, 92)
|
||||
#define AIC3262_GPO1_OUT_CNTL MAKE_REG(0, 4, 96)
|
||||
#define AIC3262_GPO1_D4_D1 (0b00011110)
|
||||
#define AIC3262_DMIC_INPUT_CONTROL MAKE_REG(0, 4, 101)
|
||||
#define AIC3262_DMIC_CONFIGURE_MASK (0b00011111)
|
||||
#define AIC3262_DMIC_CONFIGURE_SHIFT (0)
|
||||
#define AIC3262_MINIDSP_DATA_PORT_CNTL MAKE_REG(0, 4, 118)
|
||||
|
||||
#define AIC3262_DAC_ASI_LR_UNMUTE_MASK 0x50
|
||||
#define AIC3262_DAC_ASI_LR_UNMUTE 0x50
|
||||
#define AIC3262_WCLK_BCLK_MASTER_MASK (0b00100110)
|
||||
#define AIC3262_WCLK_MASTER_MASK (0b00100000)
|
||||
#define AIC3262_BCLK_MASTER_MASK (0b00000100)
|
||||
#define AIC3262_BCLK_OFFSET_MASK (0b11111111)
|
||||
#define AIC3262_ASI_INTERFACE_MASK (0b11100000)
|
||||
#define AIC3262_WCLK_OUT_MASK (0b00100000)
|
||||
#define AIC3262_BCLK_OUT_MASK (0b00000100)
|
||||
#define AIC3262_BCLK_INV_MASK (0b00000010)
|
||||
|
||||
#define AIC3262_ADC_ADAPTIVE_CRAM_REG MAKE_REG(40,0,1)
|
||||
#define AIC3262_DAC_ADAPTIVE_BANK1_REG MAKE_REG(80,0,1)
|
||||
#define AIC3262_DAC_ADAPTIVE_BANK2_REG MAKE_REG(82,0,1)
|
||||
#define AIC3262_ADC_DATAPATH_SETUP MAKE_REG(0,0,81)
|
||||
#define AIC3262_DAC_DATAPATH_SETUP MAKE_REG(0,0,63)
|
||||
|
||||
#endif
|
||||
@@ -247,6 +247,9 @@ config SND_SOC_TLV320DAC33
|
||||
config SND_SOC_TLV320AIC3111
|
||||
tristate
|
||||
|
||||
config SND_SOC_TLV320AIC326X
|
||||
tristate
|
||||
|
||||
config SND_SOC_TWL4030
|
||||
select TWL4030_CODEC
|
||||
tristate
|
||||
|
||||
@@ -35,6 +35,7 @@ snd-soc-tlv320aic3x-objs := tlv320aic3x.o
|
||||
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
|
||||
snd-soc-tlv320aic3111-objs := tlv320aic3111.o
|
||||
snd-soc-tlv320dac33-objs := tlv320dac33.o
|
||||
snd-soc-tlv320aic326x-objs := tlv320aic326x.o aic326x_tiload.o aic3xxx_cfw_ops.o aic3262_codec_ops.o
|
||||
snd-soc-twl4030-objs := twl4030.o
|
||||
snd-soc-twl6040-objs := twl6040.o
|
||||
snd-soc-uda134x-objs := uda134x.o
|
||||
@@ -134,6 +135,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
|
||||
obj-$(CONFIG_SND_SOC_TVL320AIC32X4) += snd-soc-tlv320aic32x4.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC3111) += snd-soc-tlv320aic3111.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC326X) += snd-soc-tlv320aic326x.o
|
||||
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
|
||||
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
|
||||
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
|
||||
|
||||
407
sound/soc/codecs/aic3262_codec_ops.c
Normal file
407
sound/soc/codecs/aic3262_codec_ops.c
Normal file
@@ -0,0 +1,407 @@
|
||||
#include "aic3xxx_cfw.h"
|
||||
#include "aic3xxx_cfw_ops.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mfd/tlv320aic3262-core.h>
|
||||
#include <linux/mfd/tlv320aic3262-registers.h>
|
||||
#include "tlv320aic326x.h"
|
||||
#include <sound/soc.h>
|
||||
#include "aic3262_codec_ops.h"
|
||||
|
||||
#define DSP_STATUS(rs,adc_dac,rpos,rspos) rs |= ( ((adc_dac>>rpos) & 1) << rspos)
|
||||
|
||||
|
||||
|
||||
int aic3262_ops_reg_read(void *p,unsigned int reg)
|
||||
{
|
||||
struct aic3262_priv *ps = p;
|
||||
cfw_register *c = (cfw_register *) ®
|
||||
aic326x_reg_union mreg;
|
||||
|
||||
mreg.aic326x_register.offset = c->offset;
|
||||
mreg.aic326x_register.page = c->page;
|
||||
mreg.aic326x_register.book = c->book;
|
||||
mreg.aic326x_register.reserved = 0;
|
||||
|
||||
return aic3262_reg_read(ps->codec->control_data,
|
||||
mreg.aic326x_register_int);
|
||||
|
||||
}
|
||||
int aic3262_ops_reg_write(void *p,unsigned int reg,unsigned char mval)
|
||||
{
|
||||
struct aic3262_priv *ps = p;
|
||||
aic326x_reg_union mreg;
|
||||
cfw_register *c = (cfw_register *) ®
|
||||
|
||||
mreg.aic326x_register.offset = c->offset;
|
||||
mreg.aic326x_register.page = c->page;
|
||||
mreg.aic326x_register.book = c->book;
|
||||
mreg.aic326x_register.reserved = 0;
|
||||
mval = c->data;
|
||||
DBG("reg_write:page %d book %d offset %d mval : %#x\n",mreg.aic326x_register.page,mreg.aic326x_register.book,mreg.aic326x_register.offset,mval);
|
||||
|
||||
return aic3262_reg_write(ps->codec->control_data, mreg.aic326x_register_int, mval);
|
||||
}
|
||||
|
||||
int aic3262_ops_set_bits(void *p,unsigned int reg,
|
||||
unsigned char mask, unsigned char val)
|
||||
{
|
||||
struct aic3262_priv *ps = p;
|
||||
|
||||
aic326x_reg_union mreg;
|
||||
cfw_register *c = (cfw_register *) ®
|
||||
mreg.aic326x_register.offset = c->offset;
|
||||
mreg.aic326x_register.page = c->page;
|
||||
mreg.aic326x_register.book = c->book;
|
||||
mreg.aic326x_register.reserved = 0;
|
||||
DBG("set_bits:page %d book %d offset %d mask %#x val %#x\n",mreg.aic326x_register.page,mreg.aic326x_register.book,mreg.aic326x_register.offset,mask,val);
|
||||
|
||||
return aic3262_set_bits(ps->codec->control_data,mreg.aic326x_register_int,mask,val);
|
||||
|
||||
}
|
||||
int aic3262_ops_bulk_read(void *p,unsigned int reg,int count, u8 *buf)
|
||||
{
|
||||
struct aic3262_priv *ps = p;
|
||||
|
||||
aic326x_reg_union mreg;
|
||||
cfw_register *c = (cfw_register *) ®
|
||||
mreg.aic326x_register.offset = c->offset;
|
||||
mreg.aic326x_register.page = c->page;
|
||||
mreg.aic326x_register.book = c->book;
|
||||
mreg.aic326x_register.reserved = 0;
|
||||
|
||||
return aic3262_bulk_read(ps->codec->control_data,mreg.aic326x_register_int,count,buf);
|
||||
}
|
||||
|
||||
int aic3262_ops_bulk_write(void *p,unsigned int reg ,int count, const u8 *buf)
|
||||
{
|
||||
struct aic3262_priv *ps = p;
|
||||
aic326x_reg_union mreg;
|
||||
cfw_register *c = (cfw_register *) ®
|
||||
|
||||
mreg.aic326x_register.offset = c->offset;
|
||||
mreg.aic326x_register.page = c->page;
|
||||
mreg.aic326x_register.book = c->book;
|
||||
mreg.aic326x_register.reserved = 0;
|
||||
DBG("bulk_write: ncmd %d page %d book %d offset %d data[0] %d\n",count,mreg.aic326x_register.page,mreg.aic326x_register.book,mreg.aic326x_register.offset,buf[0]);
|
||||
|
||||
aic3262_bulk_write(ps->codec->control_data,mreg.aic326x_register_int,count,buf);
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************
|
||||
Function Name : aic3262_ops_dlock_lock
|
||||
Argument : pointer argument to the codec
|
||||
Return value : Integer
|
||||
Purpose : To Read the run state of the DAC and ADC
|
||||
by reading the codec and returning the run state
|
||||
|
||||
Run state Bit format
|
||||
|
||||
------------------------------------------------------
|
||||
D31|..........| D7 | D6| D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
R R R LADC RADC R R LDAC RDAC
|
||||
------------------------------------------------------
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
int aic3262_ops_lock(void *pv)
|
||||
{
|
||||
int run_state=0;
|
||||
struct aic3262_priv *aic3262 = (struct aic3262_priv *) pv;
|
||||
mutex_lock(&aic3262->codec->mutex);
|
||||
|
||||
/* Reading the run state of adc and dac */
|
||||
run_state = get_runstate(aic3262->codec->control_data);
|
||||
|
||||
return run_state;
|
||||
}
|
||||
/********************************************************************************
|
||||
Function name : aic3262_ops_dlock_unlock
|
||||
Argument : pointer argument to the codec
|
||||
Return Value : integer returning 0
|
||||
Purpose : To unlock the mutex acqiured for reading
|
||||
run state of the codec
|
||||
*********************************************************************************/
|
||||
int aic3262_ops_unlock(void *pv)
|
||||
{
|
||||
/*Releasing the lock of mutex */
|
||||
struct aic3262_priv *aic3262 = (struct aic3262_priv *) pv;
|
||||
|
||||
mutex_unlock(&aic3262->codec->mutex);
|
||||
return 0;
|
||||
}
|
||||
/*********************************************************************************
|
||||
Function Name : aic3262_ops_dlock_stop
|
||||
Argument : pointer Argument to the codec
|
||||
mask tells us the bit format of the
|
||||
codec running state
|
||||
|
||||
Bit Format:
|
||||
------------------------------------------------------
|
||||
D31|..........| D7 | D6| D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
R R R AL AR R R DL DR
|
||||
------------------------------------------------------
|
||||
R - Reserved
|
||||
A - minidsp_A
|
||||
D - minidsp_D
|
||||
***********************************************************************************/
|
||||
|
||||
|
||||
|
||||
int aic3262_ops_stop (void *pv, int mask)
|
||||
{
|
||||
int run_state=0;
|
||||
int cur_state=0;
|
||||
int count = 100;
|
||||
struct aic3262_priv *aic3262 = (struct aic3262_priv *) pv;
|
||||
int limask=0;
|
||||
|
||||
mutex_lock(&aic3262->codec->mutex);
|
||||
run_state = get_runstate(aic3262->codec->control_data);
|
||||
|
||||
if ( ( limask=(mask & AIC3XX_COPS_MDSP_A) ) )
|
||||
{
|
||||
if((limask & 0x30) == 0x30) //Both ADC's needs to switchoff
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_ADC_DATAPATH_SETUP,0xC0,0);
|
||||
else
|
||||
{
|
||||
if(limask & 0x10) //Right ADC is on, we need to switchoff
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_ADC_DATAPATH_SETUP,0x40,0);
|
||||
|
||||
if(limask & 0x20) // Left ADC is on , we need to switchoff
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_ADC_DATAPATH_SETUP,0x80,0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( ( limask= (mask & AIC3XX_COPS_MDSP_D) ) )
|
||||
{
|
||||
if( (limask & 0x03)== 0x03 )
|
||||
{
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_DAC_DATAPATH_SETUP,0xC0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(limask & 0x01)
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_DAC_DATAPATH_SETUP,0x40,0);
|
||||
|
||||
if(limask & 0x02)
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_DAC_DATAPATH_SETUP,0x80,0);
|
||||
}
|
||||
}
|
||||
// waiting for write to complete
|
||||
|
||||
do
|
||||
{
|
||||
cur_state = get_runstate(aic3262->codec->control_data);
|
||||
count--;
|
||||
}while( ( (cur_state&mask&AIC3XX_COPS_MDSP_A) || (cur_state&mask&AIC3XX_COPS_MDSP_D) ) && count );
|
||||
|
||||
return run_state;
|
||||
|
||||
}
|
||||
/*****************************************************************************
|
||||
Function name : aic3262_ops_dlock_restore
|
||||
Argument : pointer argument to the codec,run_state
|
||||
Return Value : integer returning 0
|
||||
Purpose : To unlock the mutex acqiured for reading
|
||||
run state of the codec and to restore the states of the dsp
|
||||
*******************************************************************************/
|
||||
int aic3262_ops_restore(void *pv, int run_state)
|
||||
{
|
||||
int sync_state = 0;
|
||||
int li_cur_state = 0;
|
||||
struct aic3262_priv *aic3262 = (struct aic3262_priv *)pv;
|
||||
/* This is for read the sync mode register state */
|
||||
sync_state = SYNC_STATE(aic3262);
|
||||
/* Reading the current dsp state */
|
||||
li_cur_state = get_runstate(aic3262->codec->control_data);
|
||||
|
||||
|
||||
//checking whether the sync mode has been set or not and checking the current state
|
||||
if( ((run_state & 0x30) && (run_state & 0x03)) && (sync_state & 0x80) )
|
||||
aic3262_restart_dsps_sync(pv,run_state);
|
||||
else
|
||||
aic3262_dsp_pwrup(pv,run_state);
|
||||
|
||||
|
||||
mutex_unlock(&aic3262->codec->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Function name : aic3262_ops_adaptivebuffer_swap
|
||||
Argument : pointer argument to the codec,mask tells us which dsp has to
|
||||
be chosen for swapping
|
||||
Return Value : integer returning 0
|
||||
Purpose : To swap the coefficient buffers of minidsp according to mask
|
||||
*******************************************************************************/
|
||||
|
||||
int aic3262_ops_adaptivebuffer_swap(void *pv,int mask)
|
||||
{
|
||||
int read_state=0;
|
||||
struct aic3262_priv *aic3262 = (struct aic3262_priv *) pv;
|
||||
|
||||
if(mask & AIC3XX_ABUF_MDSP_A)
|
||||
{
|
||||
|
||||
int count=0;
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_ADC_ADAPTIVE_CRAM_REG,0x1,0x1);
|
||||
|
||||
do
|
||||
{
|
||||
read_state = aic3262_reg_read(aic3262->codec->control_data,AIC3262_ADC_ADAPTIVE_CRAM_REG);
|
||||
count++;
|
||||
}while( (read_state & 0x1) && (count <= 60) );
|
||||
}
|
||||
|
||||
if(mask & AIC3XX_ABUF_MDSP_D1)
|
||||
{
|
||||
|
||||
int count=0;
|
||||
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_DAC_ADAPTIVE_BANK1_REG,0x1,0x1);
|
||||
do
|
||||
{
|
||||
read_state = aic3262_reg_read(aic3262->codec->control_data, AIC3262_DAC_ADAPTIVE_BANK1_REG );
|
||||
count++;
|
||||
}while( (read_state & 0x1) && (count <= 60) );
|
||||
}
|
||||
|
||||
if(mask & AIC3XX_ABUF_MDSP_D2)
|
||||
{
|
||||
|
||||
int count=0;
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_DAC_ADAPTIVE_BANK2_REG,0x1,0x1);
|
||||
do
|
||||
{
|
||||
read_state = aic3262_reg_read(aic3262->codec->control_data,AIC3262_DAC_ADAPTIVE_BANK2_REG);
|
||||
count++;
|
||||
}while( (read_state & 0x1) && (count <= 60) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************
|
||||
Function name : get_runstate
|
||||
Argument : pointer argument to the codec
|
||||
Return Value : integer returning the runstate
|
||||
Purpose : To read the current state of the dac's and adc's
|
||||
*******************************************************************************/
|
||||
|
||||
int get_runstate(void *ps)
|
||||
{
|
||||
struct aic3262 *pr = ps;
|
||||
int run_state=0;
|
||||
int DAC_state=0,ADC_state=0;
|
||||
/* Read the run state */
|
||||
DAC_state = aic3262_reg_read(pr,AIC3262_DAC_FLAG);
|
||||
ADC_state = aic3262_reg_read(pr,AIC3262_ADC_FLAG);
|
||||
|
||||
DSP_STATUS(run_state,ADC_state,6,5);
|
||||
DSP_STATUS(run_state,ADC_state,2,4);
|
||||
DSP_STATUS(run_state,DAC_state,7,1);
|
||||
DSP_STATUS(run_state,DAC_state,3,0);
|
||||
|
||||
return run_state;
|
||||
|
||||
}
|
||||
/*****************************************************************************
|
||||
Function name : aic3262_dsp_pwrdwn_status
|
||||
Argument : pointer argument to the codec , cur_state of dac's and adc's
|
||||
Return Value : integer returning 0
|
||||
Purpose : To read the status of dsp's
|
||||
*******************************************************************************/
|
||||
|
||||
int aic3262_dsp_pwrdwn_status(
|
||||
void *pv //ptr to the priv data structure
|
||||
)
|
||||
{
|
||||
struct aic3262_priv *aic3262 = pv;
|
||||
int count = 100;
|
||||
int cur_state = 0;
|
||||
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_ADC_DATAPATH_SETUP,0XC0,0);
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_DAC_DATAPATH_SETUP,0XC0,0);
|
||||
|
||||
do
|
||||
{
|
||||
cur_state = get_runstate(aic3262->codec->control_data);
|
||||
}while(cur_state && count--);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
int aic3262_dsp_pwrup(void *pv,int state)
|
||||
{
|
||||
int cur_state = 0;
|
||||
int count =100;
|
||||
struct aic3262_priv *aic3262 = (struct aic3262_priv *)pv;
|
||||
|
||||
if(state & AIC3262_COPS_MDSP_A)
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_ADC_DATAPATH_SETUP,0XC0,0xC0);
|
||||
else
|
||||
{
|
||||
if(state & AIC3262_COPS_MDSP_A_L)
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_ADC_DATAPATH_SETUP,0x80,0x80);
|
||||
if(state & AIC3262_COPS_MDSP_A_R)
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_ADC_DATAPATH_SETUP,0x40,0x40);
|
||||
}
|
||||
|
||||
|
||||
if(state & AIC3262_COPS_MDSP_D)
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_DAC_DATAPATH_SETUP,0XC0,0xC0);
|
||||
else
|
||||
{
|
||||
if(state & AIC3262_COPS_MDSP_D_L)
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_DAC_DATAPATH_SETUP,0x80,0x80);
|
||||
if(state & AIC3262_COPS_MDSP_D_R)
|
||||
aic3262_set_bits(aic3262->codec->control_data,AIC3262_DAC_DATAPATH_SETUP,0x40,0x40);
|
||||
}
|
||||
|
||||
//loop for waiting for the dsps to power up together
|
||||
do
|
||||
{
|
||||
cur_state = get_runstate(aic3262->codec->control_data);
|
||||
}while ((state == cur_state ) && count--);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aic3262_restart_dsps_sync(void *pv,int run_state)
|
||||
{
|
||||
|
||||
aic3262_dsp_pwrdwn_status(pv);
|
||||
//specific command sequence to be added later
|
||||
/*
|
||||
....................
|
||||
....................
|
||||
....................
|
||||
*/
|
||||
|
||||
aic3262_dsp_pwrup(pv,run_state);
|
||||
|
||||
//specific commands to be added later
|
||||
/*
|
||||
....................
|
||||
....................
|
||||
....................
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
const aic3xxx_codec_ops aic3262_cfw_codec_ops = {
|
||||
.reg_read = aic3262_ops_reg_read,
|
||||
.reg_write = aic3262_ops_reg_write,
|
||||
.set_bits = aic3262_ops_set_bits,
|
||||
.bulk_read = aic3262_ops_bulk_read,
|
||||
.bulk_write = aic3262_ops_bulk_write,
|
||||
.lock = aic3262_ops_lock,
|
||||
.unlock = aic3262_ops_unlock,
|
||||
.stop = aic3262_ops_stop ,
|
||||
.restore = aic3262_ops_restore,
|
||||
.bswap = aic3262_ops_adaptivebuffer_swap,
|
||||
};
|
||||
|
||||
|
||||
42
sound/soc/codecs/aic3262_codec_ops.h
Normal file
42
sound/soc/codecs/aic3262_codec_ops.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#define SYNC_STATE(p) aic3262_reg_read(p->codec->control_data,AIC3262_DAC_PRB)
|
||||
|
||||
#define AIC3262_COPS_MDSP_A 0x30
|
||||
#define AIC3262_COPS_MDSP_A_L 0x20
|
||||
#define AIC3262_COPS_MDSP_A_R 0x10
|
||||
|
||||
|
||||
|
||||
#define AIC3262_COPS_MDSP_D 0x03
|
||||
#define AIC3262_COPS_MDSP_D_L 0x02
|
||||
#define AIC3262_COPS_MDSP_D_R 0x01
|
||||
|
||||
|
||||
int get_runstate(void *);
|
||||
|
||||
int aic3262_dsp_pwrup(void *,int);
|
||||
|
||||
int aic3262_pwr_down(void *,int ,int ,int ,int);
|
||||
|
||||
int aic3262_dsp_pwrdwn_status(void *);
|
||||
|
||||
int aic3262_ops_reg_read(void *p,unsigned int reg);
|
||||
|
||||
int aic3262_ops_reg_write(void *p,unsigned int reg,unsigned char mval);
|
||||
|
||||
int aic3262_ops_set_bits(void *p,unsigned int reg,unsigned char mask, unsigned char val);
|
||||
|
||||
int aic3262_ops_bulk_read(void *p,unsigned int reg,int count, u8 *buf);
|
||||
|
||||
int aic3262_ops_bulk_write(void *p, unsigned int reg,int count, const u8 *buf);
|
||||
|
||||
int aic3262_ops_lock(void *pv);
|
||||
|
||||
int aic3262_ops_unlock(void *pv);
|
||||
|
||||
int aic3262_ops_stop (void *pv, int mask);
|
||||
|
||||
int aic3262_ops_restore(void *pv, int run_state);
|
||||
|
||||
int aic3262_ops_adaptivebuffer_swap(void *pv,int mask);
|
||||
|
||||
int aic3262_restart_dsps_sync(void *pv,int run_state);
|
||||
349
sound/soc/codecs/aic326x_tiload.c
Normal file
349
sound/soc/codecs/aic326x_tiload.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* linux/sound/soc/codecs/AIC3262_tiload.c
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2010 Texas Instruments, Inc.
|
||||
*
|
||||
*
|
||||
*
|
||||
* This package 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.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* Rev 0.1 Tiload support TI 16-09-2010
|
||||
*
|
||||
* The Tiload programming support is added to AIC3262.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/control.h>
|
||||
#include <linux/switch.h>
|
||||
#include <sound/jack.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/mfd/tlv320aic3262-core.h>
|
||||
#include "tlv320aic326x.h"
|
||||
#include "aic326x_tiload.h"
|
||||
|
||||
/* enable debug prints in the driver */
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintk(x...) printk(x)
|
||||
#else
|
||||
#define dprintk(x...)
|
||||
#endif
|
||||
|
||||
#ifdef AIC3262_TiLoad
|
||||
|
||||
/* Function prototypes */
|
||||
#ifdef REG_DUMP_aic3262
|
||||
static void aic3262_dump_page(struct i2c_client *i2c, u8 page);
|
||||
#endif
|
||||
|
||||
/* externs */
|
||||
/*extern int aic3262_change_page(struct snd_soc_codec *codec, u8 new_page);
|
||||
extern int aic3262_change_book(struct snd_soc_codec *codec, u8 new_book);*/
|
||||
extern int aic3262_write(struct snd_soc_codec *codec, unsigned int reg,
|
||||
unsigned int value);
|
||||
|
||||
int aic3262_driver_init(struct snd_soc_codec *codec);
|
||||
/************** Dynamic aic3262 driver, TI LOAD support ***************/
|
||||
|
||||
static struct cdev *aic3262_cdev;
|
||||
static aic326x_reg_union aic_reg;
|
||||
static int aic3262_major = 0; /* Dynamic allocation of Mjr No. */
|
||||
static int aic3262_opened = 0; /* Dynamic allocation of Mjr No. */
|
||||
static struct snd_soc_codec *aic3262_codec;
|
||||
struct class *tiload_class;
|
||||
static unsigned int magic_num = 0xE0;
|
||||
|
||||
/******************************** Debug section *****************************/
|
||||
|
||||
#ifdef REG_DUMP_aic3262
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Function : aic3262_dump_page
|
||||
* Purpose : Read and display one codec register page, for debugging purpose
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
static void aic3262_dump_page(struct i2c_client *i2c, u8 page)
|
||||
{
|
||||
int i;
|
||||
u8 data;
|
||||
u8 test_page_array[8];
|
||||
|
||||
dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
|
||||
// aic3262_change_page(codec, page);
|
||||
|
||||
data = 0x0;
|
||||
|
||||
i2c_master_send(i2c, data, 1);
|
||||
i2c_master_recv(i2c, test_page_array, 8);
|
||||
|
||||
dprintk("\n------- aic3262 PAGE %d DUMP --------\n", page);
|
||||
for (i = 0; i < 8; i++) {
|
||||
printk(" [ %d ] = 0x%x\n", i, test_page_array[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Function : tiload_open
|
||||
*
|
||||
* Purpose : open method for aic3262-tiload programming interface
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
static int tiload_open(struct inode *in, struct file *filp)
|
||||
{
|
||||
dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
|
||||
if (aic3262_opened) {
|
||||
dprintk("%s device is already opened\n", "aic3262");
|
||||
dprintk("%s: only one instance of driver is allowed\n",
|
||||
"aic3262");
|
||||
return -1;
|
||||
}
|
||||
aic3262_opened++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Function : tiload_release
|
||||
*
|
||||
* Purpose : close method for aic3262_tilaod programming interface
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
static int tiload_release(struct inode *in, struct file *filp)
|
||||
{
|
||||
dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
|
||||
aic3262_opened--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Function : tiload_read
|
||||
*
|
||||
* Purpose : read method for mini dsp programming interface
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
static ssize_t tiload_read(struct file *file, char __user * buf,
|
||||
size_t count, loff_t * offset)
|
||||
{
|
||||
static char rd_data[8];
|
||||
char reg_addr;
|
||||
size_t size;
|
||||
#ifdef DEBUG
|
||||
int i;
|
||||
#endif
|
||||
struct aic3262 *control = aic3262_codec->control_data;
|
||||
|
||||
dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
|
||||
if (count > 128) {
|
||||
printk("Max 128 bytes can be read\n");
|
||||
count = 128;
|
||||
}
|
||||
|
||||
/* copy register address from user space */
|
||||
size = copy_from_user(®_addr, buf, 1);
|
||||
if (size != 0) {
|
||||
printk("read: copy_from_user failure\n");
|
||||
return -1;
|
||||
}
|
||||
/* Send the address to device thats is to be read */
|
||||
|
||||
aic_reg.aic326x_register.offset = reg_addr;
|
||||
size = aic3262_bulk_read(control, aic_reg.aic326x_register_int, count, rd_data);
|
||||
/*
|
||||
if (i2c_master_send(i2c, ®_addr, 1) != 1) {
|
||||
dprintk("Can not write register address\n");
|
||||
return -1;
|
||||
}
|
||||
size = i2c_master_recv(i2c, rd_data, count);
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printk(KERN_ERR "read size = %d, reg_addr= %x , count = %d\n",
|
||||
(int)size, reg_addr, (int)count);
|
||||
for (i = 0; i < (int)size; i++) {
|
||||
dprintk(KERN_ERR "rd_data[%d]=%x\n", i, rd_data[i]);
|
||||
}
|
||||
#endif
|
||||
if (size != count) {
|
||||
dprintk("read %d registers from the codec\n", size);
|
||||
}
|
||||
|
||||
if (copy_to_user(buf, rd_data, size) != 0) {
|
||||
dprintk("copy_to_user failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Function : tiload_write
|
||||
*
|
||||
* Purpose : write method for aic3262_tiload programming interface
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
static ssize_t tiload_write(struct file *file, const char __user * buf,
|
||||
size_t count, loff_t * offset)
|
||||
{
|
||||
static char wr_data[8];
|
||||
u8 pg_no;
|
||||
unsigned int reg;
|
||||
#ifdef DEBUG
|
||||
int i;
|
||||
#endif
|
||||
struct aic3262 *control = aic3262_codec->control_data;
|
||||
|
||||
dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
|
||||
/* copy buffer from user space */
|
||||
if (copy_from_user(wr_data, buf, count)) {
|
||||
printk("copy_from_user failure\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
dprintk(KERN_ERR "write size = %d\n", (int)count);
|
||||
for (i = 0; i < (int)count; i++) {
|
||||
printk(KERN_INFO "\nwr_data[%d]=%x\n", i, wr_data[i]);
|
||||
}
|
||||
#endif
|
||||
if(wr_data[0] == 0)
|
||||
{
|
||||
//change of page seen, but will only be registered
|
||||
aic_reg.aic326x_register.page = wr_data[1];
|
||||
return count;// trick
|
||||
|
||||
}
|
||||
else
|
||||
if(wr_data[0] == 127 /* && aic_reg.aic326x_register.page == 0*/)
|
||||
{
|
||||
//change of book seen, but will not be sent for I2C write
|
||||
aic_reg.aic326x_register.book = wr_data[1];
|
||||
return count; //trick
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
aic_reg.aic326x_register.offset = wr_data[0];
|
||||
aic3262_bulk_write(control, aic_reg.aic326x_register_int, count - 1,&wr_data[1]);
|
||||
return count;
|
||||
}
|
||||
/* if (wr_data[0] == 0) {
|
||||
aic3262_change_page(aic3262_codec, wr_data[1]);
|
||||
return count;
|
||||
}
|
||||
pg_no = aic3262_private->page_no;
|
||||
|
||||
if ((wr_data[0] == 127) && (pg_no == 0)) {
|
||||
aic3262_change_book(aic3262_codec, wr_data[1]);
|
||||
return count;
|
||||
}
|
||||
return i2c_master_send(i2c, wr_data, count);*/
|
||||
|
||||
}
|
||||
|
||||
static int tiload_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int num = 0;
|
||||
void __user *argp = (void __user *)arg;
|
||||
if (_IOC_TYPE(cmd) != aic3262_IOC_MAGIC)
|
||||
return -ENOTTY;
|
||||
|
||||
dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
|
||||
switch (cmd) {
|
||||
case aic3262_IOMAGICNUM_GET:
|
||||
num = copy_to_user(argp, &magic_num, sizeof(int));
|
||||
break;
|
||||
case aic3262_IOMAGICNUM_SET:
|
||||
num = copy_from_user(&magic_num, argp, sizeof(int));
|
||||
break;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/*********** File operations structure for aic3262-tiload programming *************/
|
||||
static struct file_operations aic3262_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = tiload_open,
|
||||
.release = tiload_release,
|
||||
.read = tiload_read,
|
||||
.write = tiload_write,
|
||||
.unlocked_ioctl = tiload_ioctl,
|
||||
};
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Function : aic3262_driver_init
|
||||
*
|
||||
* Purpose : Register a char driver for dynamic aic3262-tiload programming
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
int aic3262_driver_init(struct snd_soc_codec *codec)
|
||||
{
|
||||
int result;
|
||||
|
||||
dev_t dev = MKDEV(aic3262_major, 0);
|
||||
dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
|
||||
aic3262_codec = codec;
|
||||
|
||||
dprintk("allocating dynamic major number\n");
|
||||
|
||||
result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
|
||||
if (result < 0) {
|
||||
dprintk("cannot allocate major number %d\n", aic3262_major);
|
||||
return result;
|
||||
}
|
||||
|
||||
tiload_class = class_create(THIS_MODULE, DEVICE_NAME);
|
||||
aic3262_major = MAJOR(dev);
|
||||
dprintk("allocated Major Number: %d\n", aic3262_major);
|
||||
|
||||
aic3262_cdev = cdev_alloc();
|
||||
cdev_init(aic3262_cdev, &aic3262_fops);
|
||||
aic3262_cdev->owner = THIS_MODULE;
|
||||
aic3262_cdev->ops = &aic3262_fops;
|
||||
|
||||
aic_reg.aic326x_register.page = 0;
|
||||
aic_reg.aic326x_register.book = 0;
|
||||
|
||||
if (cdev_add(aic3262_cdev, dev, 1) < 0) {
|
||||
dprintk("aic3262_driver: cdev_add failed \n");
|
||||
unregister_chrdev_region(dev, 1);
|
||||
aic3262_cdev = NULL;
|
||||
return 1;
|
||||
}
|
||||
dprintk("Registered aic3262 TiLoad driver, Major number: %d \n",
|
||||
aic3262_major);
|
||||
//class_device_create(tiload_class, NULL, dev, NULL, DEVICE_NAME, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
36
sound/soc/codecs/aic326x_tiload.h
Normal file
36
sound/soc/codecs/aic326x_tiload.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* linux/sound/soc/codecs/aic3262_tiload.h
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Inc.
|
||||
*
|
||||
*
|
||||
*
|
||||
* This package 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.
|
||||
*
|
||||
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* History:
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AIC3262_TILOAD_H
|
||||
#define _AIC3262_TILOAD_H
|
||||
|
||||
/* typedefs required for the included header files */
|
||||
typedef char *string;
|
||||
|
||||
/* defines */
|
||||
#define DEVICE_NAME "tiload_node"
|
||||
#define aic3262_IOC_MAGIC 0xE0
|
||||
#define aic3262_IOMAGICNUM_GET _IOR(aic3262_IOC_MAGIC, 1, int)
|
||||
#define aic3262_IOMAGICNUM_SET _IOW(aic3262_IOC_MAGIC, 2, int)
|
||||
|
||||
#endif
|
||||
425
sound/soc/codecs/aic3xxx_cfw.h
Normal file
425
sound/soc/codecs/aic3xxx_cfw.h
Normal file
@@ -0,0 +1,425 @@
|
||||
/**
|
||||
* \file Codec Firmware Declarations
|
||||
*/
|
||||
|
||||
#ifndef CFW_FIRMWARE_H_
|
||||
#define CFW_FIRMWARE_H_
|
||||
|
||||
/** \defgroup bt Basic Types */
|
||||
/* @{ */
|
||||
#ifndef AIC3XXX_CFW_HOST_BLD
|
||||
#include <asm-generic/int-ll64.h>
|
||||
#else
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short int u16;
|
||||
typedef unsigned long int u32;
|
||||
#endif
|
||||
typedef signed char i8;
|
||||
typedef signed short int i16;
|
||||
typedef signed long int i32;
|
||||
|
||||
#define CFW_FW_MAGIC 0xC0D1F1ED
|
||||
/* @} */
|
||||
|
||||
|
||||
/** \defgroup pd Arbitrary Limitations */
|
||||
/* @{ */
|
||||
#ifndef CFW_MAX_ID
|
||||
# define CFW_MAX_ID (64) ///<Max length of string identifies
|
||||
#endif
|
||||
#ifndef CFW_MAX_DESC
|
||||
# define CFW_MAX_DESC (512) ///<Max length of description
|
||||
#endif
|
||||
#ifndef CFW_MAX_NOVLY
|
||||
# define CFW_MAX_NOVLY (4) ///<Max number of overlays per PFW
|
||||
#endif
|
||||
|
||||
#ifndef CFW_MAX_NCFG
|
||||
# define CFW_MAX_NCFG (16) ///<Max number of configurations per PFW
|
||||
#endif
|
||||
|
||||
#ifndef CFW_MAX_TRANSITIONS
|
||||
# define CFW_MAX_TRANSITIONS (32) ///<max number of pre-defined transition
|
||||
#endif
|
||||
|
||||
#ifndef CFW_MAX_NPFW
|
||||
# define CFW_MAX_NPFW (16) ///<Max number fo process flows
|
||||
#endif
|
||||
|
||||
#ifndef CFW_MAX_MODES
|
||||
# define CFW_MAX_MODES (32) ///<Max number of modes
|
||||
#endif
|
||||
|
||||
#ifndef CFW_MAX_ASI
|
||||
# define CFW_MAX_ASI (4) ///<Max number ASIs in a single device
|
||||
#endif
|
||||
|
||||
/* @} */
|
||||
|
||||
|
||||
|
||||
/** \defgroup st Enums, Flags, Macros and Supporting Types */
|
||||
/* @{ */
|
||||
|
||||
/**
|
||||
* Sample rate bitmask
|
||||
*
|
||||
*/
|
||||
enum cfw_fs {
|
||||
CFW_FS_8KHZ = 0x0001u,
|
||||
CFW_FS_11KHZ = 0x0002u,
|
||||
CFW_FS_16KHZ = 0x0004u,
|
||||
CFW_FS_22KHZ = 0x0008u,
|
||||
CFW_FS_24KHZ = 0x0010u,
|
||||
CFW_FS_32KHZ = 0x0020u,
|
||||
CFW_FS_44KHZ = 0x0040u,
|
||||
CFW_FS_48KHZ = 0x0080u,
|
||||
CFW_FS_88KHZ = 0x0100u,
|
||||
CFW_FS_96KHZ = 0x0200u,
|
||||
CFW_FS_176KHZ = 0x0400u,
|
||||
CFW_FS_192KHZ = 0x0800u,
|
||||
CFW_FS_ANY = 0x8000u,
|
||||
CFW_FS_ALL = 0x0FFFu,
|
||||
};
|
||||
|
||||
/**
|
||||
* Sample rate index
|
||||
*
|
||||
*/
|
||||
enum cfw_fsi {
|
||||
CFW_FSI_8KHZ,
|
||||
CFW_FSI_11KHZ,
|
||||
CFW_FSI_16KHZ,
|
||||
CFW_FSI_22KHZ,
|
||||
CFW_FSI_24KHZ,
|
||||
CFW_FSI_32KHZ,
|
||||
CFW_FSI_44KHZ,
|
||||
CFW_FSI_48KHZ,
|
||||
CFW_FSI_88KHZ,
|
||||
CFW_FSI_96KHZ,
|
||||
CFW_FSI_176KHZ,
|
||||
CFW_FSI_192KHZ,
|
||||
CFW_FSI_ANY = 15,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Device Family Identifier
|
||||
*
|
||||
*/
|
||||
typedef enum __attribute__ ((__packed__)) cfw_dfamily {
|
||||
CFW_DFM_TYPE_A,
|
||||
CFW_DFM_TYPE_B,
|
||||
CFW_DFM_TYPE_C
|
||||
} cfw_dfamily;
|
||||
|
||||
/**
|
||||
* Device Identifier
|
||||
*
|
||||
*/
|
||||
typedef enum __attribute__ ((__packed__)) cfw_device {
|
||||
CFW_DEV_DAC3120,
|
||||
CFW_DEV_DAC3100,
|
||||
|
||||
CFW_DEV_AIC3120,
|
||||
CFW_DEV_AIC3100,
|
||||
CFW_DEV_AIC3110,
|
||||
CFW_DEV_AIC3111,
|
||||
|
||||
CFW_DEV_AIC36,
|
||||
|
||||
CFW_DEV_AIC3206,
|
||||
CFW_DEV_AIC3204,
|
||||
CFW_DEV_AIC3254,
|
||||
CFW_DEV_AIC3256,
|
||||
CFW_DEV_AIC3253,
|
||||
|
||||
CFW_DEV_AIC3212,
|
||||
CFW_DEV_AIC3262,
|
||||
CFW_DEV_AIC3017,
|
||||
CFW_DEV_AIC3008,
|
||||
|
||||
} cfw_device;
|
||||
|
||||
/**
|
||||
* Transition Sequence Identifier
|
||||
*
|
||||
*/
|
||||
typedef enum cfw_transition_t {
|
||||
CFW_TRN_INIT,
|
||||
CFW_TRN_RESUME,
|
||||
CFW_TRN_NEUTRAL,
|
||||
CFW_TRN_SUSPEND,
|
||||
CFW_TRN_EXIT,
|
||||
CFW_TRN_N
|
||||
} cfw_transition_t;
|
||||
static const char * const cfw_transition_id[] = {
|
||||
[CFW_TRN_INIT] "INIT",
|
||||
[CFW_TRN_RESUME] "RESUME",
|
||||
[CFW_TRN_NEUTRAL] "NEUTRAL",
|
||||
[CFW_TRN_SUSPEND] "SUSPEND",
|
||||
[CFW_TRN_EXIT] "EXIT",
|
||||
};
|
||||
|
||||
/* @} */
|
||||
|
||||
/** \defgroup ds Data Structures */
|
||||
/* @{ */
|
||||
|
||||
|
||||
/**
|
||||
* CFW Meta Command
|
||||
* These commands do not appear in the register
|
||||
* set of the device.
|
||||
* Mainly delay, wait and set_bits.
|
||||
*/
|
||||
typedef enum __attribute__ ((__packed__)) cfw_meta_cmd {
|
||||
CFW_META_DELAY = 0x80,
|
||||
CFW_META_UPDTBITS,
|
||||
CFW_META_WAITBITS,
|
||||
CFW_META_LOCK,
|
||||
} cfw_meta_cmd;
|
||||
|
||||
/**
|
||||
* CFW Delay
|
||||
* Used for the meta command delay
|
||||
* Has one parameter of delay time in ms
|
||||
*/
|
||||
typedef struct cfw_meta_delay {
|
||||
u16 delay;
|
||||
cfw_meta_cmd mcmd;
|
||||
u8 unused1;
|
||||
} cfw_meta_delay;
|
||||
|
||||
/**
|
||||
* CFW set_bits or wait
|
||||
* Both these meta commands have same arguments
|
||||
* mcmd will be used to specify which command it is
|
||||
* has parameters of book, page, offset and mask
|
||||
*/
|
||||
typedef struct cfw_meta_bitop {
|
||||
u16 unused1;
|
||||
cfw_meta_cmd mcmd;
|
||||
u8 mask;
|
||||
} cfw_meta_bitop;
|
||||
|
||||
/**
|
||||
* CFW meta register
|
||||
* Contains the data structures for the meta commands
|
||||
*/
|
||||
typedef union cfw_meta_register {
|
||||
struct {
|
||||
u16 unused1;
|
||||
cfw_meta_cmd mcmd;
|
||||
u8 unused2;
|
||||
};
|
||||
cfw_meta_delay delay;
|
||||
cfw_meta_bitop bitop;
|
||||
} cfw_meta_register;
|
||||
|
||||
|
||||
/**
|
||||
* CFW Register
|
||||
*
|
||||
* A single reg write
|
||||
*
|
||||
*/
|
||||
typedef union cfw_register {
|
||||
struct {
|
||||
u8 book;
|
||||
u8 page;
|
||||
u8 offset;
|
||||
u8 data;
|
||||
};
|
||||
u32 bpod;
|
||||
cfw_meta_register meta;
|
||||
} cfw_register;
|
||||
|
||||
/**
|
||||
* CFW Burst
|
||||
*
|
||||
* A single I2C/SPI burst write sequence
|
||||
*
|
||||
*/
|
||||
typedef struct cfw_burst {
|
||||
u32 length;
|
||||
union {
|
||||
cfw_register reg;
|
||||
struct {
|
||||
u8 bpo[3];
|
||||
u8 data[1];
|
||||
};
|
||||
};
|
||||
} cfw_burst;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CFW Command
|
||||
*
|
||||
* Can be a either a
|
||||
* -# single register write,
|
||||
* -# a burst write, or
|
||||
* -# meta-command
|
||||
*
|
||||
*/
|
||||
typedef union cfw_cmd {
|
||||
cfw_register reg;
|
||||
cfw_burst *burst;
|
||||
} cfw_cmd;
|
||||
|
||||
|
||||
/**
|
||||
* CFW Block Type
|
||||
*
|
||||
* Block identifier
|
||||
*
|
||||
*/
|
||||
typedef enum __attribute__ ((__packed__)) cfw_block_t {
|
||||
CFW_BLOCK_SYSTEM_PRE,
|
||||
CFW_BLOCK_A_INST,
|
||||
CFW_BLOCK_A_A_COEF,
|
||||
CFW_BLOCK_A_B_COEF,
|
||||
CFW_BLOCK_A_F_COEF,
|
||||
CFW_BLOCK_D_INST,
|
||||
CFW_BLOCK_D_A1_COEF,
|
||||
CFW_BLOCK_D_B1_COEF,
|
||||
CFW_BLOCK_D_A2_COEF,
|
||||
CFW_BLOCK_D_B2_COEF,
|
||||
CFW_BLOCK_D_F_COEF,
|
||||
CFW_BLOCK_SYSTEM_POST,
|
||||
CFW_BLOCK_N,
|
||||
CFW_BLOCK_BURSTS = 0x80
|
||||
} cfw_block_t;
|
||||
#define CFW_BLOCK_BURSTS(x) ((x)&CFW_BLOCK_BURSTS)
|
||||
#define CFW_BLOCK_D_A_COEF CFW_BLOCK_D_A1_COEF
|
||||
#define CFW_BLOCK_D_B_COEF CFW_BLOCK_D_B1_COEF
|
||||
|
||||
/**
|
||||
* CFW Block
|
||||
*
|
||||
* A block of logically grouped sequences/commands/meta-commands
|
||||
*
|
||||
*/
|
||||
typedef struct cfw_block {
|
||||
cfw_block_t type;
|
||||
int ncmds;
|
||||
cfw_cmd cmd[1];
|
||||
} cfw_block;
|
||||
|
||||
|
||||
/**
|
||||
* CFW Image
|
||||
*
|
||||
* A downloadable image
|
||||
*/
|
||||
typedef struct cfw_image {
|
||||
char name[CFW_MAX_ID]; ///< Name of the pfw/overlay/configuration
|
||||
char desc[CFW_MAX_DESC]; ///< User string
|
||||
cfw_block *block[CFW_BLOCK_N];
|
||||
} cfw_image;
|
||||
|
||||
|
||||
/**
|
||||
* Sysclk source
|
||||
*
|
||||
*/
|
||||
typedef enum __attribute__ ((__packed__)) cfw_sclk_source {
|
||||
CFW_SYSCLK_MCLK1,
|
||||
CFW_SYSCLK_MCLK2,
|
||||
CFW_SYSCLK_BCLK1,
|
||||
CFW_SYSCLK_GPIO1,
|
||||
CFW_SYSCLK_PLL_CLK,
|
||||
CFW_SYSCLK_BCLK2,
|
||||
CFW_SYSCLK_GPI1,
|
||||
CFW_SYSCLK_HF_REF_CLK,
|
||||
CFW_SYSCLK_HF_OSC_CLK,
|
||||
CFW_SYSCLK_GPIO2,
|
||||
CFW_SYSCLK_GPI2,
|
||||
} cfw_sclk_source;
|
||||
|
||||
|
||||
/**
|
||||
* Process flow
|
||||
*
|
||||
* Complete description of a process flow
|
||||
*/
|
||||
typedef struct cfw_pfw {
|
||||
char name[CFW_MAX_ID]; ///< Name of the process flow
|
||||
char desc[CFW_MAX_DESC]; ///< User string
|
||||
u32 version;
|
||||
u16 supported_fs; ///< Sampling rates at which this process flow may run (bit mask; see \ref cfw_fs)
|
||||
u8 prb_a;
|
||||
u8 prb_d;
|
||||
int novly; ///< Number of overlays (1 or more)
|
||||
int ncfg; ///< Number of configurations (0 or more)
|
||||
cfw_block *pll;
|
||||
cfw_image *base; ///< Base sequence
|
||||
cfw_image *ovly_cfg[CFW_MAX_NOVLY][CFW_MAX_NCFG]; ///< Overlay and cfg
|
||||
///< patches (if any)
|
||||
} cfw_pfw;
|
||||
|
||||
|
||||
/**
|
||||
* Process transition
|
||||
*
|
||||
* Sequence for specific state transisitions within the driver
|
||||
*
|
||||
*/
|
||||
typedef struct cfw_transition {
|
||||
u32 id;
|
||||
char name[CFW_MAX_ID]; ///< Name of the transition
|
||||
char desc[CFW_MAX_DESC]; ///< User string
|
||||
cfw_block *block;
|
||||
} cfw_transition;
|
||||
|
||||
/**
|
||||
* Device audio mode
|
||||
*
|
||||
* Structure linking various operating modes to process flows,
|
||||
* configurations and sequences
|
||||
*
|
||||
*/
|
||||
typedef struct cfw_mode {
|
||||
u32 id;
|
||||
char name[CFW_MAX_ID];
|
||||
char desc[CFW_MAX_DESC]; ///< User string
|
||||
u32 flags;
|
||||
u8 pfw;
|
||||
u8 ovly;
|
||||
u8 cfg;
|
||||
u32 supported_cfgs;
|
||||
cfw_block *entry;
|
||||
cfw_block *exit;
|
||||
} cfw_mode;
|
||||
|
||||
/**
|
||||
* CFW Project
|
||||
*
|
||||
* Top level structure describing the CFW project
|
||||
*/
|
||||
typedef struct cfw_project {
|
||||
u32 magic;
|
||||
u32 bmagic;
|
||||
u32 size;
|
||||
u32 cksum;
|
||||
u32 version;
|
||||
u32 tstamp;
|
||||
char name[CFW_MAX_ID]; ///< Project name
|
||||
char desc[CFW_MAX_DESC]; ///< User string
|
||||
cfw_dfamily dfamily;
|
||||
cfw_device device;
|
||||
u32 flags;
|
||||
cfw_sclk_source clksrc; ///< Clock source
|
||||
u32 clkfreq; ///< Clock frequency
|
||||
cfw_transition *transition[CFW_MAX_TRANSITIONS];
|
||||
u16 npfw; ///< Number of process flows
|
||||
u16 nmode; ///< Number of operating modes
|
||||
cfw_pfw *pfw[CFW_MAX_NPFW]; ///< Indices to PFW locations
|
||||
cfw_mode *mode[CFW_MAX_MODES];
|
||||
} cfw_project;
|
||||
|
||||
|
||||
/* @} */
|
||||
|
||||
#endif /* CFW_FIRMWARE_H_ */
|
||||
447
sound/soc/codecs/aic3xxx_cfw_ops.c
Normal file
447
sound/soc/codecs/aic3xxx_cfw_ops.c
Normal file
@@ -0,0 +1,447 @@
|
||||
#ifndef AIC3XXX_CFW_HOST_BLD
|
||||
# include <linux/module.h>
|
||||
# include <linux/delay.h>
|
||||
# define warn(fmt, ...) printk(fmt "\n", ##__VA_ARGS__)
|
||||
# define error(fmt, ...) printk(fmt "\n", ##__VA_ARGS__)
|
||||
#else
|
||||
# define _GNU_SOURCE
|
||||
# include <stdlib.h>
|
||||
# include "utils.h"
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#include "aic3xxx_cfw.h"
|
||||
#include "aic3xxx_cfw_ops.h"
|
||||
|
||||
|
||||
/*
|
||||
* Firmware version numbers are used to make sure that the
|
||||
* host and target code stay in sync. It is _not_ recommended
|
||||
* to provide this number from the outside (E.g., from a makefile)
|
||||
* Instead, a set of automated tools are relied upon to keep the numbers
|
||||
* in sync at the time of host testing.
|
||||
*/
|
||||
#define CFW_FW_VERSION 0x000100AF
|
||||
|
||||
|
||||
static int aic3xxx_cfw_dlimage(void *pv, cfw_image *pim);
|
||||
static int aic3xxx_cfw_dlcfg(void *pv, cfw_image *pim);
|
||||
static void aic3xxx_cfw_dlcmds(void *pv, cfw_block *pb);
|
||||
cfw_meta_register *aic3xxx_read_meta(cfw_block *pb, int i);
|
||||
void aic3xxx_wait(void *p, unsigned int reg, u8 mask, u8 data);
|
||||
static cfw_project *aic3xxx_cfw_unpickle(void *p, int n);
|
||||
|
||||
#if defined(AIC3XXX_CFW_HOST_BLD)
|
||||
// Host test only...
|
||||
extern const aic3xxx_codec_ops dummy_codec_ops;
|
||||
extern void *dummy_codec_ops_obj;
|
||||
|
||||
void mdelay(int val)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<val*10; i++);
|
||||
}
|
||||
void *aic3xxx_cfw_init(void *pcfw, int n)
|
||||
{
|
||||
cfw_state *ps = malloc(sizeof(cfw_state));
|
||||
ps->ops = &dummy_codec_ops;
|
||||
ps->ops_obj = dummy_codec_ops_obj;
|
||||
aic3xxx_cfw_reload(ps, pcfw, n);
|
||||
return ps;
|
||||
}
|
||||
void *aic3xxx_cfw_getpjt(void *ps)
|
||||
{
|
||||
return ((cfw_state *)ps)->pjt;
|
||||
}
|
||||
// ...till here
|
||||
#endif
|
||||
|
||||
int aic3xxx_cfw_reload(void *pv, void *pcfw, int n)
|
||||
{
|
||||
cfw_state *ps = pv;
|
||||
ps->pjt = aic3xxx_cfw_unpickle(pcfw, n);
|
||||
ps->cur_mode =
|
||||
ps->cur_pfw =
|
||||
ps->cur_ovly =
|
||||
ps->cur_cfg = -1;
|
||||
return 0;
|
||||
}
|
||||
int aic3xxx_cfw_setmode(void *pv, int mode)
|
||||
{
|
||||
cfw_state *ps = pv;
|
||||
cfw_project *pjt = ps->pjt;
|
||||
return aic3xxx_cfw_setmode_cfg(pv, mode, pjt->mode[mode]->cfg);
|
||||
}
|
||||
int aic3xxx_cfw_setcfg(void *pv, int cfg)
|
||||
{
|
||||
cfw_state *ps = pv;
|
||||
cfw_project *pjt = ps->pjt;
|
||||
cfw_pfw *pfw;
|
||||
if (ps->cur_pfw >= pjt->npfw)
|
||||
return -1; // Non miniDSP
|
||||
if (!(pjt->mode[ps->cur_mode]->supported_cfgs&(1 << cfg)))
|
||||
return -1;
|
||||
if (ps->cur_cfg == cfg)
|
||||
return 0;
|
||||
pfw = pjt->pfw[ps->cur_pfw];
|
||||
ps->cur_cfg = cfg;
|
||||
return aic3xxx_cfw_dlcfg(pv, pfw->ovly_cfg[ps->cur_ovly][ps->cur_cfg]);
|
||||
}
|
||||
int aic3xxx_cfw_setmode_cfg(void *pv, int mode, int cfg)
|
||||
{
|
||||
cfw_state *ps = pv;
|
||||
cfw_project *pjt = ps->pjt;
|
||||
int which = 0;
|
||||
|
||||
if (mode >= pjt->nmode)
|
||||
return -1;
|
||||
if (pjt->mode[mode]->pfw < pjt->npfw) { // New mode uses miniDSP
|
||||
// FIXME: Add support for entry and exit sequences
|
||||
cfw_pfw *pfw = pjt->pfw[pjt->mode[mode]->pfw];
|
||||
// Make sure cfg is valid and supported in this mode
|
||||
if (cfg >= pfw->ncfg ||
|
||||
!(pjt->mode[mode]->supported_cfgs&(1u<<cfg)))
|
||||
return -1;
|
||||
/*
|
||||
* Decisions about which miniDSP to stop/restart are taken
|
||||
* on the basis of sections present in the _base_ image
|
||||
* This allows for correct sync mode operation even in cases
|
||||
* where the base PFW uses both miniDSPs where a particular
|
||||
* overlay applies only to one
|
||||
*/
|
||||
cfw_image *im = pfw->base;
|
||||
if (im->block[CFW_BLOCK_A_INST])
|
||||
which |= AIC3XX_COPS_MDSP_A;
|
||||
if (im->block[CFW_BLOCK_D_INST])
|
||||
which |= AIC3XX_COPS_MDSP_D;
|
||||
|
||||
if (pjt->mode[mode]->pfw != ps->cur_pfw) { // New mode requires different PFW
|
||||
ps->cur_pfw = pjt->mode[mode]->pfw;
|
||||
ps->cur_ovly = 0;
|
||||
ps->cur_cfg = 0;
|
||||
|
||||
which = ps->ops->stop(ps->ops_obj, which);
|
||||
aic3xxx_cfw_dlimage(pv, im);
|
||||
if (pjt->mode[mode]->ovly && pjt->mode[mode]->ovly < pfw->novly) {
|
||||
// New mode uses ovly
|
||||
aic3xxx_cfw_dlimage(pv, pfw->ovly_cfg[pjt->mode[mode]->ovly][cfg]);
|
||||
} else if (cfg) {
|
||||
// new mode needs only a cfg change
|
||||
aic3xxx_cfw_dlimage(pv, pfw->ovly_cfg[0][cfg]);
|
||||
}
|
||||
ps->ops->restore(ps->ops_obj, which);
|
||||
|
||||
} else if (pjt->mode[mode]->ovly != ps->cur_ovly) {
|
||||
// New mode requires only an ovly change
|
||||
which = ps->ops->stop(ps->ops_obj, which);
|
||||
aic3xxx_cfw_dlimage(pv, pfw->ovly_cfg[pjt->mode[mode]->ovly][cfg]);
|
||||
ps->ops->restore(ps->ops_obj, which);
|
||||
} else if (cfg != ps->cur_cfg) { // New mode requires only a cfg change
|
||||
aic3xxx_cfw_dlcfg(pv, pfw->ovly_cfg[pjt->mode[mode]->ovly][cfg]);
|
||||
}
|
||||
ps->cur_ovly = pjt->mode[mode]->ovly;
|
||||
ps->cur_cfg = cfg;
|
||||
|
||||
// FIXME: Update PLL settings if present
|
||||
// FIXME: This is hack and needs to go one way or another
|
||||
ps->cur_mode = mode;
|
||||
aic3xxx_cfw_set_pll(pv, 0);
|
||||
|
||||
} else if (pjt->mode[mode]->pfw == 0xFF) { // Bypass mode
|
||||
// FIXME
|
||||
} else { // Error
|
||||
warn("Bad pfw setting detected (%d). Max pfw=%d", pjt->mode[mode]->pfw,
|
||||
pjt->npfw);
|
||||
}
|
||||
ps->cur_mode = mode;
|
||||
warn("setmode_cfg: DONE (mode=%d pfw=%d ovly=%d cfg=%d)", ps->cur_mode, ps->cur_pfw, ps->cur_ovly, ps->cur_cfg);
|
||||
return 0;
|
||||
}
|
||||
int aic3xxx_cfw_transition(void *pv, char *ttype)
|
||||
{
|
||||
cfw_state *ps = pv;
|
||||
int i;
|
||||
for (i = 0; i < CFW_TRN_N; ++i) {
|
||||
if (!strcasecmp(ttype, cfw_transition_id[i])) {
|
||||
if (ps->pjt->transition[i]) {
|
||||
DBG("Sending transition %s[%d]", ttype, i);
|
||||
aic3xxx_cfw_dlcmds(pv, ps->pjt->transition[i]->block);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
warn("Transition %s not present or invalid", ttype);
|
||||
return 0;
|
||||
}
|
||||
int aic3xxx_cfw_set_pll(void *pv, int asi)
|
||||
{
|
||||
// FIXME: no error checks!!
|
||||
cfw_state *ps = pv;
|
||||
cfw_project *pjt = ps->pjt;
|
||||
cfw_pfw *pfw = pjt->pfw[pjt->mode[ps->cur_mode]->pfw];
|
||||
if (pfw->pll) {
|
||||
warn("Configuring PLL for ASI%d using PFW%d", asi,
|
||||
pjt->mode[ps->cur_mode]->pfw);
|
||||
aic3xxx_cfw_dlcmds(pv, pfw->pll);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static void aic3xxx_cfw_dlcmds(void *pv, cfw_block *pb)
|
||||
{
|
||||
cfw_state *ps = pv;
|
||||
int i = 0, lock = 0;
|
||||
|
||||
while (i < pb->ncmds) {
|
||||
if (CFW_BLOCK_BURSTS(pb->type))
|
||||
ps->ops->bulk_write(ps->ops_obj, pb->cmd[i].burst->reg.bpod,
|
||||
pb->cmd[i].burst->length,
|
||||
pb->cmd[i].burst->data);
|
||||
else {
|
||||
cfw_meta_delay d = pb->cmd[i].reg.meta.delay;
|
||||
cfw_meta_bitop b = pb->cmd[i].reg.meta.bitop;
|
||||
switch (pb->cmd[i].reg.meta.mcmd) {
|
||||
case CFW_META_DELAY:
|
||||
mdelay(d.delay);
|
||||
break;
|
||||
case CFW_META_UPDTBITS:
|
||||
ps->ops->set_bits(ps->ops_obj, pb->cmd[i+1].reg.bpod,
|
||||
b.mask, pb->cmd[i+1].reg.data);
|
||||
i++;
|
||||
break;
|
||||
case CFW_META_WAITBITS:
|
||||
aic3xxx_wait(ps, pb->cmd[i+1].reg.bpod,
|
||||
b.mask, pb->cmd[i+1].reg.data);
|
||||
i++;
|
||||
break;
|
||||
case CFW_META_LOCK:
|
||||
if (d.delay) {
|
||||
ps->ops->lock(ps->ops_obj);
|
||||
lock = 1;
|
||||
} else {
|
||||
if (!lock)
|
||||
error("Attempt to unlock without first locking");
|
||||
ps->ops->unlock(ps->ops_obj);
|
||||
lock = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ps->ops->reg_write(ps->ops_obj, pb->cmd[i].reg.bpod, pb->cmd[i].reg.data);
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (lock)
|
||||
error("exiting blkcmds with lock ON");
|
||||
}
|
||||
|
||||
void aic3xxx_wait(void *p, unsigned int reg, u8 mask, u8 data)
|
||||
{
|
||||
cfw_state *ps = p;
|
||||
while ((ps->ops->reg_read(ps->ops_obj, reg)&mask) != data)
|
||||
mdelay(2);
|
||||
}
|
||||
|
||||
static int aic3xxx_cfw_dlcfg(void *pv, cfw_image *pim)
|
||||
{
|
||||
cfw_state *ps = pv;
|
||||
int i,run_state,swap;
|
||||
struct {
|
||||
u32 mdsp;
|
||||
int buf_a, buf_b;
|
||||
u32 swap;
|
||||
} csecs[] = {
|
||||
{
|
||||
.mdsp=AIC3XX_COPS_MDSP_A,
|
||||
.swap=AIC3XX_ABUF_MDSP_A,
|
||||
.buf_a=CFW_BLOCK_A_A_COEF,
|
||||
.buf_b=CFW_BLOCK_A_B_COEF
|
||||
},
|
||||
{
|
||||
.mdsp=AIC3XX_COPS_MDSP_D,
|
||||
.swap=AIC3XX_ABUF_MDSP_D1,
|
||||
.buf_a=CFW_BLOCK_D_A1_COEF,
|
||||
.buf_b=CFW_BLOCK_D_B1_COEF
|
||||
},
|
||||
{
|
||||
.mdsp=AIC3XX_COPS_MDSP_D,
|
||||
.swap=AIC3XX_ABUF_MDSP_D2,
|
||||
.buf_a=CFW_BLOCK_D_A2_COEF,
|
||||
.buf_b=CFW_BLOCK_D_B2_COEF
|
||||
},
|
||||
};
|
||||
DBG("Download CFG %s", pim->name);
|
||||
run_state = ps->ops->lock(ps->ops_obj);
|
||||
swap = 0;
|
||||
for (i = 0; i < sizeof(csecs)/sizeof(csecs[0]); ++i) {
|
||||
if (pim->block[csecs[i].buf_a]) {
|
||||
if (run_state & csecs[i].mdsp) {
|
||||
aic3xxx_cfw_dlcmds(pv, pim->block[csecs[i].buf_a]);
|
||||
swap |= csecs[i].swap;
|
||||
aic3xxx_cfw_dlcmds(pv, pim->block[csecs[i].buf_b]);
|
||||
} else {
|
||||
aic3xxx_cfw_dlcmds(pv, pim->block[csecs[i].buf_a]);
|
||||
aic3xxx_cfw_dlcmds(pv, pim->block[csecs[i].buf_b]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (swap) // Check needed? FIXME
|
||||
ps->ops->bswap(ps->ops_obj, swap);
|
||||
ps->ops->unlock(ps->ops_obj);
|
||||
return 0;
|
||||
}
|
||||
static int aic3xxx_cfw_dlimage(void *pv, cfw_image *pim)
|
||||
{
|
||||
//cfw_state *ps = pv;
|
||||
int i;
|
||||
DBG("Download IMAGE %s", pim->name);
|
||||
for (i = 0; i < CFW_BLOCK_N; ++i)
|
||||
if (pim->block[i])
|
||||
aic3xxx_cfw_dlcmds(pv, pim->block[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# define FW_NDX2PTR(x, b) do { \
|
||||
x = (void *)((u8 *)(b) + ((int)(x))); \
|
||||
} while (0)
|
||||
static void aic3xxx_cfw_unpickle_block(cfw_block *pb, void *p)
|
||||
{
|
||||
int i;
|
||||
if (CFW_BLOCK_BURSTS(pb->type)) {
|
||||
for (i = 0; i < pb->ncmds; ++i) {
|
||||
FW_NDX2PTR(pb->cmd[i].burst, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void aic3xxx_cfw_unpickle_image(cfw_image *im, void *p)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < CFW_BLOCK_N; ++i)
|
||||
if (im->block[i]) {
|
||||
FW_NDX2PTR(im->block[i], p);
|
||||
aic3xxx_cfw_unpickle_block(im->block[i], p);
|
||||
}
|
||||
}
|
||||
#ifndef AIC3XXX_CFW_HOST_BLD
|
||||
static
|
||||
#endif
|
||||
unsigned int crc32(unsigned int *pdata, int n)
|
||||
{
|
||||
u32 crc = 0, i, crc_poly = 0x04C11DB7; /* CRC - 32 */
|
||||
u32 msb;
|
||||
u32 residue_value;
|
||||
int bits;
|
||||
|
||||
for (i = 0; i < (n >> 2); i++) {
|
||||
bits = 32;
|
||||
while (--bits >= 0) {
|
||||
msb = crc & 0x80000000;
|
||||
crc = (crc << 1) ^ ((*pdata >> bits) & 1);
|
||||
if (msb)
|
||||
crc = crc ^ crc_poly;
|
||||
}
|
||||
pdata++;
|
||||
}
|
||||
|
||||
switch (n & 3) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
residue_value = (*pdata & 0xFF);
|
||||
bits = 8;
|
||||
break;
|
||||
case 2:
|
||||
residue_value = (*pdata & 0xFFFF);
|
||||
bits = 16;
|
||||
break;
|
||||
case 3:
|
||||
residue_value = (*pdata & 0xFFFFFF);
|
||||
bits = 24;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n & 3) {
|
||||
while (--bits >= 0) {
|
||||
msb = crc & 0x80000000;
|
||||
crc = (crc << 1) ^ ((residue_value >> bits) & 1);
|
||||
if (msb)
|
||||
crc = crc ^ crc_poly;
|
||||
}
|
||||
}
|
||||
return (crc);
|
||||
}
|
||||
static int crc_chk(void *p, int n)
|
||||
{
|
||||
cfw_project *pjt = (void *)p;
|
||||
u32 crc = pjt->cksum, crc_comp;
|
||||
pjt->cksum = 0;
|
||||
DBG("Entering crc %d",n);
|
||||
crc_comp = crc32(p, n);
|
||||
if (crc_comp != crc) {
|
||||
DBG("CRC mismatch 0x%08X != 0x%08X", crc, crc_comp);
|
||||
return 0; // Dead code
|
||||
}
|
||||
DBG("CRC pass");
|
||||
pjt->cksum = crc;
|
||||
return 1;
|
||||
}
|
||||
#ifndef AIC3XXX_CFW_HOST_BLD
|
||||
static
|
||||
#endif
|
||||
cfw_project *aic3xxx_cfw_unpickle(void *p, int n)
|
||||
{
|
||||
cfw_project *pjt = p;
|
||||
int i, j, k;
|
||||
if (pjt->magic != CFW_FW_MAGIC ||
|
||||
pjt->size != n ||
|
||||
pjt->bmagic != CFW_FW_VERSION ||
|
||||
!crc_chk(p, n)) {
|
||||
error("magic:0x%08X!=0x%08X || size:%d!=%d || version:0x%08X!=0x%08X",
|
||||
pjt->magic, CFW_FW_MAGIC, pjt->size, n, pjt->cksum,
|
||||
CFW_FW_VERSION);
|
||||
return NULL;
|
||||
}
|
||||
DBG("Loaded firmware inside unpickle\n");
|
||||
|
||||
for (i = 0; i < CFW_MAX_TRANSITIONS; i++) {
|
||||
if (pjt->transition[i]) {
|
||||
FW_NDX2PTR(pjt->transition[i], p);
|
||||
FW_NDX2PTR(pjt->transition[i]->block, p);
|
||||
aic3xxx_cfw_unpickle_block(pjt->transition[i]->block, p);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < pjt->npfw; i++) {
|
||||
DBG("loading pfw %d\n",i);
|
||||
FW_NDX2PTR(pjt->pfw[i], p);
|
||||
if (pjt->pfw[i]->base) {
|
||||
FW_NDX2PTR(pjt->pfw[i]->base, p);
|
||||
aic3xxx_cfw_unpickle_image(pjt->pfw[i]->base, p);
|
||||
}
|
||||
if (pjt->pfw[i]->pll) {
|
||||
FW_NDX2PTR(pjt->pfw[i]->pll, p);
|
||||
aic3xxx_cfw_unpickle_block(pjt->pfw[i]->pll, p);
|
||||
}
|
||||
for (j =0; j < pjt->pfw[i]->novly; ++j)
|
||||
for (k =0; k < pjt->pfw[i]->ncfg; ++k) {
|
||||
FW_NDX2PTR(pjt->pfw[i]->ovly_cfg[j][k], p);
|
||||
aic3xxx_cfw_unpickle_image(pjt->pfw[i]->ovly_cfg[j][k], p);
|
||||
}
|
||||
}
|
||||
|
||||
DBG("loaded pfw's\n");
|
||||
for (i = 0; i < pjt->nmode; i++) {
|
||||
FW_NDX2PTR(pjt->mode[i], p);
|
||||
if (pjt->mode[i]->entry) {
|
||||
FW_NDX2PTR(pjt->mode[i]->entry, p);
|
||||
aic3xxx_cfw_unpickle_block(pjt->mode[i]->entry, p);
|
||||
}
|
||||
if (pjt->mode[i]->exit) {
|
||||
FW_NDX2PTR(pjt->mode[i]->exit, p);
|
||||
aic3xxx_cfw_unpickle_block(pjt->mode[i]->exit, p);
|
||||
}
|
||||
}
|
||||
DBG("loaded modes\n");
|
||||
return pjt;
|
||||
}
|
||||
|
||||
|
||||
69
sound/soc/codecs/aic3xxx_cfw_ops.h
Normal file
69
sound/soc/codecs/aic3xxx_cfw_ops.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef AIC3XXX_CFW_OPS_H_
|
||||
#define AIC3XXX_CFW_OPS_H_
|
||||
|
||||
#ifdef AIC3XXX_CFW_HOST_BLD
|
||||
void *aic3xxx_cfw_init(void *pcfw, int n);
|
||||
void *aic3xxx_cfw_getpjt(void *ps);
|
||||
cfw_project *aic3xxx_cfw_unpickle(void *,int);
|
||||
unsigned int crc32(unsigned int *pdata, int n);
|
||||
#endif
|
||||
|
||||
int aic3xxx_cfw_reload(void *pv, void *pcfw, int n);
|
||||
int aic3xxx_cfw_setmode(void *pv, int mode);
|
||||
int aic3xxx_cfw_setmode_cfg(void *pv, int mode, int cfg);
|
||||
int aic3xxx_cfw_setcfg(void *pv, int cfg);
|
||||
int aic3xxx_cfw_transition(void *pv, char *ttype);
|
||||
int aic3xxx_cfw_set_pll(void *pv, int asi);
|
||||
|
||||
|
||||
#define AIC3XX_COPS_MDSP_D (0x00000003u)
|
||||
#define AIC3XX_COPS_MDSP_A (0x00000030u)
|
||||
#define AIC3XX_COPS_MDSP_ALL (AIC3XX_COPS_MDSP_D|AIC3XX_COPS_MDSP_A)
|
||||
|
||||
#define AIC3XX_ABUF_MDSP_D1 (0x00000001u)
|
||||
#define AIC3XX_ABUF_MDSP_D2 (0x00000002u)
|
||||
#define AIC3XX_ABUF_MDSP_A (0x00000010u)
|
||||
#define AIC3XX_ABUF_MDSP_ALL \
|
||||
(AIC3XX_ABUF_MDSP_D1| AIC3XX_ABUF_MDSP_D2| AIC3XX_ABUF_MDSP_A)
|
||||
|
||||
typedef struct aic3xxx_codec_ops {
|
||||
int (*reg_read)(void *p, unsigned int reg);
|
||||
int (*reg_write)(void *p, unsigned int reg,
|
||||
unsigned int val);
|
||||
int (*set_bits)(void *p, unsigned int reg,
|
||||
unsigned char mask, unsigned char val);
|
||||
int (*bulk_read)(void *p, unsigned int reg,
|
||||
int count, u8 *buf);
|
||||
int (*bulk_write)(void *p, unsigned int reg,
|
||||
int count, const u8 *buf);
|
||||
|
||||
int (*lock)(void *p);
|
||||
int (*unlock)(void *p);
|
||||
int (*stop)(void *p, int mask);
|
||||
int (*restore)(void *p, int runstate);
|
||||
int (*bswap)(void *p,int mask);
|
||||
} aic3xxx_codec_ops;
|
||||
|
||||
typedef struct cfw_state {
|
||||
cfw_project *pjt;
|
||||
const aic3xxx_codec_ops *ops;
|
||||
void *ops_obj;
|
||||
int cur_mode;
|
||||
int cur_pfw;
|
||||
int cur_ovly;
|
||||
int cur_cfg;
|
||||
} cfw_state;
|
||||
|
||||
#ifndef AIC3XXX_CFW_HOST_BLD
|
||||
#ifdef DEBUG
|
||||
|
||||
# define DBG(fmt,...) printk("CFW[%s:%d]: " fmt "\n", \
|
||||
__FILE__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
|
||||
# define DBG(fmt,...)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
7
sound/soc/codecs/pickle.h
Normal file
7
sound/soc/codecs/pickle.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef PICKLE_H_
|
||||
#define PICKLE_H_
|
||||
|
||||
void *pickle_pjt(cfw_project *p, int *n);
|
||||
cfw_project *unpickle_pjt(void *p, int n);
|
||||
|
||||
#endif
|
||||
320
sound/soc/codecs/tlv320aic3262_default_fw.h
Normal file
320
sound/soc/codecs/tlv320aic3262_default_fw.h
Normal file
@@ -0,0 +1,320 @@
|
||||
unsigned char default_firmware[] = {
|
||||
237,241,209,192,175, 0, 1, 0,219, 19, 0, 0, 28, 84, 36, 37,
|
||||
0, 0, 0, 0,161, 85,149, 79, 70,105,114,109,119, 97,114,101,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 2, 13, 0, 0, 8, 2, 0, 0,
|
||||
0, 0, 0, 0, 0,240, 73, 2,172, 3, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 32, 6, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,131, 17, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
105,110,105,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
73,110,105,116,105, 97,108,105,122, 97,116,105,111,110, 32,115,
|
||||
101,113,117,101,110, 99,101, 32, 40, 97,112,112,108,105,101,100,
|
||||
32,111,110,108,121, 32,111,110, 32,115,121,115,116,101,109, 32,
|
||||
98,111,111,116, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
244, 5, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,100, 0,128, 0,
|
||||
0, 1, 1, 0, 0, 1,122, 1, 0, 0, 4, 51, 0, 0, 82, 0,
|
||||
0, 0, 67,151, 0, 1,119,127, 0, 0,129, 1, 0, 4, 11, 1,
|
||||
100,101,102, 97,117,108,116, 0, 98, 97,115,101, 95,109, 97,105,
|
||||
110, 95, 82, 97,116,101, 52, 56, 46, 99,102,103, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0,
|
||||
253, 11, 0, 0,120, 9, 0, 0,121, 12, 0, 0,254, 14, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,100,101,102, 97,117,108,116, 47,
|
||||
98, 97,115,101, 95,109, 97,105,110, 95, 82, 97,116,101, 52, 56,
|
||||
46, 99,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 8,115,247,
|
||||
0, 0, 0, 0,137, 55, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,232, 11, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 1, 0, 0, 0,
|
||||
244, 11, 0, 0, 2, 0, 0, 0, 0, 0, 60, 1, 1, 0, 0, 0,
|
||||
0, 29, 0, 0, 0, 0, 0,129,127, 0, 0, 6, 33, 0, 0,129,
|
||||
63, 0, 0, 7, 5, 0, 0, 8, 4, 0, 0, 9,176, 0, 0,129,
|
||||
127, 0, 0, 10, 1, 0, 0,129,127, 0, 0, 11, 2, 0, 0,129,
|
||||
127, 0, 0, 12, 8, 0, 0, 13, 0, 0, 0, 14,128, 0, 0, 18,
|
||||
130, 0, 0, 19,136, 0, 0, 20,128, 0, 0,129, 3, 0, 4, 11,
|
||||
0, 0, 0,129,127, 0, 4, 12, 4, 0, 0,129,127, 0, 4, 13,
|
||||
32, 0, 0,129,119, 0, 4, 14, 0, 0, 4,119,240, 0, 4,120,
|
||||
0,100, 0, 20,128,120, 0, 20, 0,100,101,102, 97,117,108,116,
|
||||
47, 80, 97,116, 99,104, 95, 98, 97,115,101, 95,109, 97,105,110,
|
||||
95, 82, 97,116,101, 52, 56, 46, 99,102,103, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,233, 14, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 1, 0, 0,
|
||||
0,245, 14, 0, 0, 2, 0, 0, 0, 0, 0, 60, 1, 1,100,101,
|
||||
102, 97,117,108,116, 47, 80, 97,116, 99,104, 95, 98, 97,115,101,
|
||||
95,115,112,107, 95, 82, 97,116,101, 52, 56, 46, 99,102,103, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 96, 8,115,247, 0, 0, 0, 0,233, 58, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 17,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 36,
|
||||
115,247, 1, 0, 0, 0,122, 17, 0, 0, 2, 0, 0, 0, 0, 0,
|
||||
60, 1, 1, 0, 0, 0, 0,100,101,102, 97,117,108,116, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
2869
sound/soc/codecs/tlv320aic326x.c
Normal file
2869
sound/soc/codecs/tlv320aic326x.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user