1.3 sparc64
1.4 ppc
1.5 SuperH
+1.6 Blackfin
2. "Policy" / "Governor"?
2.1 Policy
SH-3
SH-4
+1.6 Blackfin
+------------
+
+The following Blackfin processors are supported by cpufreq:
+
+BF522, BF523, BF524, BF525, BF526, BF527, Rev 0.1 or higher
+BF531, BF532, BF533, Rev 0.3 or higher
+BF534, BF536, BF537, Rev 0.2 or higher
+BF561, Rev 0.3 or higher
+BF542, BF544, BF547, BF548, BF549, Rev 0.1 or higher
+
2. "Policy" / "Governor" ?
==========================
archive and links it into the resulting kernel binary. By default, this
archive is empty (consuming 134 bytes on x86).
-The config option CONFIG_INITRAMFS_SOURCE (for some reason buried under
-devices->block devices in menuconfig, and living in usr/Kconfig) can be used
-to specify a source for the initramfs archive, which will automatically be
-incorporated into the resulting binary. This option can point to an existing
-gzipped cpio archive, a directory containing files to be archived, or a text
-file specification such as the following example:
+The config option CONFIG_INITRAMFS_SOURCE (in General Setup in menuconfig,
+and living in usr/Kconfig) can be used to specify a source for the
+initramfs archive, which will automatically be incorporated into the
+resulting binary. This option can point to an existing gzipped cpio
+archive, a directory containing files to be archived, or a text file
+specification such as the following example:
dir /dev 755 0 0
nod /dev/console 644 0 0 c 5 1
static struct input_dev *button_dev;
-static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t button_interrupt(int irq, void *dummy)
{
input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);
input_sync(button_dev);
+ return IRQ_HANDLED;
}
static int __init button_init(void)
ref Reference board
dell-m4-1 Dell desktops
dell-m4-2 Dell desktops
+ dell-m4-3 Dell desktops
STAC92HD73*
ref Reference board
- dell-m6 Dell desktops
+ dell-m6-amic Dell desktops/laptops with analog mics
+ dell-m6-dmic Dell desktops/laptops with digital mics
+ dell-m6 Dell desktops/laptops with both type of mics
STAC9872
vaio Setup for VAIO FE550G/SZ110
the following struct:-
/* SoC machine */
-struct snd_soc_machine {
+struct snd_soc_card {
char *name;
int (*probe)(struct platform_device *pdev);
.ops = &corgi_ops,
};
-struct snd_soc_machine then sets up the machine with it's DAIs. e.g.
+struct snd_soc_card then sets up the machine with it's DAIs. e.g.
/* corgi audio machine driver */
-static struct snd_soc_machine snd_soc_machine_corgi = {
+static struct snd_soc_card snd_soc_corgi = {
.name = "Corgi",
.dai_link = &corgi_dai,
.num_links = 1,
/* corgi audio subsystem */
static struct snd_soc_device corgi_snd_devdata = {
- .machine = &snd_soc_machine_corgi,
+ .machine = &snd_soc_corgi,
.platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &corgi_wm8731_setup,
$ cat /debug/tracing/trace_pipe > mydump.txt &
Start X or whatever.
$ echo "X is up" > /debug/tracing/trace_marker
-$ echo none > /debug/tracing/current_tracer
+$ echo nop > /debug/tracing/current_tracer
Check for lost events.
do.
Shut down mmiotrace (requires root privileges):
-$ echo none > /debug/tracing/current_tracer
+$ echo nop > /debug/tracing/current_tracer
The 'cat' process exits. If it does not, kill it by issuing 'fg' command and
pressing ctrl+c.
$ cat /debug/tracing/trace_entries
gives you a number. Approximately double this number and write it back, for
instance:
+$ echo 0 > /debug/tracing/tracing_enabled
$ echo 128000 > /debug/tracing/trace_entries
+$ echo 1 > /debug/tracing/tracing_enabled
Then start again from the top.
If you are doing a trace for a driver project, e.g. Nouveau, you should also
L: alsa-devel@alsa-project.org (subscribers-only)
S: Maintained
-SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
+SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
P: Liam Girdwood
M: lrg@slimlogic.co.uk
P: Mark Brown
# task_pt_regs() in asm/processor.h or asm/ptrace.h
# arch_has_single_step() if there is hardware single-step support
# arch_has_block_step() if there is hardware block-step support
-# arch_ptrace() and not #define __ARCH_SYS_PTRACE
-# compat_arch_ptrace() and #define __ARCH_WANT_COMPAT_SYS_PTRACE
# asm/syscall.h supplying asm-generic/syscall.h interface
# linux/regset.h user_regset interfaces
# CORE_DUMP_USE_REGSET #define'd in linux/elf.h
return PCI_SLOT(dev->devfn);
}
-void __devinit
+void
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
{
/*
* Where secondaries begin a life of C.
*/
-void __init
+void __cpuinit
smp_callin(void)
{
int cpuid = hard_smp_processor_id();
* Send a message to a secondary's console. "START" is one such
* interesting message. ;-)
*/
-static void __init
+static void __cpuinit
send_secondary_console_msg(char *str, int cpuid)
{
struct percpu_struct *cpu;
/*
* Convince the console to have a secondary cpu begin execution.
*/
-static int __init
+static int __cpuinit
secondary_cpu_start(int cpuid, struct task_struct *idle)
{
struct percpu_struct *cpu;
static int opDEC_fix;
-static void __init
+static void __cpuinit
opDEC_check(void)
{
__asm__ __volatile__ (
return;
}
-void __init
+void __cpuinit
trap_init(void)
{
/* Tell PAL-code what global pointer we want in the kernel. */
# CONFIG_MACH_AKITA is not set
# CONFIG_MACH_SPITZ is not set
# CONFIG_MACH_BORZOI is not set
-CONFIG_MACH_TOSA=y
+# CONFIG_MACH_TOSA is not set
# CONFIG_ARCH_VIPER is not set
# CONFIG_ARCH_PXA_ESERIES is not set
# CONFIG_TRIZEPS_PXA is not set
--- /dev/null
+#ifndef _INCLUDE_PALMASOC_H_
+#define _INCLUDE_PALMASOC_H_
+struct palm27x_asoc_info {
+ int jack_gpio;
+};
+
+#ifdef CONFIG_SND_PXA2XX_SOC_PALM27X
+void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data);
+#else
+static inline void palm27x_asoc_set_pdata(struct palm27x_asoc_info *data) {}
+#endif
+
+#endif
#define LCD_CONN_TYPE(_x) ((_x) & 0x0f)
#define LCD_CONN_WIDTH(_x) (((_x) >> 4) & 0x1f)
+#define LCD_TYPE_MASK 0xf
#define LCD_TYPE_UNKNOWN 0
#define LCD_TYPE_MONO_STN 1
#define LCD_TYPE_MONO_DSTN 2
u32 *mem_resume_unknown = phys_to_virt(RESUME_UNKNOWN_ADDR);
/* Devices prepare suspend */
- is_bt_on = gpio_get_value(GPIO83_BT_ON);
+ is_bt_on = !!gpio_get_value(GPIO83_BT_ON);
pxa2xx_mfp_set_lpm(GPIO83_BT_ON,
is_bt_on ? MFP_LPM_DRIVE_HIGH : MFP_LPM_DRIVE_LOW);
1:
mov r0, #0xa0000000 @ Don't suppose memory access works
orr r0, r0, #0x00200000 @ even if it's supposed to
+ orr r0, r0, #0x0000b000
mov r1, #0
str r1, [r0] @ Early disable resume for next boot
ldr r0, mioa701_jumpaddr @ (Murphy's Law)
GPIO110_MMC_DAT_2,
GPIO111_MMC_DAT_3,
GPIO112_MMC_CMD,
+ GPIO14_GPIO, /* SD detect */
+ GPIO114_GPIO, /* SD power */
+ GPIO115_GPIO, /* SD r/o switch */
/* AC97 */
GPIO28_AC97_BITCLK,
GPIO31_AC97_SYNC,
/* IrDA */
+ GPIO40_GPIO, /* ir disable */
GPIO46_FICP_RXD,
GPIO47_FICP_TXD,
GPIO16_PWM0_OUT,
/* USB */
- GPIO13_GPIO,
+ GPIO13_GPIO, /* usb detect */
+ GPIO95_GPIO, /* usb power */
/* PCMCIA */
GPIO48_nPOE,
GPIO55_nPREG,
GPIO56_nPWAIT,
GPIO57_nIOIS16,
+ GPIO94_GPIO, /* wifi power 1 */
+ GPIO108_GPIO, /* wifi power 2 */
+ GPIO116_GPIO, /* wifi ready */
+
+ /* MATRIX KEYPAD */
+ GPIO100_KP_MKIN_0,
+ GPIO101_KP_MKIN_1,
+ GPIO102_KP_MKIN_2,
+ GPIO97_KP_MKIN_3,
+ GPIO103_KP_MKOUT_0,
+ GPIO104_KP_MKOUT_1,
+ GPIO105_KP_MKOUT_2,
+
+ /* LCD */
+ GPIO58_LCD_LDD_0,
+ GPIO59_LCD_LDD_1,
+ GPIO60_LCD_LDD_2,
+ GPIO61_LCD_LDD_3,
+ GPIO62_LCD_LDD_4,
+ GPIO63_LCD_LDD_5,
+ GPIO64_LCD_LDD_6,
+ GPIO65_LCD_LDD_7,
+ GPIO66_LCD_LDD_8,
+ GPIO67_LCD_LDD_9,
+ GPIO68_LCD_LDD_10,
+ GPIO69_LCD_LDD_11,
+ GPIO70_LCD_LDD_12,
+ GPIO71_LCD_LDD_13,
+ GPIO72_LCD_LDD_14,
+ GPIO73_LCD_LDD_15,
+ GPIO74_LCD_FCLK,
+ GPIO75_LCD_LCLK,
+ GPIO76_LCD_PCLK,
+ GPIO77_LCD_BIAS,
+
+ /* MISC. */
+ GPIO10_GPIO, /* hotsync button */
+ GPIO12_GPIO, /* power detect */
+ GPIO107_GPIO, /* earphone detect */
};
/******************************************************************************
int err = 0;
/* Setup an interrupt for detecting card insert/remove events */
- err = request_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, palmtx_detect_int,
- IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+ err = gpio_request(GPIO_NR_PALMTX_SD_DETECT_N, "SD IRQ");
+ if (err)
+ goto err;
+ err = gpio_direction_input(GPIO_NR_PALMTX_SD_DETECT_N);
+ if (err)
+ goto err2;
+ err = request_irq(gpio_to_irq(GPIO_NR_PALMTX_SD_DETECT_N),
+ palmtx_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"SD/MMC card detect", data);
if (err) {
printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
__func__);
- return err;
+ goto err2;
}
err = gpio_request(GPIO_NR_PALMTX_SD_POWER, "SD_POWER");
if (err)
- goto pwr_err;
+ goto err3;
+ err = gpio_direction_output(GPIO_NR_PALMTX_SD_POWER, 0);
+ if (err)
+ goto err4;
err = gpio_request(GPIO_NR_PALMTX_SD_READONLY, "SD_READONLY");
if (err)
- goto ro_err;
+ goto err4;
+ err = gpio_direction_input(GPIO_NR_PALMTX_SD_READONLY);
+ if (err)
+ goto err5;
printk(KERN_DEBUG "%s: irq registered\n", __func__);
return 0;
-ro_err:
+err5:
+ gpio_free(GPIO_NR_PALMTX_SD_READONLY);
+err4:
gpio_free(GPIO_NR_PALMTX_SD_POWER);
-pwr_err:
- free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
+err3:
+ free_irq(gpio_to_irq(GPIO_NR_PALMTX_SD_DETECT_N), data);
+err2:
+ gpio_free(GPIO_NR_PALMTX_SD_DETECT_N);
+err:
return err;
}
{
gpio_free(GPIO_NR_PALMTX_SD_READONLY);
gpio_free(GPIO_NR_PALMTX_SD_POWER);
- free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
+ free_irq(gpio_to_irq(GPIO_NR_PALMTX_SD_DETECT_N), data);
+ gpio_free(GPIO_NR_PALMTX_SD_DETECT_N);
}
static void palmtx_mci_power(struct device *dev, unsigned int vdd)
KEY(3, 0, KEY_RIGHT),
KEY(3, 2, KEY_LEFT),
-
};
static struct pxa27x_keypad_platform_data palmtx_keypad_platform_data = {
ret = gpio_request(GPIO_NR_PALMTX_BL_POWER, "BL POWER");
if (ret)
goto err;
+ ret = gpio_direction_output(GPIO_NR_PALMTX_BL_POWER, 0);
+ if (ret)
+ goto err2;
ret = gpio_request(GPIO_NR_PALMTX_LCD_POWER, "LCD POWER");
if (ret)
goto err2;
+ ret = gpio_direction_output(GPIO_NR_PALMTX_LCD_POWER, 0);
+ if (ret)
+ goto err3;
return 0;
+err3:
+ gpio_free(GPIO_NR_PALMTX_LCD_POWER);
err2:
gpio_free(GPIO_NR_PALMTX_BL_POWER);
err:
/******************************************************************************
* IrDA
******************************************************************************/
+static int palmtx_irda_startup(struct device *dev)
+{
+ int err;
+ err = gpio_request(GPIO_NR_PALMTX_IR_DISABLE, "IR DISABLE");
+ if (err)
+ goto err;
+ err = gpio_direction_output(GPIO_NR_PALMTX_IR_DISABLE, 1);
+ if (err)
+ gpio_free(GPIO_NR_PALMTX_IR_DISABLE);
+err:
+ return err;
+}
+
+static void palmtx_irda_shutdown(struct device *dev)
+{
+ gpio_free(GPIO_NR_PALMTX_IR_DISABLE);
+}
+
static void palmtx_irda_transceiver_mode(struct device *dev, int mode)
{
gpio_set_value(GPIO_NR_PALMTX_IR_DISABLE, mode & IR_OFF);
}
static struct pxaficp_platform_data palmtx_ficp_platform_data = {
+ .startup = palmtx_irda_startup,
+ .shutdown = palmtx_irda_shutdown,
.transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF,
.transceiver_mode = palmtx_irda_transceiver_mode,
};
/******************************************************************************
* UDC
******************************************************************************/
-static void palmtx_udc_command(int cmd)
-{
- gpio_set_value(GPIO_NR_PALMTX_USB_POWER, !cmd);
- udelay(50);
- gpio_set_value(GPIO_NR_PALMTX_USB_PULLUP, !cmd);
-}
-
static struct pxa2xx_udc_mach_info palmtx_udc_info __initdata = {
.gpio_vbus = GPIO_NR_PALMTX_USB_DETECT_N,
.gpio_vbus_inverted = 1,
- .udc_command = palmtx_udc_command,
+ .gpio_pullup = GPIO_NR_PALMTX_USB_POWER,
+ .gpio_pullup_inverted = 0,
};
/******************************************************************************
ret = gpio_request(GPIO_NR_PALMTX_POWER_DETECT, "CABLE_STATE_AC");
if (ret)
- goto err_cs_ac;
-
- ret = gpio_request(GPIO_NR_PALMTX_USB_DETECT_N, "CABLE_STATE_USB");
+ goto err1;
+ ret = gpio_direction_input(GPIO_NR_PALMTX_POWER_DETECT);
if (ret)
- goto err_cs_usb;
+ goto err2;
return 0;
-err_cs_usb:
+err2:
gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
-err_cs_ac:
+err1:
return ret;
}
return gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT);
}
-static int palmtx_is_usb_online(void)
-{
- return !gpio_get_value(GPIO_NR_PALMTX_USB_DETECT_N);
-}
-
static void power_supply_exit(struct device *dev)
{
- gpio_free(GPIO_NR_PALMTX_USB_DETECT_N);
gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
}
static struct pda_power_pdata power_supply_info = {
.init = power_supply_init,
.is_ac_online = palmtx_is_ac_online,
- .is_usb_online = palmtx_is_usb_online,
.exit = power_supply_exit,
.supplied_to = palmtx_supplicants,
.num_supplicants = ARRAY_SIZE(palmtx_supplicants),
iotable_init(palmtx_io_desc, ARRAY_SIZE(palmtx_io_desc));
}
+/* setup udc GPIOs initial state */
+static void __init palmtx_udc_init(void)
+{
+ if (!gpio_request(GPIO_NR_PALMTX_USB_POWER, "UDC Vbus")) {
+ gpio_direction_output(GPIO_NR_PALMTX_USB_POWER, 1);
+ gpio_free(GPIO_NR_PALMTX_USB_POWER);
+ }
+}
+
+
static void __init palmtx_init(void)
{
pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtx_pin_config));
set_pxa_fb_info(&palmtx_lcd_screen);
pxa_set_mci_info(&palmtx_mci_platform_data);
+ palmtx_udc_init();
pxa_set_udc_info(&palmtx_udc_info);
pxa_set_ac97_info(NULL);
pxa_set_ficp_info(&palmtx_ficp_platform_data);
.gpio = NR_BUILTIN_GPIO + 1,
}, {
.bus_id = 0, /* Must match with the camera ID above */
+ .gpio = -ENXIO,
}
};
/* Jump into ROM at address 0 */
cpu_reset(0);
break;
- case 'h':
- do_hw_reset();
- break;
case 'g':
do_gpio_reset();
break;
+ case 'h':
+ default:
+ do_hw_reset();
+ break;
}
}
static unsigned long spitz_pin_config[] __initdata = {
/* Chip Selects */
GPIO78_nCS_2, /* SCOOP #2 */
+ GPIO79_nCS_3, /* NAND */
GPIO80_nCS_4, /* SCOOP #1 */
/* LCD - 16bpp Active TFT */
GPIO51_nPIOW,
GPIO85_nPCE_1,
GPIO54_nPCE_2,
- GPIO79_PSKTSEL,
GPIO55_nPREG,
GPIO56_nPWAIT,
GPIO57_nIOIS16,
+ GPIO104_PSKTSEL,
/* MMC */
GPIO32_MMC_CLK,
spitz_pcmcia_config.num_devs = 1;
platform_scoop_config = &spitz_pcmcia_config;
- pxa_set_i2c_info(NULL);
i2c_register_board_info(0, ARRAY_AND_SIZE(akita_i2c_board_info));
common_init();
#define OMAP24XX_GPIO_IRQSTATUS2 0x0028
#define OMAP24XX_GPIO_IRQENABLE2 0x002c
#define OMAP24XX_GPIO_IRQENABLE1 0x001c
+#define OMAP24XX_GPIO_WAKE_EN 0x0020
#define OMAP24XX_GPIO_CTRL 0x0030
#define OMAP24XX_GPIO_OE 0x0034
#define OMAP24XX_GPIO_DATAIN 0x0038
#endif
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
- wake_status = bank->base + OMAP24XX_GPIO_SETWKUENA;
+ wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
break;
{
int i;
- if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
+ if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
return 0;
for (i = 0; i < gpio_bank_count; i++) {
* clk_allow_idle - Counters previous clk_deny_idle
* @clk: clock signal handle
*/
-void clk_deny_idle(struct clk *clk);
+void clk_allow_idle(struct clk *clk);
extern void omap_pm_idle(void);
extern void omap_pm_suspend(void);
#define arch_has_block_step() (1)
extern void user_enable_block_step(struct task_struct *);
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#endif /* !__KERNEL__ */
/* pt_all_user_regs is used for PTRACE_GETREGS PTRACE_SETREGS */
* sn_pci_controller_fixup() - This routine sets up a bus's resources
* consistent with the Linux PCI abstraction layer.
*/
-static void
+static void __init
sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
{
s64 status = 0;
/*
* References to members of the boot_cpu_data structure.
*/
- .text
+.section .text.head, "ax"
.global start_kernel
.global __bss_start
.global _end
/*
* AP startup routine
*/
- .text
.global eit_vector
ENTRY(startup_AP)
;; setup EVB
nop
#endif /* CONFIG_SMP */
+ .text
ENTRY(stack_start)
.long init_thread_union+8192
.long __KERNEL_DS
_text = .; /* Text and read-only data */
.boot : { *(.boot) } = 0
.text : {
+ *(.text.head)
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
#include <asm/break.h>
-#define BUG() \
-do { \
- __asm__ __volatile__("break %0" : : "i" (BRK_BUG)); \
-} while (0)
+static inline void __noreturn BUG(void)
+{
+ __asm__ __volatile__("break %0" : : "i" (BRK_BUG));
+ /* Fool GCC into thinking the function doesn't return. */
+ while (1)
+ ;
+}
#define HAVE_ARCH_BUG
#if (_MIPS_ISA > _MIPS_ISA_MIPS1)
-#define BUG_ON(condition) \
-do { \
- __asm__ __volatile__("tne $0, %0, %1" \
- : : "r" (condition), "i" (BRK_BUG)); \
-} while (0)
+static inline void __BUG_ON(unsigned long condition)
+{
+ if (__builtin_constant_p(condition)) {
+ if (condition)
+ BUG();
+ else
+ return;
+ }
+ __asm__ __volatile__("tne $0, %0, %1"
+ : : "r" (condition), "i" (BRK_BUG));
+}
+
+#define BUG_ON(C) __BUG_ON((unsigned long)(C))
#define HAVE_ARCH_BUG_ON
#ifndef _ASM_PTRACE_H
#define _ASM_PTRACE_H
-#ifdef CONFIG_64BIT
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-#endif
-
/* 0 - 31 are integer registers, 32 - 63 are fp registers. */
#define FPR_BASE 32
#define PC 64
} else {
switch (cur) {
/* Bxx (d8,PC) */
- case 0xc0:
- case 0xc1:
- case 0xc2:
- case 0xc3:
- case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
- case 0xc8:
- case 0xc9:
- case 0xca:
+ case 0xc0 ... 0xca:
if (gdbstub_read_byte(pc + 1, (u8 *) &x) < 0)
goto fault;
if (!__gdbstub_mark_bp(pc + 2, 0))
break;
/* LXX (d8,PC) */
- case 0xd0:
- case 0xd1:
- case 0xd2:
- case 0xd3:
- case 0xd4:
- case 0xd5:
- case 0xd6:
- case 0xd7:
- case 0xd8:
- case 0xd9:
- case 0xda:
+ case 0xd0 ... 0xda:
if (!__gdbstub_mark_bp(pc + 1, 0))
goto fault;
if (regs->pc != regs->lar &&
#define to_parisc_driver(d) container_of(d, struct parisc_driver, drv)
#define parisc_parent(d) to_parisc_device(d->dev.parent)
-static inline char *parisc_pathname(struct parisc_device *d)
+static inline const char *parisc_pathname(struct parisc_device *d)
{
- return d->dev.bus_id;
+ return dev_name(&d->dev);
}
static inline void
typedef unsigned long __kernel_size_t;
typedef long __kernel_ssize_t;
typedef long __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
#else
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
#endif
+typedef long __kernel_time_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
#define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
struct task_struct;
#define arch_has_single_step() 1
void user_disable_single_step(struct task_struct *task);
EXPORT_SYMBOL(hppa_dma_ops);
static struct device root = {
- .bus_id = "parisc",
+ .init_name = "parisc",
};
static inline int check_dev(struct device *dev)
static void setup_bus_id(struct parisc_device *padev)
{
struct hardware_path path;
- char *output = padev->dev.bus_id;
+ char name[20];
+ char *output = name;
int i;
get_node_path(padev->dev.parent, &path);
output += sprintf(output, "%u:", (unsigned char) path.bc[i]);
}
sprintf(output, "%u", (unsigned char) padev->hw_path);
+ dev_set_name(&padev->dev, name);
}
struct parisc_device * create_tree_node(char id, struct device *parent)
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/console.h>
-#include <linux/kallsyms.h>
#include <linux/bug.h>
#include <asm/assembly.h>
DEFINE_SPINLOCK(pa_dbit_lock);
#endif
-void parisc_show_stack(struct task_struct *t, unsigned long *sp,
+static void parisc_show_stack(struct task_struct *task, unsigned long *sp,
struct pt_regs *regs);
static int printbinary(char *buf, unsigned long x, int nbits)
void show_regs(struct pt_regs *regs)
{
- int i;
+ int i, user;
char *level;
unsigned long cr30, cr31;
- level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
+ user = user_mode(regs);
+ level = user ? KERN_DEBUG : KERN_CRIT;
print_gr(level, regs);
for (i = 0; i < 8; i += 4)
PRINTREGS(level, regs->sr, "sr", RFMT, i);
- if (user_mode(regs))
+ if (user)
print_fr(level, regs);
cr30 = mfctl(30);
printk("%s CPU: %8d CR30: " RFMT " CR31: " RFMT "\n",
level, current_thread_info()->cpu, cr30, cr31);
printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);
- printk(level);
- print_symbol(" IAOQ[0]: %s\n", regs->iaoq[0]);
- printk(level);
- print_symbol(" IAOQ[1]: %s\n", regs->iaoq[1]);
- printk(level);
- print_symbol(" RP(r2): %s\n", regs->gr[2]);
-
- parisc_show_stack(current, NULL, regs);
+
+ if (user) {
+ printk("%s IAOQ[0]: " RFMT "\n", level, regs->iaoq[0]);
+ printk("%s IAOQ[1]: " RFMT "\n", level, regs->iaoq[1]);
+ printk("%s RP(r2): " RFMT "\n", level, regs->gr[2]);
+ } else {
+ printk("%s IAOQ[0]: %pS\n", level, (void *) regs->iaoq[0]);
+ printk("%s IAOQ[1]: %pS\n", level, (void *) regs->iaoq[1]);
+ printk("%s RP(r2): %pS\n", level, (void *) regs->gr[2]);
+
+ parisc_show_stack(current, NULL, regs);
+ }
}
break;
if (__kernel_text_address(info->ip)) {
- printk("%s [<" RFMT ">] ", (i&0x3)==1 ? KERN_CRIT : "", info->ip);
-#ifdef CONFIG_KALLSYMS
- print_symbol("%s\n", info->ip);
-#else
- if ((i & 0x03) == 0)
- printk("\n");
-#endif
+ printk(KERN_CRIT " [<" RFMT ">] %pS\n",
+ info->ip, (void *) info->ip);
i++;
}
}
- printk("\n");
+ printk(KERN_CRIT "\n");
}
-void parisc_show_stack(struct task_struct *task, unsigned long *sp,
+static void parisc_show_stack(struct task_struct *task, unsigned long *sp,
struct pt_regs *regs)
{
struct unwind_frame_info info;
#size-cells = <1>;
aliases {
- ethernet0 = &enet0;
- ethernet1 = &enet1;
+ ethernet0 = &enet1;
+ ethernet1 = &enet0;
serial0 = &serial0;
serial1 = &serial1;
pci0 = &pci0;
compatible = "fsl,mpc8572-l2-cache-controller";
reg = <0x20000 0x1000>;
cache-line-size = <32>; // 32 bytes
- cache-size = <0x80000>; // L2, 512K
+ cache-size = <0x100000>; // L2, 1M
interrupt-parent = <&mpic>;
interrupts = <16 2>;
};
--- /dev/null
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-rc4
+# Fri Nov 14 10:49:16 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+# CONFIG_6xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_4xx=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_PPC_DCR_NATIVE=y
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_DCR=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
+# CONFIG_PPC4xx_PCI_EXPRESS is not set
+
+#
+# Platform support
+#
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC4xx_GPIO is not set
+CONFIG_XILINX_VIRTEX=y
+# CONFIG_ACADIA is not set
+# CONFIG_EP405 is not set
+# CONFIG_HCU4 is not set
+# CONFIG_KILAUEA is not set
+# CONFIG_MAKALU is not set
+# CONFIG_WALNUT is not set
+CONFIG_XILINX_VIRTEX_GENERIC_BOARD=y
+# CONFIG_PPC40x_SIMPLE is not set
+CONFIG_XILINX_VIRTEX_II_PRO=y
+CONFIG_XILINX_VIRTEX_4_FX=y
+CONFIG_IBM405_ERR77=y
+CONFIG_IBM405_ERR51=y
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_4xx_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=m
+# CONFIG_IP_NF_TARGET_REJECT is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_XILINX_SYSACE=y
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_SERIO_XILINX_XPS_PS2=y
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+CONFIG_XILINX_HWICAP=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_XILINX=y
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_XILINX=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc1
-# Tue Aug 5 09:20:16 2008
+# Linux kernel version: 2.6.28-rc4
+# Fri Nov 14 10:31:16 2008
#
# CONFIG_PPC64 is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
-# CONFIG_HAVE_GET_USER_PAGES_FAST is not set
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
#
# CONFIG_KATMAI is not set
# CONFIG_RAINIER is not set
# CONFIG_WARP is not set
+# CONFIG_ARCHES is not set
# CONFIG_CANYONLANDS is not set
+# CONFIG_GLACIER is not set
# CONFIG_YOSEMITE is not set
CONFIG_XILINX_VIRTEX440_GENERIC_BOARD=y
+# CONFIG_PPC44x_SIMPLE is not set
+# CONFIG_PPC4xx_GPIO is not set
CONFIG_XILINX_VIRTEX=y
CONFIG_XILINX_VIRTEX_5_FXT=y
# CONFIG_IPIC is not set
# Kernel options
#
# CONFIG_HIGHMEM is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_PREEMPT=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
# CONFIG_NETFILTER_XT_TARGET_MARK is not set
-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
# CONFIG_NETFILTER_XT_MATCH_MAC is not set
# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
# CONFIG_NETFILTER_XT_MATCH_STRING is not set
# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
# CONFIG_NETFILTER_XT_MATCH_TIME is not set
# CONFIG_NETFILTER_XT_MATCH_U32 is not set
-# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+# CONFIG_NF_DEFRAG_IPV4 is not set
# CONFIG_IP_NF_QUEUE is not set
CONFIG_IP_NF_IPTABLES=m
-# CONFIG_IP_NF_MATCH_RECENT is not set
-# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
# CONFIG_IP_NF_MATCH_TTL is not set
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
CONFIG_IP_NF_FILTER=m
# CONFIG_IP_NF_TARGET_REJECT is not set
# CONFIG_IP_NF_TARGET_LOG is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
# CONFIG_MTD is not set
CONFIG_OF_DEVICE=y
-CONFIG_OF_I2C=y
+CONFIG_OF_GPIO=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_XILINX_SYSACE is not set
+CONFIG_XILINX_SYSACE=y
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
#
CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_PCIPS2 is not set
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
-# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+CONFIG_SERIO_XILINX_XPS_PS2=y
# CONFIG_GAMEPORT is not set
#
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
-CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
#
-# I2C system bus drivers (mostly embedded / system-on-chip)
+# Memory mapped GPIO expanders:
#
-# CONFIG_I2C_IBM_IIC is not set
-# CONFIG_I2C_MPC is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
+CONFIG_GPIO_XILINX=y
#
-# External I2C/SMBus adapter drivers
+# I2C GPIO expanders:
#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
#
-# Graphics adapter I2C/DDC channel drivers
+# PCI GPIO expanders:
#
-# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_GPIO_BT8XX is not set
#
-# Other I2C/SMBus bus drivers
+# SPI GPIO expanders:
#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-CONFIG_I2C_DEBUG_CORE=y
-CONFIG_I2C_DEBUG_ALGO=y
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_IBM_GXT4500 is not set
CONFIG_FB_XILINX=y
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=m
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=y
-# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
#
# Kernel hacking
#
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
# CONFIG_PPC_CLOCK is not set
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:11:37 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:12:40 2008
#
# CONFIG_PPC64 is not set
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# Kernel options
#
# CONFIG_HIGHMEM is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_SYSCALL is not set
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
# CONFIG_SCSI_SRP_ATTRS is not set
# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
#
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PPC_SOC=y
CONFIG_USB_OHCI_HCD_PPC_OF=y
# CONFIG_USB_OHCI_LITTLE_ENDIAN is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_MON is not set
#
# USB port drivers
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:12:56 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:10:16 2008
#
# CONFIG_PPC64 is not set
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
-# CONFIG_SCHED_HRTICK is not set
+CONFIG_SCHED_HRTICK=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP=y
CONFIG_SUSPEND=y
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
# SCSI support type (disk, tape, CD-ROM)
#
-# CONFIG_BLK_DEV_SD is not set
+CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_FSL is not set
CONFIG_ATA_SFF=y
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
# CONFIG_E1000E is not set
-# CONFIG_E1000E_ENABLED is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
# CONFIG_NS83820 is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-# CONFIG_GIANFAR is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
# CONFIG_TR is not set
#
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_NOZOMI is not set
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# PC SMBus host controller drivers
+#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
CONFIG_PPC_CLOCK=y
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:12:22 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:11:02 2008
#
# CONFIG_PPC64 is not set
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# Kernel options
#
# CONFIG_HIGHMEM is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_SYSCALL is not set
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
-# CONFIG_SATA_FSL is not set
CONFIG_ATA_SFF=y
# CONFIG_SATA_MV is not set
CONFIG_PATA_MPC52xx=y
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
#
# CONFIG_SOFT_WATCHDOG is not set
# CONFIG_MPC5200_WDT is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
CONFIG_DAB=y
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
#
# LED drivers
#
+# CONFIG_LEDS_PCA955X is not set
#
# LED Triggers
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
+# CONFIG_RTC_DRV_PPC is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:13:19 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:13:16 2008
#
# CONFIG_PPC64 is not set
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
-# CONFIG_SCHED_HRTICK is not set
+CONFIG_SCHED_HRTICK=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
CONFIG_ISA_DMA_API=y
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
# CONFIG_SCSI_SRP_ATTRS is not set
# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=m
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_FSL is not set
CONFIG_ATA_SFF=y
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_ATL2 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
#
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_NOZOMI is not set
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# PC SMBus host controller drivers
+#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
CONFIG_SENSORS_EEPROM=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=m
# CONFIG_USB_OHCI_HCD_PPC_SOC is not set
CONFIG_USB_OHCI_HCD_PPC_OF=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_MON is not set
#
# USB port drivers
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=m
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
+# CONFIG_RTC_DRV_PPC is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=m
CONFIG_FS_MBCACHE=m
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_DNOTIFY is not set
CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
CONFIG_PPC_CLOCK=y
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 07:12:39 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:09:30 2008
#
# CONFIG_PPC64 is not set
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# Kernel options
#
# CONFIG_HIGHMEM is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_SYSCALL is not set
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-
-#
-# Networking
-#
CONFIG_NET=y
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
-# CONFIG_SATA_FSL is not set
CONFIG_ATA_SFF=y
# CONFIG_SATA_MV is not set
CONFIG_PATA_MPC52xx=y
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI is not set
# CONFIG_IWLWIFI_LEDS is not set
#
# Character devices
#
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PPC_SOC=y
CONFIG_USB_OHCI_HCD_PPC_OF=y
# CONFIG_USB_OHCI_LITTLE_ENDIAN is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-CONFIG_USB_MON=y
#
# USB port drivers
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
+# CONFIG_RTC_DRV_PPC is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
#
# MII PHY device drivers
#
-CONFIG_MARVELL_PHY=y
+# CONFIG_MARVELL_PHY is not set
# CONFIG_DAVICOM_PHY is not set
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc6
-# Fri Jan 18 14:19:54 2008
+# Linux kernel version: 2.6.28-rc4
+# Thu Nov 13 02:09:07 2008
#
# CONFIG_PPC64 is not set
# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_MMU=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
-# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_DEFAULT_UIMAGE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
+# CONFIG_GROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
CONFIG_CLASSIC32=y
# CONFIG_PPC_CHRP is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
CONFIG_PPC_MPC52xx=y
-CONFIG_PPC_MPC5200=y
-CONFIG_PPC_MPC5200_BUGFIX=y
CONFIG_PPC_MPC5200_SIMPLE=y
CONFIG_PPC_EFIKA=y
CONFIG_PPC_LITE5200=y
+CONFIG_PPC_MPC5200_BUGFIX=y
+# CONFIG_PPC_MPC5200_GPIO is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
CONFIG_PPC_NATIVE=y
# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_MPIC_WEIRD is not set
# CONFIG_PPC_I8259 is not set
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
-# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_PPC_BESTCOMM=y
CONFIG_PPC_BESTCOMM_ATA=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+# CONFIG_IOMMU_HELPER is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND_UP_POSSIBLE=y
CONFIG_SUSPEND=y
-CONFIG_HIBERNATION_UP_POSSIBLE=y
-# CONFIG_HIBERNATION is not set
+CONFIG_SUSPEND_FREEZER=y
CONFIG_SECCOMP=y
-CONFIG_WANT_DEVICE_TREE=y
-CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
-CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
#
# Advanced setup
#
# Default settings for advanced configuration options are used
#
-CONFIG_HIGHMEM_START=0xfe000000
CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xc0000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Networking
-#
CONFIG_NET=y
#
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
# CONFIG_IP_DCCP is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_OF_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
#
# CONFIG_MTD_UBI is not set
CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_ATA_SFF=y
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
# CONFIG_SATA_MV is not set
# CONFIG_SATA_PROMISE is not set
# CONFIG_SATA_SX4 is not set
# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIL24 is not set
# CONFIG_SATA_SIS is not set
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
# CONFIG_PATA_NS87410 is not set
# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_WINBOND is not set
CONFIG_PATA_PLATFORM=y
# CONFIG_PATA_OF_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
-# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
CONFIG_PHYLIB=y
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
CONFIG_FEC_MPC52xx=y
CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_ATL2 is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
#
# USB Network Adapters
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
#
# Input device support
#
-# CONFIG_INPUT is not set
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
# Hardware I/O ports
#
# Character devices
#
-# CONFIG_VT is not set
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
#
# Serial drivers
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
#
-# I2C Algorithms
+# I2C Hardware Bus support
#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
#
-# I2C Hardware Bus support
+# PC SMBus host controller drivers
#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
# CONFIG_I2C_VOODOO3 is not set
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_M41T00 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
# CONFIG_MPC5200_WDT is not set
# CONFIG_WATCHDOG_RTAS is not set
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
CONFIG_DAB=y
# CONFIG_USB_DABUSB is not set
# Graphics support
#
# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_R128 is not set
+# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=y
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+CONFIG_FB_MACMODES=y
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
#
# Display device support
# CONFIG_DISPLAY_SUPPORT is not set
#
-# Sound
-#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_APPLE is not set
+CONFIG_HID_BELKIN=y
+CONFIG_HID_BRIGHT=y
+CONFIG_HID_CHERRY=y
+# CONFIG_HID_CHICONY is not set
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DELL=y
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
# CONFIG_USB_DEVICE_CLASS is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_PERSIST is not set
# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PPC_SOC=y
CONFIG_USB_OHCI_HCD_PPC_OF=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_LIBUSUAL is not set
#
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-CONFIG_USB_MON=y
#
# USB port drivers
#
-
-#
-# USB Serial Converter support
-#
# CONFIG_USB_SERIAL is not set
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
+# CONFIG_LEDS_CLASS is not set
#
# LED drivers
#
# LED Triggers
#
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGERS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=y
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-# CONFIG_UCC_SLOW is not set
#
# Library routines
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
-# CONFIG_INSTRUMENTATION is not set
+CONFIG_HAVE_LMB=y
#
# Kernel hacking
CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
-CONFIG_FORCED_INLINING=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
# CONFIG_CRYPTO_HMAC is not set
# CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-# CONFIG_CRYPTO_ECB is not set
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_PCBC is not set
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_XTS is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_TEST is not set
-# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
CONFIG_PPC_CLOCK=y
CONFIG_PPC_LIB_RHEAP=y
+# CONFIG_VIRTUALIZATION is not set
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 08:56:44 2008
+# Linux kernel version: 2.6.28-rc4
+# Fri Nov 14 09:54:44 2008
#
# CONFIG_PPC64 is not set
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_XILINX_SYSACE is not set
+CONFIG_XILINX_SYSACE=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
# Hardware I/O ports
#
-# CONFIG_SERIO is not set
+CONFIG_SERIO=m
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+CONFIG_SERIO_XILINX_XPS_PS2=m
# CONFIG_GAMEPORT is not set
#
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_DEBUG_GPIO is not set
# CONFIG_GPIO_SYSFS is not set
+#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_XILINX=y
+
#
# I2C GPIO expanders:
#
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_FB is not set
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_XILINX=m
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:28:58 2008
+# Linux kernel version: 2.6.28-rc4
+# Fri Nov 14 10:06:19 2008
#
# CONFIG_PPC64 is not set
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_XILINX_SYSACE is not set
+CONFIG_XILINX_SYSACE=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
# Hardware I/O ports
#
-# CONFIG_SERIO is not set
+CONFIG_SERIO=m
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+CONFIG_SERIO_XILINX_XPS_PS2=m
# CONFIG_GAMEPORT is not set
#
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_DEBUG_GPIO is not set
# CONFIG_GPIO_SYSFS is not set
+#
+# Memory mapped GPIO expanders:
+#
+CONFIG_GPIO_XILINX=y
+
#
# I2C GPIO expanders:
#
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_XILINX=m
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
unsigned long pstart, unsigned long prot,
int psize, int ssize);
-extern void set_huge_psize(int psize);
extern void add_gpage(unsigned long addr, unsigned long page_size,
unsigned long number_of_pages);
extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
#ifdef __powerpc64__
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */
#define STACK_FRAME_LR_SAVE 2 /* Location of LR in stack frame */
#define STACK_FRAME_REGS_MARKER ASM_CONST(0x7265677368657265)
blr
_GLOBAL(__setup_cpu_460ex)
_GLOBAL(__setup_cpu_460gt)
- b __init_fpu_44x
+ mflr r4
+ bl __init_fpu_44x
+ bl __fixup_440A_mcheck
+ mtlr r4
+ blr
+
_GLOBAL(__setup_cpu_440gx)
_GLOBAL(__setup_cpu_440spe)
b __fixup_440A_mcheck
beq- 1f
ld r1,PACAKSAVE(r13)
1: std r10,0(r1)
- crclr so
std r11,_NIP(r1)
std r12,_MSR(r1)
std r0,GPR0(r1)
std r10,GPR1(r1)
ACCOUNT_CPU_USER_ENTRY(r10, r11)
+ /*
+ * This "crclr so" clears CR0.SO, which is the error indication on
+ * return from this system call. There must be no cmp instruction
+ * between it and the "mfcr r9" below, otherwise if XER.SO is set,
+ * CR0.SO will get set, causing all system calls to appear to fail.
+ */
+ crclr so
std r2,GPR2(r1)
std r3,GPR3(r1)
std r4,GPR4(r1)
* parsing
*/
dn = pci_device_to_OF_node(pdev);
- if (dn)
- return of_irq_map_one(dn, 0, out_irq);
+ if (dn) {
+ rc = of_irq_map_one(dn, 0, out_irq);
+ if (!rc)
+ return rc;
+ }
/* Ok, we don't, time to have fun. Let's start by building up an
* interrupt spec. we assume #interrupt-cells is 1, which is standard
BUG_ON(!c->hotpluggable);
+#ifdef CONFIG_PPC64
if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
cpu_has_feature(CPU_FTR_SMT))
sysdev_remove_file(s, &attr_smt_snooze_delay);
+#endif
/* PMC stuff */
switch (cur_cpu_spec->pmc_type) {
unsigned long __init mmu_mapin_ram(void)
{
- unsigned long v, s;
+ unsigned long v, s, mapped;
phys_addr_t p;
v = KERNELBASE;
s -= LARGE_PAGE_SIZE_4M;
}
- return total_lowmem - s;
+ mapped = total_lowmem - s;
+
+ /* If the size of RAM is not an exact power of two, we may not
+ * have covered RAM in its entirety with 16 and 4 MiB
+ * pages. Consequently, restrict the top end of RAM currently
+ * allocable so that calls to the LMB to allocate PTEs for "tail"
+ * coverage with normal-sized pages (or other reasons) do not
+ * attempt to allocate outside the allowed range.
+ */
+
+ __initial_memory_limit_addr = memstart_addr + mapped;
+
+ return mapped;
}
return err;
}
-void set_huge_psize(int psize)
+static void __init set_huge_psize(int psize)
{
/* Check that it is a page size supported by the hardware and
* that it fits within pagetable limits. */
.priority = 1 /* Must run before sched domains notifier. */
};
+static void mark_reserved_regions_for_nid(int nid)
+{
+ struct pglist_data *node = NODE_DATA(nid);
+ int i;
+
+ for (i = 0; i < lmb.reserved.cnt; i++) {
+ unsigned long physbase = lmb.reserved.region[i].base;
+ unsigned long size = lmb.reserved.region[i].size;
+ unsigned long start_pfn = physbase >> PAGE_SHIFT;
+ unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT);
+ struct node_active_region node_ar;
+ unsigned long node_end_pfn = node->node_start_pfn +
+ node->node_spanned_pages;
+
+ /*
+ * Check to make sure that this lmb.reserved area is
+ * within the bounds of the node that we care about.
+ * Checking the nid of the start and end points is not
+ * sufficient because the reserved area could span the
+ * entire node.
+ */
+ if (end_pfn <= node->node_start_pfn ||
+ start_pfn >= node_end_pfn)
+ continue;
+
+ get_node_active_region(start_pfn, &node_ar);
+ while (start_pfn < end_pfn &&
+ node_ar.start_pfn < node_ar.end_pfn) {
+ unsigned long reserve_size = size;
+ /*
+ * if reserved region extends past active region
+ * then trim size to active region
+ */
+ if (end_pfn > node_ar.end_pfn)
+ reserve_size = (node_ar.end_pfn << PAGE_SHIFT)
+ - (start_pfn << PAGE_SHIFT);
+ dbg("reserve_bootmem %lx %lx nid=%d\n", physbase,
+ reserve_size, node_ar.nid);
+ reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase,
+ reserve_size, BOOTMEM_DEFAULT);
+ /*
+ * if reserved region is contained in the active region
+ * then done.
+ */
+ if (end_pfn <= node_ar.end_pfn)
+ break;
+
+ /*
+ * reserved region extends past the active region
+ * get next active region that contains this
+ * reserved region
+ */
+ start_pfn = node_ar.end_pfn;
+ physbase = start_pfn << PAGE_SHIFT;
+ size = size - reserve_size;
+ get_node_active_region(start_pfn, &node_ar);
+ }
+ }
+}
+
+
void __init do_init_bootmem(void)
{
int nid;
get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
- /* Allocate the node structure node local if possible */
+ /*
+ * Allocate the node structure node local if possible
+ *
+ * Be careful moving this around, as it relies on all
+ * previous nodes' bootmem to be initialized and have
+ * all reserved areas marked.
+ */
NODE_DATA(nid) = careful_allocation(nid,
sizeof(struct pglist_data),
SMP_CACHE_BYTES, end_pfn);
start_pfn, end_pfn);
free_bootmem_with_active_regions(nid, end_pfn);
- }
-
- /* Mark reserved regions */
- for (i = 0; i < lmb.reserved.cnt; i++) {
- unsigned long physbase = lmb.reserved.region[i].base;
- unsigned long size = lmb.reserved.region[i].size;
- unsigned long start_pfn = physbase >> PAGE_SHIFT;
- unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT);
- struct node_active_region node_ar;
-
- get_node_active_region(start_pfn, &node_ar);
- while (start_pfn < end_pfn &&
- node_ar.start_pfn < node_ar.end_pfn) {
- unsigned long reserve_size = size;
- /*
- * if reserved region extends past active region
- * then trim size to active region
- */
- if (end_pfn > node_ar.end_pfn)
- reserve_size = (node_ar.end_pfn << PAGE_SHIFT)
- - (start_pfn << PAGE_SHIFT);
- dbg("reserve_bootmem %lx %lx nid=%d\n", physbase,
- reserve_size, node_ar.nid);
- reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase,
- reserve_size, BOOTMEM_DEFAULT);
- /*
- * if reserved region is contained in the active region
- * then done.
- */
- if (end_pfn <= node_ar.end_pfn)
- break;
-
- /*
- * reserved region extends past the active region
- * get next active region that contains this
- * reserved region
- */
- start_pfn = node_ar.end_pfn;
- physbase = start_pfn << PAGE_SHIFT;
- size = size - reserve_size;
- get_node_active_region(start_pfn, &node_ar);
- }
-
- }
-
- for_each_online_node(nid)
+ /*
+ * Be very careful about moving this around. Future
+ * calls to careful_allocation() depend on this getting
+ * done correctly.
+ */
+ mark_reserved_regions_for_nid(nid);
sparse_memory_present_with_active_regions(nid);
+ }
}
void __init paging_init(void)
struct axon_msic *msic = get_irq_data(irq);
u32 write_offset, msi;
int idx;
+ int retry = 0;
write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
/* write_offset doesn't wrap properly, so we have to mask it */
write_offset &= MSIC_FIFO_SIZE_MASK;
- while (msic->read_offset != write_offset) {
+ while (msic->read_offset != write_offset && retry < 100) {
idx = msic->read_offset / sizeof(__le32);
msi = le32_to_cpu(msic->fifo_virt[idx]);
msi &= 0xFFFF;
pr_debug("axon_msi: woff %x roff %x msi %x\n",
write_offset, msic->read_offset, msi);
+ if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) {
+ generic_handle_irq(msi);
+ msic->fifo_virt[idx] = cpu_to_le32(0xffffffff);
+ } else {
+ /*
+ * Reading the MSIC_WRITE_OFFSET_REG does not
+ * reliably flush the outstanding DMA to the
+ * FIFO buffer. Here we were reading stale
+ * data, so we need to retry.
+ */
+ udelay(1);
+ retry++;
+ pr_debug("axon_msi: invalid irq 0x%x!\n", msi);
+ continue;
+ }
+
+ if (retry) {
+ pr_debug("axon_msi: late irq 0x%x, retry %d\n",
+ msi, retry);
+ retry = 0;
+ }
+
msic->read_offset += MSIC_FIFO_ENTRY_SIZE;
msic->read_offset &= MSIC_FIFO_SIZE_MASK;
+ }
- if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host)
- generic_handle_irq(msi);
- else
- pr_debug("axon_msi: invalid irq 0x%x!\n", msi);
+ if (retry) {
+ printk(KERN_WARNING "axon_msi: irq timed out\n");
+
+ msic->read_offset += MSIC_FIFO_ENTRY_SIZE;
+ msic->read_offset &= MSIC_FIFO_SIZE_MASK;
}
desc->chip->eoi(irq);
dn->full_name);
goto out_free_fifo;
}
+ memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES);
msic->irq_host = irq_alloc_host(dn, IRQ_HOST_MAP_NOMAP,
NR_IRQS, &msic_host_ops, 0);
return cpus_weight(cpu_possible_map);
}
-static void __devinit smp_iic_setup_cpu(int cpu)
+static void __devinit smp_cell_setup_cpu(int cpu)
{
if (cpu != boot_cpuid)
iic_setup_cpu();
+
+ /*
+ * change default DABRX to allow user watchpoints
+ */
+ mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
}
static DEFINE_SPINLOCK(timebase_lock);
.message_pass = smp_iic_message_pass,
.probe = smp_iic_probe,
.kick_cpu = smp_cell_kick_cpu,
- .setup_cpu = smp_iic_setup_cpu,
+ .setup_cpu = smp_cell_setup_cpu,
.cpu_bootable = smp_cell_cpu_bootable,
};
if (offset >= ps_size)
return VM_FAULT_SIGBUS;
+ if (fatal_signal_pending(current))
+ return VM_FAULT_SIGBUS;
+
/*
* Because we release the mmap_sem, the context may be destroyed while
* we're in spu_wait. Grab an extra reference so it isn't destroyed
answer Y or M. Otherwise say N.
config PPC_BESTCOMM_ATA
- tristate "Bestcomm ATA task support"
+ tristate
depends on PPC_BESTCOMM
- default n
help
This option enables the support for the ATA task.
config PPC_BESTCOMM_FEC
- tristate "Bestcomm FEC tasks support"
+ tristate
depends on PPC_BESTCOMM
- default n
help
This option enables the support for the FEC tasks.
config PPC_BESTCOMM_GEN_BD
- tristate "Bestcomm GenBD tasks support"
+ tristate
depends on PPC_BESTCOMM
- default n
help
This option enables the support for the GenBD tasks.
void __init mpic_init(struct mpic *mpic)
{
int i;
+ int cpu;
BUG_ON(mpic->num_sources == 0);
mpic_pasemi_msi_init(mpic);
+ if (mpic->flags & MPIC_PRIMARY)
+ cpu = hard_smp_processor_id();
+ else
+ cpu = 0;
+
for (i = 0; i < mpic->num_sources; i++) {
/* start with vector = source number, and masked */
u32 vecpri = MPIC_VECPRI_MASK | i |
continue;
/* init hw */
mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
- mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
- 1 << hard_smp_processor_id());
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
}
/* Init spurious vector */
}
regs = ioremap(res.start, 32);
- printk(KERN_INFO "Xilinx intc at 0x%08LX mapped to 0x%p\n",
- res.start, regs);
+ printk(KERN_INFO "Xilinx intc at 0x%08llx mapped to 0x%p\n",
+ (unsigned long long) res.start, regs);
/* Setup interrupt controller */
out_be32(regs + XINTC_IER, 0); /* disable all irqs */
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc4
-# Thu Aug 21 19:43:29 2008
+# Linux kernel version: 2.6.28-rc6
+# Thu Nov 27 11:00:49 2008
#
CONFIG_SCHED_MC=y
CONFIG_MMU=y
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_NS=y
+# CONFIG_CGROUP_FREEZER is not set
# CONFIG_CGROUP_DEVICE is not set
# CONFIG_CPUSETS is not set
CONFIG_GROUP_SCHED=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_KPROBES=y
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
CONFIG_KRETPROBES=y
-# CONFIG_HAVE_IOREMAP_PROT is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_PREEMPT_NOTIFIERS=y
CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# Base setup
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y
CONFIG_HAVE_MEMORY_PRESENT=y
-# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
#
# I/O subsystem configuration
CONFIG_IPL_VM=y
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=m
CONFIG_FORCE_MAX_ZONEORDER=9
# CONFIG_PROCESS_DEBUG is not set
# CONFIG_XFRM_STATISTICS is not set
CONFIG_NET_KEY=y
# CONFIG_NET_KEY_MIGRATE is not set
-CONFIG_IUCV=m
+CONFIG_IUCV=y
CONFIG_AFIUCV=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_NF_CONNTRACK_TFTP is not set
# CONFIG_NF_CT_NETLINK is not set
# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
+# CONFIG_NF_DEFRAG_IPV4 is not set
# CONFIG_NF_CONNTRACK_IPV4 is not set
# CONFIG_IP_NF_QUEUE is not set
# CONFIG_IP_NF_IPTABLES is not set
# CONFIG_NET_SCH_HTB is not set
# CONFIG_NET_SCH_HFSC is not set
CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=y
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
CONFIG_NET_ACT_NAT=m
# CONFIG_NET_ACT_PEDIT is not set
# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_SCH_FIFO=y
CONFIG_CAN_VCAN=m
# CONFIG_CAN_DEBUG_DEVICES is not set
# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_PCMCIA is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HAVE_IDE is not set
+# CONFIG_C2PORT is not set
#
# SCSI device support
CONFIG_SCSI_DH_ALUA=m
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
# CONFIG_TR is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
-
-#
-# Sonics Silicon Backplane
-#
+# CONFIG_REGULATOR is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
CONFIG_ACCESSIBILITY=y
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_FRAME_POINTER is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_KPROBES_SANITY_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
CONFIG_SAMPLES=y
# CONFIG_SAMPLE_KOBJECT is not set
# CONFIG_SAMPLE_KPROBES is not set
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_GF128MUL=m
# CONFIG_CRYPTO_NULL is not set
#
# Ciphers
#
-# CONFIG_CRYPTO_AES is not set
+CONFIG_CRYPTO_AES=m
# CONFIG_CRYPTO_ANUBIS is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_BLOWFISH is not set
#
# CONFIG_CRYPTO_DEFLATE is not set
CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_HW=y
CONFIG_ZCRYPT=m
# CONFIG_ZCRYPT_MONOLITHIC is not set
# Library routines
#
CONFIG_BITREVERSE=m
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
- if (mm->context.has_pgste)
- ptep_rcp_copy(ptep);
pte_val(*ptep) = _PAGE_TYPE_EMPTY;
if (mm->context.noexec)
pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY;
psw_t psw;
unsigned long gprs[NUM_GPRS];
unsigned long orig_gpr2;
+ unsigned short svcnr;
unsigned short ilc;
- unsigned short trap;
};
#endif
extern void user_enable_single_step(struct task_struct *);
extern void user_disable_single_step(struct task_struct *);
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
#define user_stack_pointer(regs)((regs)->gprs[15])
static inline long syscall_get_nr(struct task_struct *task,
struct pt_regs *regs)
{
- if (regs->trap != __LC_SVC_OLD_PSW)
- return -1;
- return regs->gprs[2];
+ return regs->svcnr ? regs->svcnr : -1;
}
static inline void syscall_rollback(struct task_struct *task,
unsigned int i, unsigned int n,
unsigned long *args)
{
+ unsigned long mask = -1UL;
+
BUG_ON(i + n > 6);
#ifdef CONFIG_COMPAT
- if (test_tsk_thread_flag(task, TIF_31BIT)) {
- if (i + n == 6)
- args[--n] = (u32) regs->args[0];
- while (n-- > 0)
- args[n] = (u32) regs->gprs[2 + i + n];
- }
+ if (test_tsk_thread_flag(task, TIF_31BIT))
+ mask = 0xffffffff;
#endif
if (i + n == 6)
- args[--n] = regs->args[0];
- memcpy(args, ®s->gprs[2 + i], n * sizeof(args[0]));
+ args[--n] = regs->args[0] & mask;
+ while (n-- > 0)
+ if (i + n > 0)
+ args[n] = regs->gprs[2 + i + n] & mask;
+ if (i == 0)
+ args[0] = regs->orig_gpr2 & mask;
}
static inline void syscall_set_arguments(struct task_struct *task,
BUG_ON(i + n > 6);
if (i + n == 6)
regs->args[0] = args[--n];
- memcpy(®s->gprs[2 + i], args, n * sizeof(args[0]));
+ while (n-- > 0)
+ if (i + n > 0)
+ regs->gprs[2 + i + n] = args[n];
+ if (i == 0)
+ regs->orig_gpr2 = args[0];
}
#endif /* _ASM_SYSCALL_H */
DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc));
- DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap));
+ DEFINE(__PT_SVCNR, offsetof(struct pt_regs, svcnr));
DEFINE(__PT_SIZE, sizeof(struct pt_regs));
BLANK();
DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
return err;
restore_fp_regs(¤t->thread.fp_regs);
- regs->trap = -1; /* disable syscall checks */
+ regs->svcnr = 0; /* disable syscall checks */
return 0;
}
SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 60
SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
.macro CREATE_STACK_FRAME psworg,savearea
s %r15,BASED(.Lc_spsize) # make room for registers & psw
mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack
- la %r12,\psworg
st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
- icm %r12,12,__LC_SVC_ILC
+ icm %r12,3,__LC_SVC_ILC
stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack
- st %r12,SP_ILC(%r15)
+ st %r12,SP_SVCNR(%r15)
mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
la %r12,0
st %r12,__SF_BACKCHAIN(%r15) # clear back chain
#endif
sysc_do_svc:
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- sla %r7,2 # *4 and test for svc 0
+ ltr %r7,%r7 # test for svc 0
bnz BASED(sysc_nr_ok) # svc number > 0
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
bnl BASED(sysc_nr_ok)
lr %r7,%r1 # copy svc number to %r7
- sla %r7,2 # *4
sysc_nr_ok:
mvc SP_ARGS(4,%r15),SP_R7(%r15)
sysc_do_restart:
+ sth %r7,SP_SVCNR(%r15)
+ sll %r7,2 # svc number *4
l %r8,BASED(.Lsysc_table)
tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
l %r8,0(%r7,%r8) # get system call addr.
sysc_restart:
ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
l %r7,SP_R2(%r15) # load new svc number
- sla %r7,2
mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
lm %r2,%r6,SP_R2(%r15) # load svc arguments
b BASED(sysc_do_restart) # restart svc
#
sysc_singlestep:
ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
- mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check
+ mvi SP_SVCNR(%r15),0xff # set trap indication to pgm check
+ mvi SP_SVCNR+1(%r15),0xff
la %r2,SP_PTREGS(%r15) # address of register-save area
l %r1,BASED(.Lhandle_per) # load adr. of per handler
la %r14,BASED(sysc_return) # load adr. of system return
bnl BASED(sysc_tracenogo)
l %r8,BASED(.Lsysc_table)
lr %r7,%r2
- sll %r7,2 # *4
+ sll %r7,2 # svc number *4
l %r8,0(%r7,%r8)
sysc_tracego:
lm %r3,%r6,SP_R3(%r15)
# per was called from kernel, must be kprobes
#
kernel_per:
- mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check
+ mvi SP_SVCNR(%r15),0xff # set trap indication to pgm check
+ mvi SP_SVCNR+1(%r15),0xff
la %r2,SP_PTREGS(%r15) # address of register-save area
l %r1,BASED(.Lhandle_per) # load adr. of per handler
la %r14,BASED(sysc_restore)# load adr. of system return
SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120
SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
.macro CREATE_STACK_FRAME psworg,savearea
aghi %r15,-SP_SIZE # make room for registers & psw
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
- la %r12,\psworg
stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
- icm %r12,12,__LC_SVC_ILC
+ icm %r12,3,__LC_SVC_ILC
stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack
- st %r12,SP_ILC(%r15)
+ st %r12,SP_SVCNR(%r15)
mvc SP_R12(32,%r15),\savearea # move %r12-%r15 to stack
la %r12,0
stg %r12,__SF_BACKCHAIN(%r15)
#endif
sysc_do_svc:
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- slag %r7,%r7,2 # *4 and test for svc 0
+ ltgr %r7,%r7 # test for svc 0
jnz sysc_nr_ok
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
jnl sysc_nr_ok
lgfr %r7,%r1 # clear high word in r1
- slag %r7,%r7,2 # svc 0: system call number in %r1
sysc_nr_ok:
mvc SP_ARGS(8,%r15),SP_R7(%r15)
sysc_do_restart:
+ sth %r7,SP_SVCNR(%r15)
+ sllg %r7,%r7,2 # svc number * 4
larl %r10,sys_call_table
#ifdef CONFIG_COMPAT
tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ?
sysc_restart:
ni __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
lg %r7,SP_R2(%r15) # load new svc number
- slag %r7,%r7,2 # *4
mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
lmg %r2,%r6,SP_R2(%r15) # load svc arguments
j sysc_do_restart # restart svc
# _TIF_SINGLE_STEP is set, call do_single_step
#
sysc_singlestep:
- ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
- lhi %r0,__LC_PGM_OLD_PSW
- sth %r0,SP_TRAP(%r15) # set trap indication to pgm check
+ ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
+ xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
la %r2,SP_PTREGS(%r15) # address of register-save area
larl %r14,sysc_return # load adr. of system return
jg do_single_step # branch to do_sigtrap
lghi %r0,NR_syscalls
clgr %r0,%r2
jnh sysc_tracenogo
- slag %r7,%r2,2 # *4
+ sllg %r7,%r2,2 # svc number *4
lgf %r8,0(%r7,%r10)
sysc_tracego:
lmg %r3,%r6,SP_R3(%r15)
# per was called from kernel, must be kprobes
#
kernel_per:
- lhi %r0,__LC_PGM_OLD_PSW
- sth %r0,SP_TRAP(%r15) # set trap indication to pgm check
+ xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
la %r2,SP_PTREGS(%r15) # address of register-save area
larl %r14,sysc_restore # load adr. of system ret, no work
jg do_single_step # branch to do_single_step
/*
* Initial thread structure.
*
- * We need to make sure that this is 8192-byte aligned due to the
+ * We need to make sure that this is THREAD_SIZE aligned due to the
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry..
*/
* debugger stored an invalid system call number. Skip
* the system call and the system call restart handling.
*/
- regs->trap = -1;
+ regs->svcnr = 0;
ret = -1;
}
current->thread.fp_regs.fpc &= FPC_VALID_MASK;
restore_fp_regs(¤t->thread.fp_regs);
- regs->trap = -1; /* disable syscall checks */
+ regs->svcnr = 0; /* disable syscall checks */
return 0;
}
oldset = ¤t->blocked;
/* Are we from a system call? */
- if (regs->trap == __LC_SVC_OLD_PSW) {
+ if (regs->svcnr) {
continue_addr = regs->psw.addr;
restart_addr = continue_addr - regs->ilc;
retval = regs->gprs[2];
case -ERESTART_RESTARTBLOCK:
regs->gprs[2] = -EINTR;
}
- regs->trap = -1; /* Don't deal with this again. */
+ regs->svcnr = 0; /* Don't deal with this again. */
}
/* Get signal to deliver. When running under ptrace, at this point
static ext_int_info_t ext_int_info_cc;
static ext_int_info_t ext_int_etr_cc;
-static u64 jiffies_timer_cc;
+static u64 sched_clock_base_cc;
static DEFINE_PER_CPU(struct clock_event_device, comparators);
*/
unsigned long long sched_clock(void)
{
- return ((get_clock_xt() - jiffies_timer_cc) * 125) >> 9;
+ return ((get_clock_xt() - sched_clock_base_cc) * 125) >> 9;
}
/*
*/
void __init time_init(void)
{
- u64 init_timer_cc;
-
- init_timer_cc = reset_tod_clock();
- jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY;
+ sched_clock_base_cc = reset_tod_clock();
/* set xtime */
- tod_to_timeval(init_timer_cc - TOD_UNIX_EPOCH, &xtime);
+ tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &xtime);
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
delta = -delta;
adjust.offset = -ticks * (1000000 / HZ);
}
- jiffies_timer_cc += delta;
+ sched_clock_base_cc += delta;
if (adjust.offset != 0) {
printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
adjust.offset);
* Written by Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
+#include <asm/thread_info.h>
#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h>
}
_edata = .; /* End of data section */
- . = ALIGN(2 * PAGE_SIZE); /* init_task */
+ . = ALIGN(THREAD_SIZE); /* init_task */
.data.init_task : {
*(.data.init_task)
}
};
extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#define force_successful_syscall_return() \
do { current_thread_info()->syscall_noerror = 1; \
} while (0)
unsigned int fsr_storage;
-void __init cpu_probe(void)
+void __cpuinit cpu_probe(void)
{
int psr_impl, psr_vers, fpu_vers;
int i, psr;
.align 4
/* The Sparc trap table, bootloader gives us control at _start. */
- .text
+ .section .text.head,"ax"
.globl start, _stext, _start, __stext
.globl trapbase
_start: /* danger danger */
#include "irq.h"
-volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,};
+volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
unsigned char boot_cpu_id = 0;
unsigned char boot_cpu_id4 = 0; /* boot_cpu_id << 2 */
panic("SMP bolixed\n");
}
-struct linux_prom_registers smp_penguin_ctable __initdata = { 0 };
+struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 };
void smp_send_reschedule(int cpu)
{
"i" (ASI_M_CTL));
}
-void __init smp4d_callin(void)
+void __cpuinit smp4d_callin(void)
{
int cpuid = hard_smp4d_processor_id();
extern spinlock_t sun4d_imsk_lock;
extern unsigned int lvl14_resolution;
-static void __init smp_setup_percpu_timer(void)
+static void __cpuinit smp_setup_percpu_timer(void)
{
int cpu = hard_smp4d_processor_id();
extern unsigned int lvl14_resolution;
-static void __init smp_setup_percpu_timer(void)
+static void __cpuinit smp_setup_percpu_timer(void)
{
int cpu = smp_processor_id();
.globl sun4m_cpu_startup, __smp4m_processor_id
.globl sun4d_cpu_startup, __smp4d_processor_id
- __INIT
+ __CPUINIT
.align 4
/* When we start up a cpu for the first time it enters this routine.
/* CPUID in bootbus can be found at PA 0xff0140000 */
#define SUN4D_BOOTBUS_CPUID 0xf0140000
- __INIT
+ __CPUINIT
.align 4
sun4d_cpu_startup:
.text 0xf0004000 :
{
_text = .;
+ *(.text.head)
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
/* Paging initialization on the Sparc Reference MMU. */
extern void sparc_context_init(int);
-void (*poke_srmmu)(void) __initdata = NULL;
+void (*poke_srmmu)(void) __cpuinitdata = NULL;
extern unsigned long bootmem_init(unsigned long *pages_avail);
(int)vac_cache_size, (int)vac_line_size);
}
-static void __init poke_hypersparc(void)
+static void __cpuinit poke_hypersparc(void)
{
volatile unsigned long clear;
unsigned long mreg = srmmu_get_mmureg();
hypersparc_setup_blockops();
}
-static void __init poke_cypress(void)
+static void __cpuinit poke_cypress(void)
{
unsigned long mreg = srmmu_get_mmureg();
unsigned long faddr, tagval;
init_cypress_common();
}
-static void __init poke_swift(void)
+static void __cpuinit poke_swift(void)
{
unsigned long mreg;
}
-static void __init poke_turbosparc(void)
+static void __cpuinit poke_turbosparc(void)
{
unsigned long mreg = srmmu_get_mmureg();
unsigned long ccreg;
poke_srmmu = poke_turbosparc;
}
-static void __init poke_tsunami(void)
+static void __cpuinit poke_tsunami(void)
{
unsigned long mreg = srmmu_get_mmureg();
tsunami_setup_blockops();
}
-static void __init poke_viking(void)
+static void __cpuinit poke_viking(void)
{
unsigned long mreg = srmmu_get_mmureg();
static int smp_catch;
return kern_base + (val - KERNBASE);
}
-static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
+static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
{
extern unsigned long sparc64_ttable_tl0;
extern unsigned long kern_locked_tte_data;
*/
static struct thread_info *cpu_new_thread = NULL;
-static int __devinit smp_boot_one_cpu(unsigned int cpu)
+static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
{
struct trap_per_cpu *tb = &trap_block[cpu];
unsigned long entry =
return nid;
}
-static void add_node_ranges(void)
+static void __init add_node_ranges(void)
{
int i;
{
u8 pending;
asm volatile("int $0x16; setnz %0"
- : "=rm" (pending)
+ : "=qm" (pending)
: "a" (0x0100));
return pending;
}
#ifndef _ASM_X86_DS_H
#define _ASM_X86_DS_H
-#ifdef CONFIG_X86_DS
#include <linux/types.h>
#include <linux/init.h>
+#ifdef CONFIG_X86_DS
+
struct task_struct;
/*
#else /* CONFIG_X86_DS */
-#define ds_init_intel(config) do {} while (0)
+struct cpuinfo_x86;
+static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {}
#endif /* CONFIG_X86_DS */
#endif /* _ASM_X86_DS_H */
*/
#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
-#if defined(CONFIG_GART_IOMMU) || defined(CONFIG_CALGARY_IOMMU)
-
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
-#else
-/* No IOMMU */
-
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME) (0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME) (0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
-
-#endif
-
#endif /* __KERNEL__ */
#endif /* _ASM_X86_PCI_64_H */
extern int do_set_thread_area(struct task_struct *p, int idx,
struct user_desc __user *info, int can_allocate);
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
#endif /* __KERNEL__ */
#endif /* !__ASSEMBLY__ */
obj-y += process.o
obj-y += i387.o xsave.o
obj-y += ptrace.o
-obj-y += ds.o
+obj-$(CONFIG_X86_DS) += ds.o
obj-$(CONFIG_X86_32) += tls.o
obj-$(CONFIG_IA32_EMULATION) += tls.o
obj-y += step.o
}
}
-void enable_IR_x2apic(void)
+void __init enable_IR_x2apic(void)
{
#ifdef CONFIG_INTR_REMAP
int ret;
u32 i = 0;
if (cpu_family == CPU_HW_PSTATE) {
- rdmsr(MSR_PSTATE_STATUS, lo, hi);
- i = lo & HW_PSTATE_MASK;
- data->currpstate = i;
+ if (data->currpstate == HW_PSTATE_INVALID) {
+ /* read (initial) hw pstate if not yet set */
+ rdmsr(MSR_PSTATE_STATUS, lo, hi);
+ i = lo & HW_PSTATE_MASK;
+
+ /*
+ * a workaround for family 11h erratum 311 might cause
+ * an "out-of-range Pstate if the core is in Pstate-0
+ */
+ if (i >= data->numps)
+ data->currpstate = HW_PSTATE_0;
+ else
+ data->currpstate = i;
+ }
return 0;
}
do {
}
data->cpu = pol->cpu;
+ data->currpstate = HW_PSTATE_INVALID;
if (powernow_k8_cpu_init_acpi(data)) {
/*
* http://www.gnu.org/licenses/gpl.html
*/
+
+enum pstate {
+ HW_PSTATE_INVALID = 0xff,
+ HW_PSTATE_0 = 0,
+ HW_PSTATE_1 = 1,
+ HW_PSTATE_2 = 2,
+ HW_PSTATE_3 = 3,
+ HW_PSTATE_4 = 4,
+ HW_PSTATE_5 = 5,
+ HW_PSTATE_6 = 6,
+ HW_PSTATE_7 = 7,
+};
+
struct powernow_k8_data {
unsigned int cpu;
u32 exttype; /* extended interface = 1 */
/* keep track of the current fid / vid or pstate */
- u32 currvid, currfid, currpstate;
+ u32 currvid;
+ u32 currfid;
+ enum pstate currpstate;
/* the powernow_table includes all frequency and vid/fid pairings:
* fid are the lower 8 bits of the index, vid are the upper 8 bits.
*/
-#ifdef CONFIG_X86_DS
-
#include <asm/ds.h>
#include <linux/errno.h>
static inline struct ds_context *ds_get_context(struct task_struct *task)
{
struct ds_context *context;
+ unsigned long irq;
- spin_lock(&ds_lock);
+ spin_lock_irqsave(&ds_lock, irq);
context = (task ? task->thread.ds_ctx : this_system_context);
if (context)
context->count++;
- spin_unlock(&ds_lock);
+ spin_unlock_irqrestore(&ds_lock, irq);
return context;
}
/*
* Same as ds_get_context, but allocates the context and it's DS
* structure, if necessary; returns NULL; if out of memory.
- *
- * pre: requires ds_lock to be held
*/
static inline struct ds_context *ds_alloc_context(struct task_struct *task)
{
struct ds_context **p_context =
(task ? &task->thread.ds_ctx : &this_system_context);
struct ds_context *context = *p_context;
+ unsigned long irq;
if (!context) {
- spin_unlock(&ds_lock);
-
context = kzalloc(sizeof(*context), GFP_KERNEL);
-
- if (!context) {
- spin_lock(&ds_lock);
+ if (!context)
return NULL;
- }
context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL);
if (!context->ds) {
kfree(context);
- spin_lock(&ds_lock);
return NULL;
}
- spin_lock(&ds_lock);
- /*
- * Check for race - another CPU could have allocated
- * it meanwhile:
- */
+ spin_lock_irqsave(&ds_lock, irq);
+
if (*p_context) {
kfree(context->ds);
kfree(context);
- return *p_context;
- }
- *p_context = context;
+ context = *p_context;
+ } else {
+ *p_context = context;
- context->this = p_context;
- context->task = task;
+ context->this = p_context;
+ context->task = task;
- if (task)
- set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
+ if (task)
+ set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
- if (!task || (task == current))
- wrmsr(MSR_IA32_DS_AREA, (unsigned long)context->ds, 0);
-
- get_tracer(task);
+ if (!task || (task == current))
+ wrmsrl(MSR_IA32_DS_AREA,
+ (unsigned long)context->ds);
+ }
+ spin_unlock_irqrestore(&ds_lock, irq);
}
context->count++;
*/
static inline void ds_put_context(struct ds_context *context)
{
+ unsigned long irq;
+
if (!context)
return;
- spin_lock(&ds_lock);
+ spin_lock_irqsave(&ds_lock, irq);
if (--context->count)
goto out;
kfree(context->ds);
kfree(context);
out:
- spin_unlock(&ds_lock);
+ spin_unlock_irqrestore(&ds_lock, irq);
}
struct ds_context *context;
unsigned long buffer, adj;
const unsigned long alignment = (1 << 3);
+ unsigned long irq;
int error = 0;
if (!ds_cfg.sizeof_ds)
return -EOPNOTSUPP;
- spin_lock(&ds_lock);
-
- error = -ENOMEM;
context = ds_alloc_context(task);
if (!context)
- goto out_unlock;
+ return -ENOMEM;
+
+ spin_lock_irqsave(&ds_lock, irq);
error = -EPERM;
if (!check_tracer(task))
goto out_unlock;
+ get_tracer(task);
+
error = -EALREADY;
if (context->owner[qual] == current)
- goto out_unlock;
+ goto out_put_tracer;
error = -EPERM;
if (context->owner[qual] != NULL)
- goto out_unlock;
+ goto out_put_tracer;
context->owner[qual] = current;
- spin_unlock(&ds_lock);
+ spin_unlock_irqrestore(&ds_lock, irq);
error = -ENOMEM;
out_release:
context->owner[qual] = NULL;
ds_put_context(context);
+ put_tracer(task);
+ return error;
+
+ out_put_tracer:
+ spin_unlock_irqrestore(&ds_lock, irq);
+ ds_put_context(context);
+ put_tracer(task);
return error;
out_unlock:
- spin_unlock(&ds_lock);
+ spin_unlock_irqrestore(&ds_lock, irq);
ds_put_context(context);
return error;
}
.sizeof_ds = sizeof(long) * 12,
.sizeof_field = sizeof(long),
.sizeof_rec[ds_bts] = sizeof(long) * 3,
+#ifdef __i386__
.sizeof_rec[ds_pebs] = sizeof(long) * 10
+#else
+ .sizeof_rec[ds_pebs] = sizeof(long) * 18
+#endif
};
static const struct ds_configuration ds_cfg_64 = {
.sizeof_ds = 8 * 12,
.sizeof_field = 8,
.sizeof_rec[ds_bts] = 8 * 3,
+#ifdef __i386__
.sizeof_rec[ds_pebs] = 8 * 10
+#else
+ .sizeof_rec[ds_pebs] = 8 * 18
+#endif
};
static inline void
while (leftovers--)
ds_put_context(context);
}
-#endif /* CONFIG_X86_DS */
stts();
}
-void __init init_thread_xstate(void)
+void __cpuinit init_thread_xstate(void)
{
if (!HAVE_HWFP) {
xstate_size = sizeof(struct i387_soft_struct);
int __init probe_nr_irqs(void)
{
- int idx;
- int nr = 0;
-#ifndef CONFIG_XEN
- int nr_min = 32;
-#else
- int nr_min = NR_IRQS;
-#endif
-
- for (idx = 0; idx < nr_ioapics; idx++)
- nr += io_apic_get_redir_entries(idx) + 1;
-
- /* double it for hotplug and msi and nmi */
- nr <<= 1;
-
- /* something wrong ? */
- if (nr < nr_min)
- nr = nr_min;
- if (WARN_ON(nr > NR_IRQS))
- nr = NR_IRQS;
-
- return nr;
+ return NR_IRQS;
}
/* --------------------------------------------------------------------------
void __init setup_ioapic_dest(void)
{
int pin, ioapic, irq, irq_entry;
+ struct irq_desc *desc;
struct irq_cfg *cfg;
+ cpumask_t mask;
if (skip_ioapic_setup == 1)
return;
* cpu is online.
*/
cfg = irq_cfg(irq);
- if (!cfg->vector)
+ if (!cfg->vector) {
setup_IO_APIC_irq(ioapic, pin, irq,
irq_trigger(irq_entry),
irq_polarity(irq_entry));
+ continue;
+
+ }
+
+ /*
+ * Honour affinities which have been set in early boot
+ */
+ desc = irq_to_desc(irq);
+ if (desc->status &
+ (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
+ mask = desc->affinity;
+ else
+ mask = TARGET_CPUS;
+
#ifdef CONFIG_INTR_REMAP
- else if (intr_remapping_enabled)
- set_ir_ioapic_affinity_irq(irq, TARGET_CPUS);
-#endif
+ if (intr_remapping_enabled)
+ set_ir_ioapic_affinity_irq(irq, mask);
else
- set_ioapic_affinity_irq(irq, TARGET_CPUS);
+#endif
+ set_ioapic_affinity_irq(irq, mask);
}
}
}
#ifdef CONFIG_X86_LOCAL_APIC
-static void __devinit kvm_setup_secondary_clock(void)
+static void __cpuinit kvm_setup_secondary_clock(void)
{
/*
* Now that the first cpu already had this clocksource initialized,
++p;
if (*p == '\0')
break;
- bridge = simple_strtol(p, &endp, 0);
+ bridge = simple_strtoul(p, &endp, 0);
if (p == endp)
break;
/*
* Enable and initialize the xsave feature.
*/
-void __init xsave_cntxt_init(void)
+void __ref xsave_cntxt_init(void)
{
unsigned int eax, ebx, ecx, edx;
int i;
if (!reset_value) {
- reset_value = kmalloc(sizeof(unsigned) * num_counters,
+ reset_value = kmalloc(sizeof(reset_value[0]) * num_counters,
GFP_ATOMIC);
if (!reset_value)
return;
pci_siemens_interrupt_controller);
/*
- * Regular PCI devices have 256 bytes, but AMD Family 10h Opteron ext config
- * have 4096 bytes. Even if the device is capable, that doesn't mean we can
- * access it. Maybe we don't have a way to generate extended config space
- * accesses. So check it
+ * Regular PCI devices have 256 bytes, but AMD Family 10h/11h CPUs have
+ * 4096 bytes configuration space for each function of their processor
+ * configuration space.
*/
-static void fam10h_pci_cfg_space_size(struct pci_dev *dev)
+static void amd_cpu_pci_cfg_space_size(struct pci_dev *dev)
{
dev->cfg_size = pci_cfg_space_size_ext(dev);
}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1200, fam10h_pci_cfg_space_size);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, fam10h_pci_cfg_space_size);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, fam10h_pci_cfg_space_size);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, fam10h_pci_cfg_space_size);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, fam10h_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1200, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1300, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1301, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1302, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1303, amd_cpu_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1304, amd_cpu_pci_cfg_space_size);
/*
* SB600: Disable BAR1 on device 14.0 to avoid HPET resources from
* For 64-bit, we must skip the Xen hole in the middle of the address
* space, just after the big x86-64 virtual hole.
*/
-static int xen_pgd_walk(struct mm_struct *mm,
- int (*func)(struct mm_struct *mm, struct page *,
- enum pt_level),
- unsigned long limit)
+static int __xen_pgd_walk(struct mm_struct *mm, pgd_t *pgd,
+ int (*func)(struct mm_struct *mm, struct page *,
+ enum pt_level),
+ unsigned long limit)
{
- pgd_t *pgd = mm->pgd;
int flush = 0;
unsigned hole_low, hole_high;
unsigned pgdidx_limit, pudidx_limit, pmdidx_limit;
return flush;
}
+static int xen_pgd_walk(struct mm_struct *mm,
+ int (*func)(struct mm_struct *mm, struct page *,
+ enum pt_level),
+ unsigned long limit)
+{
+ return __xen_pgd_walk(mm, mm->pgd, func, limit);
+}
+
/* If we're using split pte locks, then take the page's lock and
return a pointer to it. Otherwise return NULL. */
static spinlock_t *xen_pte_lock(struct page *page, struct mm_struct *mm)
xen_mc_batch();
- if (xen_pgd_walk(mm, xen_pin_page, USER_LIMIT)) {
+ if (__xen_pgd_walk(mm, pgd, xen_pin_page, USER_LIMIT)) {
/* re-enable interrupts for flushing */
xen_mc_issue(0);
PT_PMD);
#endif
- xen_pgd_walk(mm, xen_unpin_page, USER_LIMIT);
+ __xen_pgd_walk(mm, pgd, xen_unpin_page, USER_LIMIT);
xen_mc_issue(0);
}
alternatives_smp_switch(0);
}
-static void xen_play_dead(void)
+static void __cpuinit xen_play_dead(void) /* used only with CPU_HOTPLUG */
{
play_dead_common();
HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
void xen_mark_init_mm_pinned(void);
-void __init xen_setup_vcpu_info_placement(void);
+void xen_setup_vcpu_info_placement(void);
#ifdef CONFIG_SMP
void xen_smp_init(void);
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
val->intval = battery->current_now * 1000;
+ /* if power units are mW, convert to mA by
+ dividing by current voltage (mV/1000) */
+ if (!battery->power_unit) {
+ if (battery->voltage_now) {
+ val->intval /= battery->voltage_now;
+ val->intval *= 1000;
+ } else
+ val->intval = -1;
+ }
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
acpi_dmi_osi_linux(1, d); /* enable */
return 0;
}
-static int __init dmi_disable_osi_linux(const struct dmi_system_id *d)
-{
- acpi_dmi_osi_linux(0, d); /* disable */
- return 0;
-}
-static int __init dmi_unknown_osi_linux(const struct dmi_system_id *d)
-{
- acpi_dmi_osi_linux(-1, d); /* unknown */
- return 0;
-}
static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
{
printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
return 0;
}
-/*
- * Most BIOS that invoke OSI(Linux) do nothing with it.
- * But some cause Linux to break.
- * Only a couple use it to make Linux run better.
- *
- * Thus, Linux should continue to disable OSI(Linux) by default,
- * should continue to discourage BIOS writers from using it, and
- * should whitelist the few existing systems that require it.
- *
- * If it appears clear a vendor isn't using OSI(Linux)
- * for anything constructive, blacklist them by name to disable
- * unnecessary dmesg warnings on all of their products.
- */
-
static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
- /*
- * Disable OSI(Linux) warnings on all "Acer, inc."
- *
- * _OSI(Linux) disables the latest Windows BIOS code:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"),
- * _OSI(Linux) effect unknown:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"),
- */
- /*
- * note that dmi_check_system() uses strstr()
- * to match sub-strings rather than !strcmp(),
- * so "Acer" below matches "Acer, inc." above.
- */
- /*
- * Disable OSI(Linux) warnings on all "Acer"
- *
- * _OSI(Linux) effect unknown:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"),
- *
- * _OSI(Linux) is a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Acer",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "Apple Computer, Inc."
- * Disable OSI(Linux) warnings on all "Apple Inc."
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
- * _OSI(Linux) effect unknown:
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Apple",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "BenQ"
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Joybook S31"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "BenQ",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "BenQ"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "Clevo Co."
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "M570RU"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Clevo",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "COMPAL"
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_BOARD_NAME, "HEL8X"),
- * _OSI(Linux) unknown effect:
- * DMI_MATCH(DMI_BOARD_NAME, "IFL91"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Compal",
- .matches = {
- DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
- },
- },
- { /* OSI(Linux) touches USB, unknown side-effect */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell Dimension 5150",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM051"),
- },
- },
- { /* OSI(Linux) is a NOP */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell i1501",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell Latitude D830",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell OptiPlex GX620",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"),
- },
- },
- { /* OSI(Linux) causes some USB initialization to not run */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell OptiPlex 755",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 755"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PE 1900",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"),
- },
- },
- { /* OSI(Linux) is a NOP */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PE 1950",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"),
- },
- },
- { /* OSI(Linux) is a NOP */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell PE R200",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R200"),
- },
- },
- { /* OSI(Linux) touches USB */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell PR 390",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"),
- },
- },
- { /* OSI(Linux) touches USB */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PR 390",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 690"),
- },
- },
- { /* OSI(Linux) unknown - ASL looks benign, but may effect dock/SMM */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PR M4300",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Precision M4300"),
- },
- },
- { /* OSI(Linux) is a NOP */
- .callback = dmi_disable_osi_linux,
- .ident = "Dell Vostro 1000",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1000"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dell PE SC440",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"),
- },
- },
- { /* OSI(Linux) effect unknown */
- .callback = dmi_unknown_osi_linux,
- .ident = "Dialogue Flybook V5",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dialogue Technology Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Flybook V5"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "FUJITSU SIEMENS"
- *
- * _OSI(Linux) disables latest Windows BIOS code:
- * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2510"),
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1536"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1556"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 1546"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
- * _OSI(Linux) unknown effect:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo M1425"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo Si 1520"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Fujitsu Siemens",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- },
- },
{
.callback = dmi_disable_osi_vista,
.ident = "Fujitsu Siemens",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
},
},
+
/*
- * Disable OSI(Linux) warnings on all "Hewlett-Packard"
- *
- * _OSI(Linux) confirmed to be a NOP:
- * .ident = "HP Pavilion tx 1000"
- * DMI_MATCH(DMI_BOARD_NAME, "30BF"),
- * .ident = "HP Pavilion dv2000"
- * DMI_MATCH(DMI_BOARD_NAME, "30B5"),
- * .ident = "HP Pavilion dv5000",
- * DMI_MATCH(DMI_BOARD_NAME, "30A7"),
- * .ident = "HP Pavilion dv6300 30BC",
- * DMI_MATCH(DMI_BOARD_NAME, "30BC"),
- * .ident = "HP Pavilion dv6000",
- * DMI_MATCH(DMI_BOARD_NAME, "30B7"),
- * DMI_MATCH(DMI_BOARD_NAME, "30B8"),
- * .ident = "HP Pavilion dv9000",
- * DMI_MATCH(DMI_BOARD_NAME, "30B9"),
- * .ident = "HP Pavilion dv9500",
- * DMI_MATCH(DMI_BOARD_NAME, "30CB"),
- * .ident = "HP/Compaq Presario C500",
- * DMI_MATCH(DMI_BOARD_NAME, "30C6"),
- * .ident = "HP/Compaq Presario F500",
- * DMI_MATCH(DMI_BOARD_NAME, "30D3"),
- * _OSI(Linux) unknown effect:
- * .ident = "HP Pavilion dv6500",
- * DMI_MATCH(DMI_BOARD_NAME, "30D0"),
+ * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
+ * Linux ignores it, except for the machines enumerated below.
*/
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Hewlett-Packard",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- },
- },
+
/*
* Lenovo has a mix of systems OSI(Linux) situations
* and thus we can not wildcard the vendor.
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
},
},
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Lenovo 3000 V100",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"),
- },
- },
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Lenovo 3000 N100",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "LG Electronics"
- *
- * _OSI(Linux) confirmed to be a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"),
- * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
- *
- * unknown:
- * DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"),
- * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "LG",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
- },
- },
- /* NEC - OSI(Linux) effect unknown */
- {
- .callback = dmi_unknown_osi_linux,
- .ident = "NEC VERSA M360",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "NEC Computers SAS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "NEC VERSA M360"),
- },
- },
- /* Panasonic */
- {
- .callback = dmi_unknown_osi_linux,
- .ident = "Panasonic",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
- /* Toughbook CF-52 */
- DMI_MATCH(DMI_PRODUCT_NAME, "CF-52CCABVBG"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "Samsung Electronics"
- *
- * OSI(Linux) disables PNP0C32 and other BIOS code for Windows:
- * DMI_MATCH(DMI_PRODUCT_NAME, "R40P/R41P"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "R59P/R60P/R61P"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Samsung",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "Sony Corporation"
- *
- * _OSI(Linux) is a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NR11S_S"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ38GP_C"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ650N"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-TZ21MN_N"),
- * _OSI(Linux) unknown effect:
- * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Sony",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- },
- },
- /*
- * Disable OSI(Linux) warnings on all "TOSHIBA"
- *
- * _OSI(Linux) breaks sound (bugzilla 7787):
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P100"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P105"),
- * _OSI(Linux) is a NOP:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A100"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A210"),
- * _OSI(Linux) unknown effect:
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A135"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A200"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P205"),
- * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U305"),
- */
- {
- .callback = dmi_disable_osi_linux,
- .ident = "Toshiba",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- },
- },
{}
};
goto unlock;
err:
/* false interrupt, state didn't change */
- ++ec->curr->irq_count;
+ if (in_interrupt())
+ ++ec->curr->irq_count;
unlock:
spin_unlock_irqrestore(&ec->curr_lock, flags);
}
#include <linux/interrupt.h>
#include <linux/kmod.h>
#include <linux/delay.h>
-#include <linux/dmi.h>
#include <linux/workqueue.h>
#include <linux/nmi.h>
#include <linux/acpi.h>
static char osi_additional_string[OSI_STRING_LENGTH_MAX];
/*
- * "Ode to _OSI(Linux)"
+ * The story of _OSI(Linux)
*
- * osi_linux -- Control response to BIOS _OSI(Linux) query.
+ * From pre-history through Linux-2.6.22,
+ * Linux responded TRUE upon a BIOS OSI(Linux) query.
*
- * As Linux evolves, the features that it supports change.
- * So an OSI string such as "Linux" is not specific enough
- * to be useful across multiple versions of Linux. It
- * doesn't identify any particular feature, interface,
- * or even any particular version of Linux...
+ * Unfortunately, reference BIOS writers got wind of this
+ * and put OSI(Linux) in their example code, quickly exposing
+ * this string as ill-conceived and opening the door to
+ * an un-bounded number of BIOS incompatibilities.
*
- * Unfortunately, Linux-2.6.22 and earlier responded "yes"
- * to a BIOS _OSI(Linux) query. When
- * a reference mobile BIOS started using it, its use
- * started to spread to many vendor platforms.
- * As it is not supportable, we need to halt that spread.
+ * For example, OSI(Linux) was used on resume to re-POST a
+ * video card on one system, because Linux at that time
+ * could not do a speedy restore in its native driver.
+ * But then upon gaining quick native restore capability,
+ * Linux has no way to tell the BIOS to skip the time-consuming
+ * POST -- putting Linux at a permanent performance disadvantage.
+ * On another system, the BIOS writer used OSI(Linux)
+ * to infer native OS support for IPMI! On other systems,
+ * OSI(Linux) simply got in the way of Linux claiming to
+ * be compatible with other operating systems, exposing
+ * BIOS issues such as skipped device initialization.
*
- * Today, most BIOS references to _OSI(Linux) are noise --
- * they have no functional effect and are just dead code
- * carried over from the reference BIOS.
- *
- * The next most common case is that _OSI(Linux) harms Linux,
- * usually by causing the BIOS to follow paths that are
- * not tested during Windows validation.
- *
- * Finally, there is a short list of platforms
- * where OSI(Linux) benefits Linux.
- *
- * In Linux-2.6.23, OSI(Linux) is first disabled by default.
- * DMI is used to disable the dmesg warning about OSI(Linux)
- * on platforms where it is known to have no effect.
- * But a dmesg warning remains for systems where
- * we do not know if OSI(Linux) is good or bad for the system.
- * DMI is also used to enable OSI(Linux) for the machines
- * that are known to need it.
+ * So "Linux" turned out to be a really poor chose of
+ * OSI string, and from Linux-2.6.23 onward we respond FALSE.
*
* BIOS writers should NOT query _OSI(Linux) on future systems.
- * It will be ignored by default, and to get Linux to
- * not ignore it will require a kernel source update to
- * add a DMI entry, or a boot-time "acpi_osi=Linux" invocation.
+ * Linux will complain on the console when it sees it, and return FALSE.
+ * To get Linux to return TRUE for your system will require
+ * a kernel source update to add a DMI entry,
+ * or boot with "acpi_osi=Linux"
*/
-#define OSI_LINUX_ENABLE 0
static struct osi_linux {
unsigned int enable:1;
unsigned int dmi:1;
unsigned int cmdline:1;
unsigned int known:1;
-} osi_linux = { OSI_LINUX_ENABLE, 0, 0, 0};
+} osi_linux = { 0, 0, 0, 0};
static void __init acpi_request_region (struct acpi_generic_address *addr,
unsigned int length, char *desc)
return (AE_OK);
}
-/**
- * acpi_dmi_dump - dump DMI slots needed for blacklist entry
- *
- * Returns 0 on success
- */
-static int acpi_dmi_dump(void)
-{
-
- if (!dmi_available)
- return -1;
-
- printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
- dmi_get_system_info(DMI_SYS_VENDOR));
- printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
- dmi_get_system_info(DMI_PRODUCT_NAME));
- printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
- dmi_get_system_info(DMI_PRODUCT_VERSION));
- printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
- dmi_get_system_info(DMI_BOARD_NAME));
- printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
- dmi_get_system_info(DMI_BIOS_VENDOR));
- printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
- dmi_get_system_info(DMI_BIOS_DATE));
-
- return 0;
-}
-
-
/******************************************************************************
*
* FUNCTION: acpi_os_validate_interface
osi_linux.cmdline ? " via cmdline" :
osi_linux.dmi ? " via DMI" : "");
- if (!osi_linux.dmi) {
- if (acpi_dmi_dump())
- printk(KERN_NOTICE PREFIX
- "[please extract dmidecode output]\n");
- printk(KERN_NOTICE PREFIX
- "Please send DMI info above to "
- "linux-acpi@vger.kernel.org\n");
- }
- if (!osi_linux.known && !osi_linux.cmdline) {
- printk(KERN_NOTICE PREFIX
- "If \"acpi_osi=%sLinux\" works better, "
- "please notify linux-acpi@vger.kernel.org\n",
- osi_linux.enable ? "!" : "");
- }
-
if (osi_linux.enable)
return AE_OK;
}
if (!acpi_match_device_ids(device, button_device_ids))
device->wakeup.flags.run_wake = 1;
- /*
- * Don't set Power button GPE as run_wake
- * if Fixed Power button is used
- */
- if (!strcmp(device->pnp.hardware_id, "PNP0C0C") &&
- !(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) {
- device->wakeup.flags.run_wake = 0;
- device->wakeup.flags.valid = 0;
- }
-
end:
if (ACPI_FAILURE(status))
device->flags.wake_capable = 0;
old_suspend_ordering = true;
}
+/*
+ * According to the ACPI specification the BIOS should make sure that ACPI is
+ * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still,
+ * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
+ * on such systems during resume. Unfortunately that doesn't help in
+ * particularly pathological cases in which SCI_EN has to be set directly on
+ * resume, although the specification states very clearly that this flag is
+ * owned by the hardware. The set_sci_en_on_resume variable will be set in such
+ * cases.
+ */
+static bool set_sci_en_on_resume;
+
/**
* acpi_pm_disable_gpes - Disable the GPEs.
*/
}
/* If ACPI is not enabled by the BIOS, we need to enable it here. */
- acpi_enable();
+ if (set_sci_en_on_resume)
+ acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1);
+ else
+ acpi_enable();
+
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(acpi_state);
return 0;
}
+static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d)
+{
+ set_sci_en_on_resume = true;
+ return 0;
+}
+
static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
{
.callback = init_old_suspend_ordering,
DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
},
},
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Apple MacBook 1,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Apple MacMini 1,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
+ },
+ },
{},
};
#endif /* CONFIG_SUSPEND */
ret = input_register_polled_device(toshiba_acpi.poll_dev);
if (ret) {
printk(MY_ERR "unable to register kill-switch input device\n");
- rfkill_free(toshiba_acpi.rfk_dev);
- toshiba_acpi.rfk_dev = NULL;
toshiba_acpi_exit();
return ret;
}
struct acpi_object_list *arguments, unsigned long long *data)
{
acpi_status status = AE_OK;
- union acpi_object *element;
+ union acpi_object element;
struct acpi_buffer buffer = { 0, NULL };
-
if (!data)
return AE_BAD_PARAMETER;
- element = kzalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
- if (!element)
- return AE_NO_MEMORY;
-
buffer.length = sizeof(union acpi_object);
- buffer.pointer = element;
+ buffer.pointer = &element;
status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
if (ACPI_FAILURE(status)) {
acpi_util_eval_error(handle, pathname, status);
- kfree(element);
return status;
}
- if (element->type != ACPI_TYPE_INTEGER) {
+ if (element.type != ACPI_TYPE_INTEGER) {
acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
- kfree(element);
return AE_BAD_DATA;
}
- *data = element->integer.value;
- kfree(element);
+ *data = element.integer.value;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
int in_irq;
/* Details of hardware device */
- unsigned long physaddr;
+ resource_size_t physaddr;
void __iomem *baseaddr;
int irq;
int bus_width; /* 0 := 8 bit; 1 := 16 bit */
/* Okay, it's a data request, set it up for transfer */
dev_dbg(ace->dev,
- "request: sec=%lx hcnt=%lx, ccnt=%x, dir=%i\n",
- req->sector, req->hard_nr_sectors,
+ "request: sec=%llx hcnt=%lx, ccnt=%x, dir=%i\n",
+ (unsigned long long) req->sector, req->hard_nr_sectors,
req->current_nr_sectors, rq_data_dir(req));
ace->req = req;
int rc;
dev_dbg(ace->dev, "ace_setup(ace=0x%p)\n", ace);
- dev_dbg(ace->dev, "physaddr=0x%lx irq=%i\n", ace->physaddr, ace->irq);
+ dev_dbg(ace->dev, "physaddr=0x%llx irq=%i\n",
+ (unsigned long long)ace->physaddr, ace->irq);
spin_lock_init(&ace->lock);
init_completion(&ace->id_completion);
/* Print the identification */
dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n",
(version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff);
- dev_dbg(ace->dev, "physaddr 0x%lx, mapped to 0x%p, irq=%i\n",
- ace->physaddr, ace->baseaddr, ace->irq);
+ dev_dbg(ace->dev, "physaddr 0x%llx, mapped to 0x%p, irq=%i\n",
+ (unsigned long long) ace->physaddr, ace->baseaddr, ace->irq);
ace->media_change = 1;
ace_revalidate_disk(ace->gd);
err_blk_initq:
iounmap(ace->baseaddr);
err_ioremap:
- dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n",
- ace->physaddr);
+ dev_info(ace->dev, "xsysace: error initializing device at 0x%llx\n",
+ (unsigned long long) ace->physaddr);
return -ENOMEM;
}
}
static int __devinit
-ace_alloc(struct device *dev, int id, unsigned long physaddr,
+ace_alloc(struct device *dev, int id, resource_size_t physaddr,
int irq, int bus_width)
{
struct ace_device *ace;
static int __devinit ace_probe(struct platform_device *dev)
{
- unsigned long physaddr = 0;
+ resource_size_t physaddr = 0;
int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
int id = dev->id;
int irq = NO_IRQ;
ace_of_probe(struct of_device *op, const struct of_device_id *match)
{
struct resource res;
- unsigned long physaddr;
+ resource_size_t physaddr;
const u32 *id;
int irq, bus_width, rc;
static int uninorth_rev;
static int is_u3;
-static char __devinitdata *aperture = NULL;
+static char *aperture = NULL;
static int uninorth_fetch_size(void)
{
* do is go probing around in the usual places hoping we can find it.
*/
-static int stli_findeisabrds(void)
+static int __init stli_findeisabrds(void)
{
struct stlibrd *brdp;
unsigned int iobase, eid, i;
* can find.
*/
-static int stli_initbrds(void)
+static int __init stli_initbrds(void)
{
struct stlibrd *brdp, *nxtbrdp;
struct stlconf conf;
}
#endif
if (device == MKDEV(TTYAUX_MAJOR, 1)) {
- driver = tty_driver_kref_get(console_device(&index));
- if (driver) {
- /* Don't let /dev/console block */
- filp->f_flags |= O_NONBLOCK;
- noctty = 1;
- goto got_driver;
+ struct tty_driver *console_driver = console_device(&index);
+ if (console_driver) {
+ driver = tty_driver_kref_get(console_driver);
+ if (driver) {
+ /* Don't let /dev/console block */
+ filp->f_flags |= O_NONBLOCK;
+ noctty = 1;
+ goto got_driver;
+ }
}
mutex_unlock(&tty_mutex);
return -ENODEV;
if (!request_mem_region(drvdata->mem_start,
drvdata->mem_size, DRIVER_NAME)) {
dev_err(dev, "Couldn't lock memory region at %Lx\n",
- regs_res->start);
+ (unsigned long long) regs_res->start);
retval = -EBUSY;
goto failed1;
}
mutex_init(&drvdata->sem);
drvdata->is_open = 0;
- dev_info(dev, "ioremap %lx to %p with size %Lx\n",
- (unsigned long int)drvdata->mem_start,
- drvdata->base_address, drvdata->mem_size);
+ dev_info(dev, "ioremap %llx to %p with size %llx\n",
+ (unsigned long long) drvdata->mem_start,
+ drvdata->base_address,
+ (unsigned long long) drvdata->mem_size);
cdev_init(&drvdata->cdev, &hwicap_fops);
drvdata->cdev.owner = THIS_MODULE;
return ret;
}
-static int __devexit talitos_remove(struct of_device *ofdev)
+static int talitos_remove(struct of_device *ofdev)
{
struct device *dev = &ofdev->dev;
struct talitos_private *priv = dev_get_drvdata(dev);
.name = "talitos",
.match_table = talitos_match,
.probe = talitos_probe,
- .remove = __devexit_p(talitos_remove),
+ .remove = talitos_remove,
};
static int __init talitos_init(void)
return;
}
+ drm_vblank_cleanup(dev);
+
drm_lastclose(dev);
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
}
}
-static void drm_vblank_cleanup(struct drm_device *dev)
+void drm_vblank_cleanup(struct drm_device *dev)
{
/* Bail if the driver didn't call drm_vblank_init() */
if (dev->num_crtcs == 0)
free_irq(dev->pdev->irq, dev);
- drm_vblank_cleanup(dev);
-
return 0;
}
EXPORT_SYMBOL(drm_irq_uninstall);
spin_lock_init(&dev_priv->user_irq_lock);
+ ret = drm_vblank_init(dev, I915_NUM_PIPE);
+
+ if (ret) {
+ (void) i915_driver_unload(dev);
+ return ret;
+ }
+
return ret;
}
PIPE_B,
};
+#define I915_NUM_PIPE 2
+
/* Interface history:
*
* 1.1: Original.
int user_irq_refcount;
/** Cached value of IMR to avoid reads in updating the bitfield */
u32 irq_mask_reg;
+ u32 pipestat[2];
int tex_lru_log_granularity;
int allow_batchbuffer;
u32 saveDSPBCNTR;
u32 saveDSPARB;
u32 saveRENDERSTANDBY;
+ u32 saveHWS;
u32 savePIPEACONF;
u32 savePIPEBCONF;
u32 savePIPEASRC;
struct drm_file *file_priv);
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
+void
+i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
+
+void
+i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
+
+
/* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data,
struct drm_file *file_priv);
#include "i915_drv.h"
#include <linux/swap.h>
+#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
+
static int
i915_gem_object_set_domain(struct drm_gem_object *obj,
uint32_t read_domains,
i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_get_aperture *args = data;
- struct drm_i915_gem_object *obj_priv;
if (!(dev->driver->driver_features & DRIVER_GEM))
return -ENODEV;
args->aper_size = dev->gtt_total;
- args->aper_available_size = args->aper_size;
-
- list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
- if (obj_priv->pin_count > 0)
- args->aper_available_size -= obj_priv->obj->size;
- }
+ args->aper_available_size = (args->aper_size -
+ atomic_read(&dev->pin_memory));
return 0;
}
for (i = 0; i < args->buffer_count; i++) {
struct drm_gem_object *obj = object_list[i];
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
-
- if (obj_priv->gtt_space == NULL) {
- /* We evicted the buffer in the process of validating
- * our set of buffers in. We could try to recover by
- * kicking them everything out and trying again from
- * the start.
- */
- ret = -ENOMEM;
- goto err;
- }
/* make sure all previous memory operations have passed */
ret = i915_gem_object_set_domain(obj,
i915_gem_retire_requests(dev);
- /* Active and flushing should now be empty as we've
- * waited for a sequence higher than any pending execbuffer
- */
- BUG_ON(!list_empty(&dev_priv->mm.active_list));
- BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+ if (!dev_priv->mm.wedged) {
+ /* Active and flushing should now be empty as we've
+ * waited for a sequence higher than any pending execbuffer
+ */
+ WARN_ON(!list_empty(&dev_priv->mm.active_list));
+ WARN_ON(!list_empty(&dev_priv->mm.flushing_list));
+ /* Request should now be empty as we've also waited
+ * for the last request in the list
+ */
+ WARN_ON(!list_empty(&dev_priv->mm.request_list));
+ }
- /* Request should now be empty as we've also waited
- * for the last request in the list
+ /* Empty the active and flushing lists to inactive. If there's
+ * anything left at this point, it means that we're wedged and
+ * nothing good's going to happen by leaving them there. So strip
+ * the GPU domains and just stuff them onto inactive.
*/
- BUG_ON(!list_empty(&dev_priv->mm.request_list));
+ while (!list_empty(&dev_priv->mm.active_list)) {
+ struct drm_i915_gem_object *obj_priv;
+
+ obj_priv = list_first_entry(&dev_priv->mm.active_list,
+ struct drm_i915_gem_object,
+ list);
+ obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
+ i915_gem_object_move_to_inactive(obj_priv->obj);
+ }
+
+ while (!list_empty(&dev_priv->mm.flushing_list)) {
+ struct drm_i915_gem_object *obj_priv;
+
+ obj_priv = list_first_entry(&dev_priv->mm.flushing_list,
+ struct drm_i915_gem_object,
+ list);
+ obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
+ i915_gem_object_move_to_inactive(obj_priv->obj);
+ }
- /* Move all buffers out of the GTT. */
+
+ /* Move all inactive buffers out of the GTT. */
ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
+ WARN_ON(!list_empty(&dev_priv->mm.inactive_list));
if (ret) {
mutex_unlock(&dev->struct_mutex);
return ret;
}
- BUG_ON(!list_empty(&dev_priv->mm.active_list));
- BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
- BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
- BUG_ON(!list_empty(&dev_priv->mm.request_list));
-
i915_gem_cleanup_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex);
#define MAX_NOPID ((u32)~0)
-/** These are the interrupts used by the driver */
-#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \
- I915_ASLE_INTERRUPT | \
- I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
- I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+/**
+ * Interrupts that are always left unmasked.
+ *
+ * Since pipe events are edge-triggered from the PIPESTAT register to IIR,
+ * we leave them always unmasked in IMR and then control enabling them through
+ * PIPESTAT alone.
+ */
+#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \
+ I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
+ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+
+/** Interrupts that we mask and unmask at runtime. */
+#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
+
+/** These are all of the interrupts used by the driver */
+#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
+ I915_INTERRUPT_ENABLE_VAR)
void
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
}
}
+static inline u32
+i915_pipestat(int pipe)
+{
+ if (pipe == 0)
+ return PIPEASTAT;
+ if (pipe == 1)
+ return PIPEBSTAT;
+ BUG_ON(1);
+}
+
+void
+i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
+{
+ if ((dev_priv->pipestat[pipe] & mask) != mask) {
+ u32 reg = i915_pipestat(pipe);
+
+ dev_priv->pipestat[pipe] |= mask;
+ /* Enable the interrupt, clear any pending status */
+ I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16));
+ (void) I915_READ(reg);
+ }
+}
+
+void
+i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
+{
+ if ((dev_priv->pipestat[pipe] & mask) != 0) {
+ u32 reg = i915_pipestat(pipe);
+
+ dev_priv->pipestat[pipe] &= ~mask;
+ I915_WRITE(reg, dev_priv->pipestat[pipe]);
+ (void) I915_READ(reg);
+ }
+}
+
/**
* i915_pipe_enabled - check if a pipe is enabled
* @dev: DRM device
{
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 iir;
+ u32 iir, new_iir;
u32 pipea_stats, pipeb_stats;
+ u32 vblank_status;
+ u32 vblank_enable;
int vblank = 0;
+ unsigned long irqflags;
+ int irq_received;
+ int ret = IRQ_NONE;
atomic_inc(&dev_priv->irq_received);
- if (dev->pdev->msi_enabled)
- I915_WRITE(IMR, ~0);
iir = I915_READ(IIR);
- if (iir == 0) {
- if (dev->pdev->msi_enabled) {
- I915_WRITE(IMR, dev_priv->irq_mask_reg);
- (void) I915_READ(IMR);
- }
- return IRQ_NONE;
+ if (IS_I965G(dev)) {
+ vblank_status = I915_START_VBLANK_INTERRUPT_STATUS;
+ vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE;
+ } else {
+ vblank_status = I915_VBLANK_INTERRUPT_STATUS;
+ vblank_enable = I915_VBLANK_INTERRUPT_ENABLE;
}
- /*
- * Clear the PIPE(A|B)STAT regs before the IIR otherwise
- * we may get extra interrupts.
- */
- if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
+ for (;;) {
+ irq_received = iir != 0;
+
+ /* Can't rely on pipestat interrupt bit in iir as it might
+ * have been cleared after the pipestat interrupt was received.
+ * It doesn't set the bit in iir again, but it still produces
+ * interrupts (for non-MSI).
+ */
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
pipea_stats = I915_READ(PIPEASTAT);
- if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A))
- pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
- PIPE_VBLANK_INTERRUPT_ENABLE);
- else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
- PIPE_VBLANK_INTERRUPT_STATUS)) {
+ pipeb_stats = I915_READ(PIPEBSTAT);
+ /*
+ * Clear the PIPE(A|B)STAT regs before the IIR
+ */
+ if (pipea_stats & 0x8000ffff) {
+ I915_WRITE(PIPEASTAT, pipea_stats);
+ irq_received = 1;
+ }
+
+ if (pipeb_stats & 0x8000ffff) {
+ I915_WRITE(PIPEBSTAT, pipeb_stats);
+ irq_received = 1;
+ }
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
+
+ if (!irq_received)
+ break;
+
+ ret = IRQ_HANDLED;
+
+ I915_WRITE(IIR, iir);
+ new_iir = I915_READ(IIR); /* Flush posted writes */
+
+ if (dev_priv->sarea_priv)
+ dev_priv->sarea_priv->last_dispatch =
+ READ_BREADCRUMB(dev_priv);
+
+ if (iir & I915_USER_INTERRUPT) {
+ dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
+ DRM_WAKEUP(&dev_priv->irq_queue);
+ }
+
+ if (pipea_stats & vblank_status) {
vblank++;
drm_handle_vblank(dev, 0);
}
- I915_WRITE(PIPEASTAT, pipea_stats);
- }
- if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
- pipeb_stats = I915_READ(PIPEBSTAT);
- /* Ack the event */
- I915_WRITE(PIPEBSTAT, pipeb_stats);
-
- /* The vblank interrupt gets enabled even if we didn't ask for
- it, so make sure it's shut down again */
- if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
- pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
- PIPE_VBLANK_INTERRUPT_ENABLE);
- else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
- PIPE_VBLANK_INTERRUPT_STATUS)) {
+ if (pipeb_stats & vblank_status) {
vblank++;
drm_handle_vblank(dev, 1);
}
- if (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS)
+ if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
+ (iir & I915_ASLE_INTERRUPT))
opregion_asle_intr(dev);
- I915_WRITE(PIPEBSTAT, pipeb_stats);
- }
-
- I915_WRITE(IIR, iir);
- if (dev->pdev->msi_enabled)
- I915_WRITE(IMR, dev_priv->irq_mask_reg);
- (void) I915_READ(IIR); /* Flush posted writes */
-
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_dispatch =
- READ_BREADCRUMB(dev_priv);
- if (iir & I915_USER_INTERRUPT) {
- dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
- DRM_WAKEUP(&dev_priv->irq_queue);
+ /* With MSI, interrupts are only generated when iir
+ * transitions from zero to nonzero. If another bit got
+ * set while we were handling the existing iir bits, then
+ * we would never get another interrupt.
+ *
+ * This is fine on non-MSI as well, as if we hit this path
+ * we avoid exiting the interrupt handler only to generate
+ * another one.
+ *
+ * Note that for MSI this could cause a stray interrupt report
+ * if an interrupt landed in the time between writing IIR and
+ * the posting read. This should be rare enough to never
+ * trigger the 99% of 100,000 interrupts test for disabling
+ * stray interrupts.
+ */
+ iir = new_iir;
}
- if (iir & I915_ASLE_INTERRUPT)
- opregion_asle_intr(dev);
-
- return IRQ_HANDLED;
+ return ret;
}
static int i915_emit_irq(struct drm_device * dev)
int i915_enable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 pipestat_reg = 0;
- u32 pipestat;
- u32 interrupt = 0;
unsigned long irqflags;
- switch (pipe) {
- case 0:
- pipestat_reg = PIPEASTAT;
- interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
- break;
- case 1:
- pipestat_reg = PIPEBSTAT;
- interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
- break;
- default:
- DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
- pipe);
- return 0;
- }
-
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
- /* Enabling vblank events in IMR comes before PIPESTAT write, or
- * there's a race where the PIPESTAT vblank bit gets set to 1, so
- * the OR of enabled PIPESTAT bits goes to 1, so the PIPExEVENT in
- * ISR flashes to 1, but the IIR bit doesn't get set to 1 because
- * IMR masks it. It doesn't ever get set after we clear the masking
- * in IMR because the ISR bit is edge, not level-triggered, on the
- * OR of PIPESTAT bits.
- */
- i915_enable_irq(dev_priv, interrupt);
- pipestat = I915_READ(pipestat_reg);
if (IS_I965G(dev))
- pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
+ i915_enable_pipestat(dev_priv, pipe,
+ PIPE_START_VBLANK_INTERRUPT_ENABLE);
else
- pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
- /* Clear any stale interrupt status */
- pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
- PIPE_VBLANK_INTERRUPT_STATUS);
- I915_WRITE(pipestat_reg, pipestat);
- (void) I915_READ(pipestat_reg); /* Posting read */
+ i915_enable_pipestat(dev_priv, pipe,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
-
return 0;
}
void i915_disable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 pipestat_reg = 0;
- u32 pipestat;
- u32 interrupt = 0;
unsigned long irqflags;
- switch (pipe) {
- case 0:
- pipestat_reg = PIPEASTAT;
- interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
- break;
- case 1:
- pipestat_reg = PIPEBSTAT;
- interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
- break;
- default:
- DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
- pipe);
- return;
- break;
- }
-
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
- i915_disable_irq(dev_priv, interrupt);
- pipestat = I915_READ(pipestat_reg);
- pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
- PIPE_VBLANK_INTERRUPT_ENABLE);
- /* Clear any stale interrupt status */
- pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
- PIPE_VBLANK_INTERRUPT_STATUS);
- I915_WRITE(pipestat_reg, pipestat);
- (void) I915_READ(pipestat_reg); /* Posting read */
+ i915_disable_pipestat(dev_priv, pipe,
+ PIPE_VBLANK_INTERRUPT_ENABLE |
+ PIPE_START_VBLANK_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
}
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
I915_WRITE(HWSTAM, 0xeffe);
+ I915_WRITE(PIPEASTAT, 0);
+ I915_WRITE(PIPEBSTAT, 0);
I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0);
+ (void) I915_READ(IER);
}
int i915_driver_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- int ret, num_pipes = 2;
-
- /* Set initial unmasked IRQs to just the selected vblank pipes. */
- dev_priv->irq_mask_reg = ~0;
-
- ret = drm_vblank_init(dev, num_pipes);
- if (ret)
- return ret;
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
- dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
- dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
- dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
+ /* Unmask the interrupts that we always want on. */
+ dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
+
+ dev_priv->pipestat[0] = 0;
+ dev_priv->pipestat[1] = 0;
+
+ /* Disable pipe interrupt enables, clear pending pipe status */
+ I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
+ I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
+ /* Clear pending interrupt status */
+ I915_WRITE(IIR, I915_READ(IIR));
- I915_WRITE(IMR, dev_priv->irq_mask_reg);
I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
+ I915_WRITE(IMR, dev_priv->irq_mask_reg);
(void) I915_READ(IER);
opregion_enable_asle(dev);
void i915_driver_irq_uninstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 temp;
if (!dev_priv)
return;
dev_priv->vblank_pipe = 0;
I915_WRITE(HWSTAM, 0xffffffff);
+ I915_WRITE(PIPEASTAT, 0);
+ I915_WRITE(PIPEBSTAT, 0);
I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0);
- temp = I915_READ(PIPEASTAT);
- I915_WRITE(PIPEASTAT, temp);
- temp = I915_READ(PIPEBSTAT);
- I915_WRITE(PIPEBSTAT, temp);
- temp = I915_READ(IIR);
- I915_WRITE(IIR, temp);
+ I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
+ I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
+ I915_WRITE(IIR, I915_READ(IIR));
}
struct opregion_asle *asle = dev_priv->opregion.asle;
if (asle) {
- u32 pipeb_stats = I915_READ(PIPEBSTAT);
if (IS_MOBILE(dev)) {
- /* Many devices trigger events with a write to the
- legacy backlight controller, so we need to ensure
- that it's able to generate interrupts */
- I915_WRITE(PIPEBSTAT, pipeb_stats |=
- I915_LEGACY_BLC_EVENT_ENABLE);
- i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT |
- I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
- } else
- i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT);
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+ i915_enable_pipestat(dev_priv, 1,
+ I915_LEGACY_BLC_EVENT_ENABLE);
+ spin_unlock_irqrestore(&dev_priv->user_irq_lock,
+ irqflags);
+ }
asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
ASLE_PFMB_EN;
if (IS_I965G(dev) && IS_MOBILE(dev))
dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
+ /* Hardware status page */
+ dev_priv->saveHWS = I915_READ(HWS_PGA);
+
/* Display arbitration control */
dev_priv->saveDSPARB = I915_READ(DSPARB);
if (IS_I965G(dev) && IS_MOBILE(dev))
I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
+ /* Hardware status page */
+ I915_WRITE(HWS_PGA, dev_priv->saveHWS);
+
/* Display arbitration */
I915_WRITE(DSPARB, dev_priv->saveDSPARB);
int mga_driver_load(struct drm_device * dev, unsigned long flags)
{
drm_mga_private_t *dev_priv;
+ int ret;
dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
if (!dev_priv)
dev->types[7] = _DRM_STAT_PRIMARY;
dev->types[8] = _DRM_STAT_SECONDARY;
+ ret = drm_vblank_init(dev, 1);
+
+ if (ret) {
+ (void) mga_driver_unload(dev);
+ return ret;
+ }
+
return 0;
}
int mga_driver_irq_postinstall(struct drm_device *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
- int ret;
-
- ret = drm_vblank_init(dev, 1);
- if (ret)
- return ret;
DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.dev_priv_size = sizeof(drm_r128_buf_priv_t),
+ .load = r128_driver_load,
.preclose = r128_driver_preclose,
.lastclose = r128_driver_lastclose,
.get_vblank_counter = r128_get_vblank_counter,
.patchlevel = DRIVER_PATCHLEVEL,
};
+int r128_driver_load(struct drm_device * dev, unsigned long flags)
+{
+ return drm_vblank_init(dev, 1);
+}
+
static int __init r128_init(void)
{
driver.num_ioctls = r128_max_ioctl;
extern int r128_driver_irq_postinstall(struct drm_device *dev);
extern void r128_driver_irq_uninstall(struct drm_device * dev);
extern void r128_driver_lastclose(struct drm_device * dev);
+extern int r128_driver_load(struct drm_device * dev, unsigned long flags);
extern void r128_driver_preclose(struct drm_device * dev,
struct drm_file *file_priv);
int r128_driver_irq_postinstall(struct drm_device *dev)
{
- return drm_vblank_init(dev, 1);
+ return 0;
}
void r128_driver_irq_uninstall(struct drm_device * dev)
if (ret != 0)
return ret;
+ ret = drm_vblank_init(dev, 2);
+ if (ret) {
+ radeon_driver_unload(dev);
+ return ret;
+ }
+
DRM_DEBUG("%s card detected\n",
((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
return ret;
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
- int ret;
atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
- ret = drm_vblank_init(dev, 2);
- if (ret)
- return ret;
-
dev->max_vblank_count = 0x001fffff;
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
if (!dev_priv)
return -EINVAL;
- drm_vblank_init(dev, 1);
status = VIA_READ(VIA_REG_INTERRUPT);
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
| dev_priv->irq_enable_mask);
ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
if (ret) {
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ return ret;
}
- return ret;
+
+ ret = drm_vblank_init(dev, 1);
+ if (ret) {
+ drm_sman_takedown(&dev_priv->sman);
+ drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+ return ret;
+ }
+
+ return 0;
}
int via_driver_unload(struct drm_device *dev)
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
APPLE_RDESC_JIS },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
APPLE_ISO_KEYBOARD },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
.driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ }
#define USB_VENDOR_ID_GAMERON 0x0810
#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
+#define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002
#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
static const struct hid_device_id pl_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR),
.driver_data = 1 }, /* Twin USB Joystick */
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR),
+ .driver_data = 1 }, /* Twin USB Joystick */
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), }, /* GreenAsia Inc. USB Joystick */
{ }
};
if (insize > HID_MAX_BUFFER_SIZE)
insize = HID_MAX_BUFFER_SIZE;
- mutex_lock(&usbhid->setup);
if (hid_alloc_buffers(dev, hid)) {
ret = -ENOMEM;
goto fail;
hid_dump_device(hid);
set_bit(HID_STARTED, &usbhid->iofl);
- mutex_unlock(&usbhid->setup);
return 0;
usbhid->urbout = NULL;
usbhid->urbctrl = NULL;
hid_free_buffers(dev, hid);
- mutex_unlock(&usbhid->setup);
return ret;
}
if (WARN_ON(!usbhid))
return;
- mutex_lock(&usbhid->setup);
clear_bit(HID_STARTED, &usbhid->iofl);
spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
set_bit(HID_DISCONNECTED, &usbhid->iofl);
usbhid->urbout = NULL;
hid_free_buffers(hid_to_usb_dev(hid), hid);
- mutex_unlock(&usbhid->setup);
}
static struct hid_ll_driver usb_hid_driver = {
hid->driver_data = usbhid;
usbhid->hid = hid;
- mutex_init(&usbhid->setup); /* needed on suspend/resume */
ret = hid_add_device(hid);
if (ret) {
struct hid_device *hid = usb_get_intfdata (intf);
struct usbhid_device *usbhid = hid->driver_data;
- mutex_lock(&usbhid->setup);
- if (!test_bit(HID_STARTED, &usbhid->iofl)) {
- mutex_unlock(&usbhid->setup);
+ if (!test_bit(HID_STARTED, &usbhid->iofl))
return 0;
- }
spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
set_bit(HID_SUSPENDED, &usbhid->iofl);
spin_unlock_irq(&usbhid->inlock);
del_timer_sync(&usbhid->io_retry);
usb_kill_urb(usbhid->urbin);
- mutex_unlock(&usbhid->setup);
dev_dbg(&intf->dev, "suspend\n");
return 0;
}
struct usbhid_device *usbhid = hid->driver_data;
int status;
- mutex_lock(&usbhid->setup);
- if (!test_bit(HID_STARTED, &usbhid->iofl)) {
- mutex_unlock(&usbhid->setup);
+ if (!test_bit(HID_STARTED, &usbhid->iofl))
return 0;
- }
clear_bit(HID_SUSPENDED, &usbhid->iofl);
usbhid->retry_delay = 0;
status = hid_start_in(hid);
- mutex_unlock(&usbhid->setup);
dev_dbg(&intf->dev, "resume status %d\n", status);
return status;
}
dma_addr_t outbuf_dma; /* Output buffer dma */
spinlock_t outlock; /* Output fifo spinlock */
- struct mutex setup;
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
struct timer_list io_retry; /* Retry timer */
unsigned long stop_retry; /* Time to give up, in jiffies */
if (adapter_parm[type].init.val)
line_set(port, 1, &adapter_parm[type].init);
- parport_release(adapter->pdev);
-
if (i2c_bit_add_bus(&adapter->adapter) < 0) {
printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
goto ERROR1;
return;
ERROR1:
+ parport_release(adapter->pdev);
parport_unregister_device(adapter->pdev);
ERROR0:
kfree(adapter);
if (adapter_parm[type].init.val)
line_set(port, 0, &adapter_parm[type].init);
+ parport_release(adapter->pdev);
parport_unregister_device(adapter->pdev);
if (prev)
prev->next = adapter->next;
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/gpio.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
#include <asm/irq.h>
+#include <asm/mach-types.h>
+
#include <mach/usb.h>
+#include <mach/mux.h>
#ifndef DEBUG
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_MACH_OMAP_H2
-
/* board-specific PM hooks */
-#include <asm/gpio.h>
-#include <mach/mux.h>
-#include <asm/mach-types.h>
-
+#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
#if defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
}
+#endif
+
+#if defined(CONFIG_MACH_OMAP_H4)
+
+static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
+{
+ /* H4 controls this by DIP switch S2.4; no soft control.
+ * ON means the charger is always enabled. Leave it OFF
+ * unless the OTG port is used only in B-peripheral mode.
+ */
+}
+
+static void enable_vbus_source(struct isp1301 *isp)
+{
+ /* this board won't supply more than 8mA vbus power.
+ * some boards can switch a 100ma "unit load" (or more).
+ */
+}
+
+
+/* products will deliver OTG messages with LEDs, GUI, etc */
+static inline void notresponding(struct isp1301 *isp)
+{
+ printk(KERN_NOTICE "OTG device not responding.\n");
+}
+
+
#endif
/*-------------------------------------------------------------------------*/
* NOTE: guaranteeing certain response times might mean we shouldn't
* share keventd's work queue; a realtime task might be safest.
*/
-void
-isp1301_defer_work(struct isp1301 *isp, int work)
+static void isp1301_defer_work(struct isp1301 *isp, int work)
{
int status;
otg_ctrl &= ~OTG_XCEIV_INPUTS;
otg_ctrl &= ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD);
-
if (int_src & INTR_SESS_VLD)
otg_ctrl |= OTG_ASESSVLD;
else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) {
static int otg_remove(struct platform_device *dev)
{
- otg_dev = 0;
+ otg_dev = NULL;
return 0;
}
-struct platform_driver omap_otg_driver = {
+static struct platform_driver omap_otg_driver = {
.probe = otg_probe,
.remove = otg_remove,
.driver = {
isp = dev_get_drvdata(dev);
+ /* FIXME -- not with a "new style" driver, it doesn't!! */
+
/* ugly -- i2c hijacks our memory hook to wait_for_completion() */
if (isp->i2c_release)
isp->i2c_release(dev);
otg_unbind(isp);
#endif
if (machine_is_omap_h2())
- omap_free_gpio(2);
+ gpio_free(2);
isp->timer.data = 0;
set_bit(WORK_STOP, &isp->todo);
flush_scheduled_work();
put_device(&i2c->dev);
- the_transceiver = 0;
+ the_transceiver = NULL;
return 0;
}
if (!host) {
omap_writew(0, OTG_IRQ_EN);
power_down(isp);
- isp->otg.host = 0;
+ isp->otg.host = NULL;
return 0;
}
isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
{
struct isp1301 *isp = container_of(otg, struct isp1301, otg);
+#ifndef CONFIG_USB_OTG
u32 l;
+#endif
if (!otg || isp != the_transceiver)
return -ENODEV;
if (!isp->otg.default_a)
enable_vbus_draw(isp, 0);
usb_gadget_vbus_disconnect(isp->otg.gadget);
- isp->otg.gadget = 0;
+ isp->otg.gadget = NULL;
power_down(isp);
return 0;
}
power_up(isp);
isp->otg.state = OTG_STATE_B_IDLE;
- if (machine_is_omap_h2())
+ if (machine_is_omap_h2() || machine_is_omap_h3())
isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
/*-------------------------------------------------------------------------*/
-static int __init isp1301_probe(struct i2c_client *i2c)
+static int __init
+isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
int status;
struct isp1301 *isp;
static void __exit isp_exit(void)
{
if (the_transceiver)
- otg_set_transceiver(0);
+ otg_set_transceiver(NULL);
i2c_del_driver(&isp1301_driver);
}
module_exit(isp_exit);
/* detach any active clients. This must be done first, because
* it can fail; in which case we give up. */
- list_for_each_entry_safe(client, _n, &adap->clients, list) {
+ list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) {
struct i2c_driver *driver;
driver = client->driver;
hw->chipset = ide_acorn;
}
-static int __init
+static int __devinit
icside_register_v5(struct icside_state *state, struct expansion_card *ec)
{
void __iomem *base;
.swdma_mask = ATA_SWDMA2,
};
-static int __init
+static int __devinit
icside_register_v6(struct icside_state *state, struct expansion_card *ec)
{
void __iomem *ioc_base, *easi_base;
{
struct ml_device *ml = dev->ff->private;
struct ml_effect_state *state = &ml->states[effect_id];
+ unsigned long flags;
- spin_lock_bh(&ml->timer_lock);
+ spin_lock_irqsave(&ml->timer_lock, flags);
if (value > 0) {
debug("initiated play");
ml_play_effects(ml);
}
- spin_unlock_bh(&ml->timer_lock);
+ spin_unlock_irqrestore(&ml->timer_lock, flags);
return 0;
}
atkbd_disable(atkbd);
/* make sure we don't have a command in flight */
- flush_scheduled_work();
+ cancel_delayed_work_sync(&atkbd->event_work);
sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
input_unregister_device(atkbd->dev);
atkbd->force_release_mask);
}
+/*
+ * Inventec system with broken key release on volume keys
+ */
+static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd)
+{
+ const unsigned int forced_release_keys[] = {
+ 0xae, 0xb0,
+ };
+ int i;
+
+ if (atkbd->set == 2)
+ for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
+ __set_bit(forced_release_keys[i],
+ atkbd->force_release_mask);
+}
+
/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
.callback = atkbd_setup_fixup,
.driver_data = atkbd_hp_keymap_fixup,
},
+ {
+ .ident = "Inventec Symphony",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"),
+ },
+ .callback = atkbd_setup_fixup,
+ .driver_data = atkbd_inventec_keymap_fixup,
+ },
{ }
};
static char *phone = "kip1000";
module_param(phone, charp, S_IRUSR);
-MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}");
+MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01, atcom}");
enum {
/* HID Registers */
}
}
+/*
+ * Keymap for ATCom AU-100
+ * http://www.atcom.cn/En_products_AU100.html
+ * http://www.packetizer.com/products/au100/
+ * http://www.voip-info.org/wiki/view/AU-100
+ *
+ * Contributed by daniel@gimpelevich.san-francisco.ca.us
+ */
+static unsigned short keymap_atcom(int scancode)
+{
+ switch (scancode) { /* phone key: */
+ case 0x82: return KEY_NUMERIC_0; /* 0 */
+ case 0x11: return KEY_NUMERIC_1; /* 1 */
+ case 0x12: return KEY_NUMERIC_2; /* 2 */
+ case 0x14: return KEY_NUMERIC_3; /* 3 */
+ case 0x21: return KEY_NUMERIC_4; /* 4 */
+ case 0x22: return KEY_NUMERIC_5; /* 5 */
+ case 0x24: return KEY_NUMERIC_6; /* 6 */
+ case 0x41: return KEY_NUMERIC_7; /* 7 */
+ case 0x42: return KEY_NUMERIC_8; /* 8 */
+ case 0x44: return KEY_NUMERIC_9; /* 9 */
+ case 0x84: return KEY_NUMERIC_POUND; /* # */
+ case 0x81: return KEY_NUMERIC_STAR; /* * */
+ case 0x18: return KEY_ENTER; /* pickup */
+ case 0x28: return KEY_ESC; /* hangup */
+ case 0x48: return KEY_LEFT; /* left arrow */
+ case 0x88: return KEY_RIGHT; /* right arrow */
+ default: return special_keymap(scancode);
+ }
+}
+
static unsigned short (*keymap)(int) = keymap_kip1000;
/*
keymap = keymap_usbph01;
printk(KERN_INFO KBUILD_MODNAME ": "
"Keymap for Allied-Telesis Corega USBPH01 phone loaded\n");
+ } else if (!strcasecmp(phone, "atcom")) {
+ keymap = keymap_atcom;
+ printk(KERN_INFO KBUILD_MODNAME ": "
+ "Keymap for ATCom AU-100 phone loaded\n");
} else {
printk(KERN_ERR KBUILD_MODNAME ": "
"Unsupported phone: %s\n", phone);
*/
static int hgpk_validate_byte(unsigned char *packet)
{
- return (packet[0] & 0x0C) == 0x08;
+ return (packet[0] & 0x0C) != 0x08;
}
static void hgpk_process_packet(struct psmouse *psmouse)
DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
},
},
+ {
+ .ident = "Dell XPS M1530",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),
+ },
+ },
+ {
+ .ident = "Compal HEL80I",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
+ },
+ },
{ }
};
* - Support Intuos3 4x6
* v1.47 (pc) - Added support for Bamboo
* v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
+ * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
*/
/*
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.48"
+#define DRIVER_VERSION "v1.49"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
struct usb_device *usbdev;
struct usb_interface *intf;
struct urb *irq;
- struct wacom_wac * wacom_wac;
+ struct wacom_wac *wacom_wac;
struct mutex lock;
unsigned int open:1;
char phys[32];
};
struct wacom_combo {
- struct wacom * wacom;
- struct urb * urb;
+ struct wacom *wacom;
+ struct urb *urb;
};
extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern __u16 wacom_le16_to_cpu(unsigned char *data);
extern __u16 wacom_be16_to_cpu(unsigned char *data);
-extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
-extern const struct usb_device_id * get_device_table(void);
+extern struct wacom_features *get_wacom_feature(const struct usb_device_id *id);
+extern const struct usb_device_id *get_device_table(void);
#endif
#include "wacom.h"
#include "wacom_wac.h"
+/* defines to get HID report descriptor */
+#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01)
+#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02)
+#define HID_USAGE_UNDEFINED 0x00
+#define HID_USAGE_PAGE 0x05
+#define HID_USAGE_PAGE_DIGITIZER 0x0d
+#define HID_USAGE_PAGE_DESKTOP 0x01
+#define HID_USAGE 0x09
+#define HID_USAGE_X 0x30
+#define HID_USAGE_Y 0x31
+#define HID_USAGE_X_TILT 0x3d
+#define HID_USAGE_Y_TILT 0x3e
+#define HID_USAGE_FINGER 0x22
+#define HID_USAGE_STYLUS 0x20
+#define HID_COLLECTION 0xc0
+
+enum {
+ WCM_UNDEFINED = 0,
+ WCM_DESKTOP,
+ WCM_DIGITIZER,
+};
+
+struct hid_descriptor {
+ struct usb_descriptor_header header;
+ __le16 bcdHID;
+ u8 bCountryCode;
+ u8 bNumDescriptors;
+ u8 bDescriptorType;
+ __le16 wDescriptorLength;
+} __attribute__ ((packed));
+
+/* defines to get/set USB message */
#define USB_REQ_GET_REPORT 0x01
#define USB_REQ_SET_REPORT 0x09
+#define WAC_HID_FEATURE_REPORT 0x03
static int usb_get_report(struct usb_interface *intf, unsigned char type,
unsigned char id, void *buf, int size)
void wacom_report_key(void *wcombo, unsigned int key_type, int key_data)
{
input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data);
- return;
}
void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data)
{
input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data);
- return;
}
void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data)
{
input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data);
- return;
}
void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value)
{
input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value);
- return;
}
__u16 wacom_be16_to_cpu(unsigned char *data)
void wacom_input_sync(void *wcombo)
{
input_sync(get_input_dev((struct wacom_combo *)wcombo));
- return;
}
static int wacom_open(struct input_dev *dev)
void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_1) |
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_1) |
BIT_MASK(BTN_5);
input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
}
input_dev->evbit[0] |= BIT_MASK(EV_MSC);
input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) |
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
BIT_MASK(BTN_4);
}
{
input_dev->evbit[0] |= BIT_MASK(EV_REL);
input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2);
void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) |
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3);
input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_4) |
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) |
BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7);
input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
}
void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
}
void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL);
input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
- input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) |
BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
- input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2) |
- BIT_MASK(BTN_TOOL_RUBBER);
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2);
}
void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER);
}
+static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
+ struct wacom_wac *wacom_wac)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct wacom_features *features = wacom_wac->features;
+ char limit = 0, result = 0;
+ int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
+ unsigned char *report;
+
+ report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
+ if (!report)
+ return -ENOMEM;
+
+ /* retrive report descriptors */
+ do {
+ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_DESCRIPTOR,
+ USB_RECIP_INTERFACE | USB_DIR_IN,
+ HID_DEVICET_REPORT << 8,
+ intf->altsetting[0].desc.bInterfaceNumber, /* interface */
+ report,
+ hid_desc->wDescriptorLength,
+ 5000); /* 5 secs */
+ } while (result < 0 && limit++ < 5);
+
+ if (result < 0)
+ goto out;
+
+ for (i = 0; i < hid_desc->wDescriptorLength; i++) {
+
+ switch (report[i]) {
+ case HID_USAGE_PAGE:
+ switch (report[i + 1]) {
+ case HID_USAGE_PAGE_DIGITIZER:
+ usage = WCM_DIGITIZER;
+ i++;
+ break;
+
+ case HID_USAGE_PAGE_DESKTOP:
+ usage = WCM_DESKTOP;
+ i++;
+ break;
+ }
+ break;
+
+ case HID_USAGE:
+ switch (report[i + 1]) {
+ case HID_USAGE_X:
+ if (usage == WCM_DESKTOP) {
+ if (finger) {
+ features->touch_x_max =
+ features->touch_y_max =
+ wacom_le16_to_cpu(&report[i + 3]);
+ features->x_max =
+ wacom_le16_to_cpu(&report[i + 6]);
+ i += 7;
+ } else if (pen) {
+ features->x_max =
+ wacom_le16_to_cpu(&report[i + 3]);
+ i += 4;
+ }
+ } else if (usage == WCM_DIGITIZER) {
+ /* max pressure isn't reported
+ features->pressure_max = (unsigned short)
+ (report[i+4] << 8 | report[i + 3]);
+ */
+ features->pressure_max = 255;
+ i += 4;
+ }
+ break;
+
+ case HID_USAGE_Y:
+ if (usage == WCM_DESKTOP)
+ features->y_max =
+ wacom_le16_to_cpu(&report[i + 3]);
+ i += 4;
+ break;
+
+ case HID_USAGE_FINGER:
+ finger = 1;
+ i++;
+ break;
+
+ case HID_USAGE_STYLUS:
+ pen = 1;
+ i++;
+ break;
+
+ case HID_USAGE_UNDEFINED:
+ if (usage == WCM_DESKTOP && finger) /* capacity */
+ features->pressure_max =
+ wacom_le16_to_cpu(&report[i + 3]);
+ i += 4;
+ break;
+ }
+ break;
+
+ case HID_COLLECTION:
+ /* reset UsagePage ans Finger */
+ finger = usage = 0;
+ break;
+ }
+ }
+
+ result = 0;
+
+ out:
+ kfree(report);
+ return result;
+}
+
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_host_interface *interface = intf->cur_altsetting;
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
struct wacom_wac *wacom_wac;
+ struct wacom_features *features;
struct input_dev *input_dev;
int error = -ENOMEM;
char rep_data[2], limit = 0;
+ struct hid_descriptor *hid_desc;
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
- wacom_wac->features = get_wacom_feature(id);
- BUG_ON(wacom_wac->features->pktlen > 10);
+ wacom_wac->features = features = get_wacom_feature(id);
+ BUG_ON(features->pktlen > 10);
input_dev->name = wacom_wac->features->name;
wacom->wacom_wac = wacom_wac;
input_dev->open = wacom_open;
input_dev->close = wacom_close;
+ endpoint = &intf->cur_altsetting->endpoint[0].desc;
+
+ /* TabletPC need to retrieve the physical and logical maximum from report descriptor */
+ if (wacom_wac->features->type == TABLETPC) {
+ if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
+ if (usb_get_extra_descriptor(&interface->endpoint[0],
+ HID_DEVICET_REPORT, &hid_desc)) {
+ printk("wacom: can not retrive extra class descriptor\n");
+ goto fail2;
+ }
+ }
+ error = wacom_parse_hid(intf, hid_desc, wacom_wac);
+ if (error)
+ goto fail2;
+ }
+
input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS);
- input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0);
- input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
+ if (features->type == TABLETPC) {
+ input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
+ input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0);
+ input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0);
+ }
input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
wacom_init_input_dev(input_dev, wacom_wac);
- endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
usb_fill_int_urb(wacom->irq, dev,
usb_rcvintpipe(dev, endpoint->bEndpointAddress),
wacom_wac->data, wacom_wac->features->pktlen,
if (error)
goto fail3;
- /* Ask the tablet to report tablet data. Repeat until it succeeds */
- do {
- rep_data[0] = 2;
- rep_data[1] = 2;
- usb_set_report(intf, 3, 2, rep_data, 2);
- usb_get_report(intf, 3, 2, rep_data, 2);
- } while (rep_data[1] != 2 && limit++ < 5);
+ /*
+ * Ask the tablet to report tablet data if it is not a Tablet PC.
+ * Repeat until it succeeds
+ */
+ if (wacom_wac->features->type != TABLETPC) {
+ do {
+ rep_data[0] = 2;
+ rep_data[1] = 2;
+ error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
+ 2, rep_data, 2);
+ if (error >= 0)
+ error = usb_get_report(intf,
+ WAC_HID_FEATURE_REPORT, 2,
+ rep_data, 2);
+ } while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+ }
usb_set_intfdata(intf, wacom);
return 0;
usb_kill_urb(wacom->irq);
input_unregister_device(wacom->dev);
usb_free_urb(wacom->irq);
- usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
+ usb_buffer_free(interface_to_usbdev(intf), 10,
+ wacom->wacom_wac->data, wacom->data_dma);
kfree(wacom->wacom_wac);
kfree(wacom);
}
return 1;
}
+int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
+{
+ char *data = wacom->data;
+ int prox = 0, pressure;
+ static int stylusInProx, touchInProx = 1, touchOut;
+ struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
+
+ dbg("wacom_tpc_irq: received report #%d", data[0]);
+
+ if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */
+ if (urb->actual_length == 5) { /* with touch */
+ prox = data[0] & 0x03;
+ } else { /* with capacity */
+ prox = data[1] & 0x03;
+ }
+
+ if (!stylusInProx) { /* stylus not in prox */
+ if (prox) {
+ if (touchInProx) {
+ wacom->tool[1] = BTN_TOOL_DOUBLETAP;
+ wacom->id[0] = TOUCH_DEVICE_ID;
+ if (urb->actual_length != 5) {
+ wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
+ wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
+ wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
+ wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
+ } else {
+ wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
+ wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+ wacom_report_key(wcombo, BTN_TOUCH, 1);
+ }
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+ wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
+ touchOut = 1;
+ return 1;
+ }
+ } else {
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+ wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
+ wacom_report_key(wcombo, BTN_TOUCH, 0);
+ touchOut = 0;
+ touchInProx = 1;
+ return 1;
+ }
+ } else if (touchOut || !prox) { /* force touch out-prox */
+ wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+ wacom_report_key(wcombo, BTN_TOUCH, 0);
+ touchOut = 0;
+ touchInProx = 1;
+ return 1;
+ }
+ } else if (data[0] == 2) { /* Penabled */
+ prox = data[1] & 0x20;
+
+ touchInProx = 0;
+
+ wacom->id[0] = ERASER_DEVICE_ID;
+
+ /*
+ * if going from out of proximity into proximity select between the eraser
+ * and the pen based on the state of the stylus2 button, choose eraser if
+ * pressed else choose pen. if not a proximity change from out to in, send
+ * an out of proximity for previous tool then a in for new tool.
+ */
+ if (prox) { /* in prox */
+ if (!wacom->tool[0]) {
+ /* Going into proximity select tool */
+ wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+ if (wacom->tool[1] == BTN_TOOL_PEN)
+ wacom->id[0] = STYLUS_DEVICE_ID;
+ } else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) {
+ /*
+ * was entered with stylus2 pressed
+ * report out proximity for previous tool
+ */
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+ wacom_report_key(wcombo, wacom->tool[1], 0);
+ wacom_input_sync(wcombo);
+
+ /* set new tool */
+ wacom->tool[1] = BTN_TOOL_PEN;
+ wacom->id[0] = STYLUS_DEVICE_ID;
+ return 0;
+ }
+ if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+ /* Unknown tool selected default to pen tool */
+ wacom->tool[1] = BTN_TOOL_PEN;
+ wacom->id[0] = STYLUS_DEVICE_ID;
+ }
+ wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
+ wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
+ wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
+ wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
+ pressure = ((data[7] & 0x01) << 8) | data[6];
+ if (pressure < 0)
+ pressure = wacom->features->pressure_max + pressure + 1;
+ wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
+ wacom_report_key(wcombo, BTN_TOUCH, pressure);
+ } else {
+ wacom_report_abs(wcombo, ABS_PRESSURE, 0);
+ wacom_report_key(wcombo, BTN_STYLUS, 0);
+ wacom_report_key(wcombo, BTN_STYLUS2, 0);
+ wacom_report_key(wcombo, BTN_TOUCH, 0);
+ }
+ wacom_report_key(wcombo, wacom->tool[1], prox);
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+ stylusInProx = prox;
+ wacom->tool[0] = prox;
+ return 1;
+ }
+ return 0;
+}
+
int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
{
switch (wacom_wac->features->type) {
case PENPARTNER:
- return (wacom_penpartner_irq(wacom_wac, wcombo));
- break;
+ return wacom_penpartner_irq(wacom_wac, wcombo);
+
case PL:
- return (wacom_pl_irq(wacom_wac, wcombo));
- break;
+ return wacom_pl_irq(wacom_wac, wcombo);
+
case WACOM_G4:
case GRAPHIRE:
case WACOM_MO:
- return (wacom_graphire_irq(wacom_wac, wcombo));
- break;
+ return wacom_graphire_irq(wacom_wac, wcombo);
+
case PTU:
- return (wacom_ptu_irq(wacom_wac, wcombo));
- break;
+ return wacom_ptu_irq(wacom_wac, wcombo);
+
case INTUOS:
case INTUOS3S:
case INTUOS3:
case INTUOS3L:
case CINTIQ:
case WACOM_BEE:
- return (wacom_intuos_irq(wacom_wac, wcombo));
- break;
+ return wacom_intuos_irq(wacom_wac, wcombo);
+
+ case TABLETPC:
+ return wacom_tpc_irq(wacom_wac, wcombo);
+
default:
return 0;
}
/* fall through */
case INTUOS3S:
input_dev_i3s(input_dev, wacom_wac);
+ /* fall through */
case INTUOS:
input_dev_i(input_dev, wacom_wac);
break;
case PL:
case PTU:
+ case TABLETPC:
input_dev_pl(input_dev, wacom_wac);
- break;
+ /* fall through */
case PENPARTNER:
input_dev_pt(input_dev, wacom_wac);
break;
{ "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 },
{ "Wacom BambooFun 4x5", 9, 14760, 9225, 511, 63, WACOM_MO },
{ "Wacom BambooFun 6x8", 9, 21648, 13530, 511, 63, WACOM_MO },
+ { "Wacom Bamboo1 Medium",8, 16704, 12064, 511, 63, GRAPHIRE },
{ "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE },
{ "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE },
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ },
{ "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE },
{ "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE },
+ { "Wacom DTU1931", 8, 37832, 30305, 511, 0, PL },
+ { "Wacom ISDv4 90", 8, 26202, 16325, 255, 0, TABLETPC },
+ { "Wacom ISDv4 93", 8, 26202, 16325, 255, 0, TABLETPC },
+ { "Wacom ISDv4 9A", 8, 26202, 16325, 255, 0, TABLETPC },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
{ }
};
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
{ }
};
-const struct usb_device_id * get_device_table(void) {
- const struct usb_device_id * id_table = wacom_ids;
+const struct usb_device_id *get_device_table(void)
+{
+ const struct usb_device_id *id_table = wacom_ids;
+
return id_table;
}
-struct wacom_features * get_wacom_feature(const struct usb_device_id * id) {
+struct wacom_features * get_wacom_feature(const struct usb_device_id *id)
+{
int index = id - wacom_ids;
struct wacom_features *wf = &wacom_features[index];
+
return wf;
}
#define WACOM_WAC_H
#define STYLUS_DEVICE_ID 0x02
+#define TOUCH_DEVICE_ID 0x03
#define CURSOR_DEVICE_ID 0x06
#define ERASER_DEVICE_ID 0x0A
#define PAD_DEVICE_ID 0x0F
CINTIQ,
WACOM_BEE,
WACOM_MO,
+ TABLETPC,
MAX_TYPE
};
int pressure_max;
int distance_max;
int type;
+ int touch_x_max;
+ int touch_y_max;
};
struct wacom_wac {
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, "
- "features: %x02x, controller: 0x%02x\n",
+ "features: 0x%02x, controller: 0x%02x\n",
elo_types[(packet[1] -'0') & 0x03],
packet[5], packet[4], packet[3], packet[7]);
{ "" }
};
-static struct xenbus_driver xenkbd = {
+static struct xenbus_driver xenkbd_driver = {
.name = "vkbd",
.owner = THIS_MODULE,
.ids = xenkbd_ids,
if (xen_initial_domain())
return -ENODEV;
- return xenbus_register_frontend(&xenkbd);
+ return xenbus_register_frontend(&xenkbd_driver);
}
static void __exit xenkbd_cleanup(void)
{
- xenbus_unregister_driver(&xenkbd);
+ xenbus_unregister_driver(&xenkbd_driver);
}
module_init(xenkbd_init);
memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
}
-static int HiSax_inithardware(int *busy_flag)
+static int __init HiSax_inithardware(int *busy_flag)
{
int foundcards = 0;
int i = 0;
printk(KERN_INFO "HiSax module removed\n");
}
-int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
+#ifdef CONFIG_HOTPLUG
+
+int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
{
u_char ids[16];
int ret = -1;
}
EXPORT_SYMBOL(hisax_init_pcmcia);
+#endif
+
EXPORT_SYMBOL(HiSax_closecard);
#include "hisax_if.h"
static void hisax_bh(struct work_struct *work);
static void EChannel_proc_rcv(struct hisax_d_if *d_if);
+static int hisax_setup_card_dynamic(struct IsdnCard *card)
+{
+ return 2;
+}
+
int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
char *name, int protocol)
{
cards[i].protocol = protocol;
sprintf(id, "%s%d", name, i);
nrcards++;
- retval = checkcard(i, id, NULL, hisax_d_if->owner, hisax_cs_setup_card);
+ retval = checkcard(i, id, NULL, hisax_d_if->owner,
+ hisax_setup_card_dynamic);
if (retval == 0) { // yuck
cards[i].typ = 0;
nrcards--;
cancel_rearming_delayed_work(&rm->cpu[1].sniffer);
}
-static int rackmeter_setup(struct rackmeter *rm)
+static int __devinit rackmeter_setup(struct rackmeter *rm)
{
pr_debug("rackmeter: setting up i2s..\n");
rackmeter_setup_i2s(rm);
{ }
};
-static struct macio_driver rackmeter_drv = {
+static struct macio_driver rackmeter_driver = {
.name = "rackmeter",
.owner = THIS_MODULE,
.match_table = rackmeter_match,
.probe = rackmeter_probe,
- .remove = rackmeter_remove,
+ .remove = __devexit_p(rackmeter_remove),
.shutdown = rackmeter_shutdown,
};
{
pr_debug("rackmeter_init()\n");
- return macio_register_driver(&rackmeter_drv);
+ return macio_register_driver(&rackmeter_driver);
}
static void __exit rackmeter_exit(void)
{
pr_debug("rackmeter_exit()\n");
- macio_unregister_driver(&rackmeter_drv);
+ macio_unregister_driver(&rackmeter_driver);
}
module_init(rackmeter_init);
goto outinput;
}
- if (!acpi_video_backlight_support()) {
- printk(KERN_INFO DRV_PFX "Sony: Brightness ignored, must be "
+ if (acpi_video_backlight_support()) {
+ printk(KERN_INFO DRV_PFX "brightness ignored, must be "
"controlled by ACPI video driver\n");
} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
&handle))) {
static u8 fan_control_initial_status;
static u8 fan_control_desired_level;
+static u8 fan_control_resume_level;
static int fan_watchdog_maxinterval;
static struct mutex fan_mutex;
case TPACPI_FAN_WR_ACPI_FANS:
case TPACPI_FAN_WR_TPEC:
- if ((level != TP_EC_FAN_AUTO) &&
- (level != TP_EC_FAN_FULLSPEED) &&
+ if (!(level & TP_EC_FAN_AUTO) &&
+ !(level & TP_EC_FAN_FULLSPEED) &&
((level < 0) || (level > 7)))
return -EINVAL;
static void fan_suspend(pm_message_t state)
{
+ int rc;
+
if (!fan_control_allowed)
return;
/* Store fan status in cache */
- fan_get_status_safe(NULL);
+ fan_control_resume_level = 0;
+ rc = fan_get_status_safe(&fan_control_resume_level);
+ if (rc < 0)
+ printk(TPACPI_NOTICE
+ "failed to read fan level for later "
+ "restore during resume: %d\n", rc);
+
+ /* if it is undefined, don't attempt to restore it.
+ * KEEP THIS LAST */
if (tp_features.fan_ctrl_status_undef)
- fan_control_desired_level = TP_EC_FAN_AUTO;
+ fan_control_resume_level = 0;
}
static void fan_resume(void)
{
- u8 saved_fan_level;
u8 current_level = 7;
bool do_set = false;
+ int rc;
/* DSDT *always* updates status on resume */
tp_features.fan_ctrl_status_undef = 0;
- saved_fan_level = fan_control_desired_level;
if (!fan_control_allowed ||
+ !fan_control_resume_level ||
(fan_get_status_safe(¤t_level) < 0))
return;
switch (fan_control_access_mode) {
case TPACPI_FAN_WR_ACPI_SFAN:
- do_set = (saved_fan_level > current_level);
+ /* never decrease fan level */
+ do_set = (fan_control_resume_level > current_level);
break;
case TPACPI_FAN_WR_ACPI_FANS:
case TPACPI_FAN_WR_TPEC:
- do_set = ((saved_fan_level & TP_EC_FAN_FULLSPEED) ||
- (saved_fan_level == 7 &&
- !(current_level & TP_EC_FAN_FULLSPEED)));
+ /* never decrease fan level, scale is:
+ * TP_EC_FAN_FULLSPEED > 7 >= TP_EC_FAN_AUTO
+ *
+ * We expect the firmware to set either 7 or AUTO, but we
+ * handle FULLSPEED out of paranoia.
+ *
+ * So, we can safely only restore FULLSPEED or 7, anything
+ * else could slow the fan. Restoring AUTO is useless, at
+ * best that's exactly what the DSDT already set (it is the
+ * slower it uses).
+ *
+ * Always keep in mind that the DSDT *will* have set the
+ * fans to what the vendor supposes is the best level. We
+ * muck with it only to speed the fan up.
+ */
+ if (fan_control_resume_level != 7 &&
+ !(fan_control_resume_level & TP_EC_FAN_FULLSPEED))
+ return;
+ else
+ do_set = !(current_level & TP_EC_FAN_FULLSPEED) &&
+ (current_level != fan_control_resume_level);
break;
default:
return;
if (do_set) {
printk(TPACPI_NOTICE
"restoring fan level to 0x%02x\n",
- saved_fan_level);
- fan_set_level_safe(saved_fan_level);
+ fan_control_resume_level);
+ rc = fan_set_level_safe(fan_control_resume_level);
+ if (rc < 0)
+ printk(TPACPI_NOTICE
+ "failed to restore fan level: %d\n", rc);
}
}
}
/*
- * OK, now the LEB is locked and we can safely start moving iy. Since
+ * OK, now the LEB is locked and we can safely start moving it. Since
* this function utilizes thie @ubi->peb1_buf buffer which is shared
* with some other functions, so lock the buffer by taking the
* @ubi->buf_mutex.
}
err = ubi_io_read_data(ubi, buf, pnum, 0, len);
- if (err && err != UBI_IO_BITFLIPS)
+ if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
goto out_free_buf;
data_crc = be32_to_cpu(vid_hdr->data_crc);
ubi_msg("%s: %d consecutive failures",
ubi->bgt_name, WL_MAX_FAILURES);
ubi_ro_mode(ubi);
- break;
+ ubi->thread_enabled = 0;
+ continue;
}
} else
failures = 0;
config FEC_MPC52xx
tristate "MPC52xx FEC driver"
- depends on PPC_MPC52xx && PPC_BESTCOMM_FEC
+ depends on PPC_MPC52xx && PPC_BESTCOMM
select CRC32
select PHYLIB
+ select PPC_BESTCOMM_FEC
---help---
This option enables support for the MPC5200's on-chip
Fast Ethernet Controller
* Once we know the feature-set enabled for the device, we'll cache
* the register offset the descriptor ring is assigned to.
**/
-static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
+static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
{
int feature_mask = 0, rss_i;
int i, txr_idx, rxr_idx;
* number of queues at compile-time. The polling_netdev array is
* intended for Multiqueue, but should work fine with a single queue.
**/
-static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
+static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
{
int i;
* Attempt to configure the interrupts using the best available
* capabilities of the hardware and the kernel.
**/
-static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
- *adapter)
+static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
{
int err = 0;
int vector, v_budget;
* - Hardware queue count (num_*_queues)
* - defined by miscellaneous hardware support/features (RSS, etc.)
**/
-static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
+static int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
{
int err;
return 0;
}
-static int ibmtr_resume(struct pcmcia_device *link)
+static int __devinit ibmtr_resume(struct pcmcia_device *link)
{
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
* This routine has a simple purpose -- make the SMC chip generate an
* interrupt, so an auto-detect routine can detect it, and find the IRQ,
*/
-static int __init smc911x_findirq(struct net_device *dev)
+static int __devinit smc911x_findirq(struct net_device *dev)
{
struct smc911x_local *lp = netdev_priv(dev);
int timeout = 20;
* o actually GRAB the irq.
* o GRAB the region
*/
-static int __init smc911x_probe(struct net_device *dev)
+static int __devinit smc911x_probe(struct net_device *dev)
{
struct smc911x_local *lp = netdev_priv(dev);
int i, retval;
* 0 --> there is a device
* anything else, error
*/
-static int smc911x_drv_probe(struct platform_device *pdev)
+static int __devinit smc911x_drv_probe(struct platform_device *pdev)
{
#ifdef SMC_DYNAMIC_BUS_CONFIG
struct smc911x_platdata *pd = pdev->dev.platform_data;
return ret;
}
-static int smc911x_drv_remove(struct platform_device *pdev)
+static int __devexit smc911x_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct smc911x_local *lp = netdev_priv(ndev);
static struct platform_driver smc911x_driver = {
.probe = smc911x_drv_probe,
- .remove = smc911x_drv_remove,
+ .remove = __devexit_p(smc911x_drv_remove),
.suspend = smc911x_drv_suspend,
.resume = smc911x_drv_resume,
.driver = {
* I just deleted auto_irq.c, since it was never built...
* --jgarzik
*/
-static int __init smc_findirq(struct smc_local *lp)
+static int __devinit smc_findirq(struct smc_local *lp)
{
void __iomem *ioaddr = lp->base;
int timeout = 20;
* o actually GRAB the irq.
* o GRAB the region
*/
-static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr,
unsigned long irq_flags)
{
struct smc_local *lp = netdev_priv(dev);
* 0 --> there is a device
* anything else, error
*/
-static int smc_drv_probe(struct platform_device *pdev)
+static int __devinit smc_drv_probe(struct platform_device *pdev)
{
struct smc91x_platdata *pd = pdev->dev.platform_data;
struct smc_local *lp;
return ret;
}
-static int smc_drv_remove(struct platform_device *pdev)
+static int __devexit smc_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct smc_local *lp = netdev_priv(ndev);
static struct platform_driver smc_driver = {
.probe = smc_drv_probe,
- .remove = smc_drv_remove,
+ .remove = __devexit_p(smc_drv_remove),
.suspend = smc_drv_suspend,
.resume = smc_drv_resume,
.driver = {
return 0;
}
-static struct xenbus_driver netfront = {
+static struct xenbus_driver netfront_driver = {
.name = "vif",
.owner = THIS_MODULE,
.ids = netfront_ids,
printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n");
- return xenbus_register_frontend(&netfront);
+ return xenbus_register_frontend(&netfront_driver);
}
module_init(netif_init);
if (xen_initial_domain())
return;
- xenbus_unregister_driver(&netfront);
+ xenbus_unregister_driver(&netfront_driver);
}
module_exit(netif_exit);
return 0;
}
-static int __devinit pci_setup(char *str)
+static int __init pci_setup(char *str)
{
while (str) {
char *k = strchr(str, ',');
* link, then start recursive peer enumeration. Returns %0 if
* enumeration succeeds or %-EBUSY if enumeration fails.
*/
-int rio_enum_mport(struct rio_mport *mport)
+int __devinit rio_enum_mport(struct rio_mport *mport)
{
struct rio_net *net = NULL;
int rc = 0;
* peer discovery. Returns %0 if discovery succeeds or %-EBUSY
* on failure.
*/
-int rio_disc_mport(struct rio_mport *mport)
+int __devinit rio_disc_mport(struct rio_mport *mport)
{
struct rio_net *net = NULL;
int enum_timeout_flag = 0;
device_initcall(rio_init);
-int rio_init_mports(void)
+int __devinit rio_init_mports(void)
{
int rc = 0;
struct rio_mport *port;
advansys_wide_free_mem(boardp);
free_irq(boardp->irq, shost);
err_free_dma:
+#ifdef CONFIG_ISA
if (shost->dma_channel != NO_ISA_DMA)
free_dma(shost->dma_channel);
+#endif
err_free_proc:
kfree(boardp->prtbuf);
err_unmap:
ASC_DBG(1, "begin\n");
scsi_remove_host(shost);
free_irq(board->irq, shost);
+#ifdef CONFIG_ISA
if (shost->dma_channel != NO_ISA_DMA) {
ASC_DBG(1, "free_dma()\n");
free_dma(shost->dma_channel);
}
+#endif
if (ASC_NARROW_BOARD(board)) {
dma_unmap_single(board->dev,
board->dvc_var.asc_dvc_var.overrun_dma,
.remove = gdth_pci_remove_one,
};
-static void gdth_pci_remove_one(struct pci_dev *pdev)
+static void __devexit gdth_pci_remove_one(struct pci_dev *pdev)
{
gdth_ha_str *ha = pci_get_drvdata(pdev);
pci_disable_device(pdev);
}
-static int gdth_pci_init_one(struct pci_dev *pdev,
+static int __devinit gdth_pci_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
ushort vendor = pdev->vendor;
#endif /* CONFIG_ISA */
#ifdef CONFIG_PCI
-static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
+static int __devinit gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
gdth_ha_str *ha)
{
register gdt6_dpram_str __iomem *dp6_ptr;
/* controller protocol functions */
-static void __init gdth_enable_int(gdth_ha_str *ha)
+static void __devinit gdth_enable_int(gdth_ha_str *ha)
{
ulong flags;
gdt2_dpram_str __iomem *dp2_ptr;
/* search for devices */
-static int __init gdth_search_drives(gdth_ha_str *ha)
+static int __devinit gdth_search_drives(gdth_ha_str *ha)
{
ushort cdev_cnt, i;
int ok;
#endif /* CONFIG_EISA */
#ifdef CONFIG_PCI
-static int gdth_pci_probe_one(gdth_pci_str *pcistr,
+static int __devinit gdth_pci_probe_one(gdth_pci_str *pcistr,
gdth_ha_str **ha_out)
{
struct Scsi_Host *shp;
static int ulite_request_port(struct uart_port *port)
{
- pr_debug("ulite console: port=%p; port->mapbase=%x\n",
- port, port->mapbase);
+ pr_debug("ulite console: port=%p; port->mapbase=%llx\n",
+ port, (unsigned long long) port->mapbase);
if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) {
dev_err(port->dev, "Memory region busy\n");
nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc_controller->lock, flags);
+ /* report disconnect; the controller is already quiesced */
+ driver->disconnect(&udc_controller->gadget);
+
/* unbind gadget and unhook driver. */
driver->unbind(&udc_controller->gadget);
udc_controller->gadget.dev.driver = NULL;
nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc_controller->lock, flags);
+ /* report disconnect; the controller is already quiesced */
+ driver->disconnect(&udc_controller->gadget);
+
/* unbind gadget and unhook driver. */
driver->unbind(&udc_controller->gadget);
udc_controller->gadget.dev.driver = NULL;
if (mach->gpio_vbus) {
int value = gpio_get_value(mach->gpio_vbus);
- return mach->gpio_vbus_inverted ? !value : value;
+
+ if (mach->gpio_vbus_inverted)
+ return !value;
+ else
+ return !!value;
}
if (mach->udc_is_connected)
return mach->udc_is_connected();
struct pxa25x_udc *udc;
udc = container_of(_gadget, struct pxa25x_udc, gadget);
- udc->vbus = (is_active != 0);
+ udc->vbus = is_active;
DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
pullup(udc);
return 0;
static irqreturn_t udc_vbus_irq(int irq, void *_dev)
{
struct pxa25x_udc *dev = _dev;
- int vbus = gpio_get_value(dev->mach->gpio_vbus);
- if (dev->mach->gpio_vbus_inverted)
- vbus = !vbus;
-
- pxa25x_udc_vbus_session(&dev->gadget, vbus);
+ pxa25x_udc_vbus_session(&dev->gadget, is_vbus_present());
return IRQ_HANDLED;
}
}
break;
case PCI_VENDOR_ID_ATI:
- /* SB700 old version has a bug in EHCI controller,
+ /* SB600 and old version of SB700 have a bug in EHCI controller,
* which causes usb devices lose response in some cases.
*/
- if (pdev->device == 0x4396) {
+ if ((pdev->device == 0x4386) || (pdev->device == 0x4396)) {
p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
PCI_DEVICE_ID_ATI_SBX00_SMBUS,
NULL);
if (!p_smbus)
break;
rev = p_smbus->revision;
- if ((rev == 0x3a) || (rev == 0x3b)) {
+ if ((pdev->device == 0x4386) || (rev == 0x3a)
+ || (rev == 0x3b)) {
u8 tmp;
+ ehci_info(ehci, "applying AMD SB600/SB700 USB "
+ "freeze workaround\n");
pci_read_config_byte(pdev, 0x53, &tmp);
pci_write_config_byte(pdev, 0x53, tmp | (1<<3));
}
* the async ring; just the I/O watchdog. Note that if a
* SHRINK were pending, OFF would never be requested.
*/
- enum ehci_timer_action oldactions = ehci->actions;
+ if (timer_pending(&ehci->watchdog)
+ && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
+ & ehci->actions))
+ return;
if (!test_and_set_bit (action, &ehci->actions)) {
unsigned long t;
- if (timer_pending(&ehci->watchdog)
- && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
- & oldactions))
- return;
-
switch (action) {
case TIMER_IO_WATCHDOG:
t = EHCI_IO_JIFFIES;
t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
break;
}
- mod_timer(&ehci->watchdog, round_jiffies(t + jiffies));
+ mod_timer(&ehci->watchdog, t + jiffies);
}
}
err("no more memory");
goto reset_open_count;
}
+ kref_init(&tty->kref);
termios = kzalloc(sizeof(*termios), GFP_KERNEL);
if (!termios) {
retval = -ENOMEM;
#define ONDA_VENDOR_ID 0x19d2
#define ONDA_PRODUCT_MSA501HS 0x0001
#define ONDA_PRODUCT_ET502HS 0x0002
+#define ONDA_PRODUCT_MT503HS 0x0200
#define BANDRICH_VENDOR_ID 0x1A8D
#define BANDRICH_PRODUCT_C100_1 0x1002
{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) },
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0003) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0004) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0005) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0006) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0007) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0008) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0009) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000a) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000b) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000c) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000d) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000e) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x000f) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0010) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0011) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0012) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0013) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0014) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0015) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0016) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0017) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0018) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0019) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0020) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0021) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0022) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0023) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0024) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0025) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0026) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0027) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0028) },
+ { USB_DEVICE(ONDA_VENDOR_ID, 0x0029) },
+ { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MT503HS) },
{ USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
#endif
+/* Reported by Tamas Kerecsen <kerecsen@bigfoot.com>
+ * Obviously the PROM has not been customized by the VAR;
+ * the Vendor and Product string descriptors are:
+ * Generic Mass Storage (PROTOTYPE--Remember to change idVendor)
+ * Generic Manufacturer (PROTOTYPE--Remember to change idVendor)
+ */
+UNUSUAL_DEV( 0x045e, 0xffff, 0x0000, 0x0000,
+ "Mitac",
+ "GPS",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64 ),
+
/*
* This virtual floppy is found in Sun equipment (x4600, x4200m2, etc.)
* Reported by Pete Zaitcev <zaitcev@redhat.com>
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
+/* Reported by Tobias Kunze Briseno <t-linux@fictive.com> */
+UNUSUAL_DEV( 0x04b0, 0x0403, 0x0200, 0x0200,
+ "NIKON",
+ "NIKON DSC D2H",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
/* Reported by Milinevsky Dmitry <niam.niam@gmail.com> */
UNUSUAL_DEV( 0x04b0, 0x0409, 0x0100, 0x0100,
"NIKON",
objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
-objs-y$(CONFIG_MACH_SX1) += lcd_sx1.o
omapfb-objs := $(objs-yy)
+++ /dev/null
-/*
- * LCD panel support for the Siemens SX1 mobile phone
- *
- * Current version : Vovan888@gmail.com, great help from FCA00000
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <mach/gpio.h>
-#include <mach/omapfb.h>
-#include <mach/mcbsp.h>
-#include <mach/mux.h>
-
-/*
- * OMAP310 GPIO registers
- */
-#define GPIO_DATA_INPUT 0xfffce000
-#define GPIO_DATA_OUTPUT 0xfffce004
-#define GPIO_DIR_CONTROL 0xfffce008
-#define GPIO_INT_CONTROL 0xfffce00c
-#define GPIO_INT_MASK 0xfffce010
-#define GPIO_INT_STATUS 0xfffce014
-#define GPIO_PIN_CONTROL 0xfffce018
-
-
-#define A_LCD_SSC_RD 3
-#define A_LCD_SSC_SD 7
-#define _A_LCD_RESET 9
-#define _A_LCD_SSC_CS 12
-#define _A_LCD_SSC_A0 13
-
-#define DSP_REG 0xE1017024
-
-const unsigned char INIT_1[12] = {
- 0x1C, 0x02, 0x88, 0x00, 0x1E, 0xE0, 0x00, 0xDC, 0x00, 0x02, 0x00
-};
-
-const unsigned char INIT_2[127] = {
- 0x15, 0x00, 0x29, 0x00, 0x3E, 0x00, 0x51, 0x00,
- 0x65, 0x00, 0x7A, 0x00, 0x8D, 0x00, 0xA1, 0x00,
- 0xB6, 0x00, 0xC7, 0x00, 0xD8, 0x00, 0xEB, 0x00,
- 0xFB, 0x00, 0x0B, 0x01, 0x1B, 0x01, 0x27, 0x01,
- 0x34, 0x01, 0x41, 0x01, 0x4C, 0x01, 0x55, 0x01,
- 0x5F, 0x01, 0x68, 0x01, 0x70, 0x01, 0x78, 0x01,
- 0x7E, 0x01, 0x86, 0x01, 0x8C, 0x01, 0x94, 0x01,
- 0x9B, 0x01, 0xA1, 0x01, 0xA4, 0x01, 0xA9, 0x01,
- 0xAD, 0x01, 0xB2, 0x01, 0xB7, 0x01, 0xBC, 0x01,
- 0xC0, 0x01, 0xC4, 0x01, 0xC8, 0x01, 0xCB, 0x01,
- 0xCF, 0x01, 0xD2, 0x01, 0xD5, 0x01, 0xD8, 0x01,
- 0xDB, 0x01, 0xE0, 0x01, 0xE3, 0x01, 0xE6, 0x01,
- 0xE8, 0x01, 0xEB, 0x01, 0xEE, 0x01, 0xF1, 0x01,
- 0xF3, 0x01, 0xF8, 0x01, 0xF9, 0x01, 0xFC, 0x01,
- 0x00, 0x02, 0x03, 0x02, 0x07, 0x02, 0x09, 0x02,
- 0x0E, 0x02, 0x13, 0x02, 0x1C, 0x02, 0x00
-};
-
-const unsigned char INIT_3[15] = {
- 0x14, 0x26, 0x33, 0x3D, 0x45, 0x4D, 0x53, 0x59,
- 0x5E, 0x63, 0x67, 0x6D, 0x71, 0x78, 0xFF
-};
-
-static void epson_sendbyte(int flag, unsigned char byte)
-{
- int i, shifter = 0x80;
-
- if (!flag)
- gpio_set_value(_A_LCD_SSC_A0, 0);
- mdelay(2);
- gpio_set_value(A_LCD_SSC_RD, 1);
-
- gpio_set_value(A_LCD_SSC_SD, flag);
-
- OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
- OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
- for (i = 0; i < 8; i++) {
- OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
- gpio_set_value(A_LCD_SSC_SD, shifter & byte);
- OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
- shifter >>= 1;
- }
- gpio_set_value(_A_LCD_SSC_A0, 1);
-}
-
-static void init_system(void)
-{
- omap_mcbsp_request(OMAP_MCBSP3);
- omap_mcbsp_stop(OMAP_MCBSP3);
-}
-
-static void setup_GPIO(void)
-{
- /* new wave */
- gpio_request(A_LCD_SSC_RD, "lcd_ssc_rd");
- gpio_request(A_LCD_SSC_SD, "lcd_ssc_sd");
- gpio_request(_A_LCD_RESET, "lcd_reset");
- gpio_request(_A_LCD_SSC_CS, "lcd_ssc_cs");
- gpio_request(_A_LCD_SSC_A0, "lcd_ssc_a0");
-
- /* set GPIOs to output, with initial data */
- gpio_direction_output(A_LCD_SSC_RD, 1);
- gpio_direction_output(A_LCD_SSC_SD, 0);
- gpio_direction_output(_A_LCD_RESET, 0);
- gpio_direction_output(_A_LCD_SSC_CS, 1);
- gpio_direction_output(_A_LCD_SSC_A0, 1);
-}
-
-static void display_init(void)
-{
- int i;
-
- omap_cfg_reg(MCBSP3_CLKX);
-
- mdelay(2);
- setup_GPIO();
- mdelay(2);
-
- /* reset LCD */
- gpio_set_value(A_LCD_SSC_SD, 1);
- epson_sendbyte(0, 0x25);
-
- gpio_set_value(_A_LCD_RESET, 0);
- mdelay(10);
- gpio_set_value(_A_LCD_RESET, 1);
-
- gpio_set_value(_A_LCD_SSC_CS, 1);
- mdelay(2);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD, phase 1 */
- epson_sendbyte(0, 0xCA);
- for (i = 0; i < 10; i++)
- epson_sendbyte(1, INIT_1[i]);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 2 */
- epson_sendbyte(0, 0xCB);
- for (i = 0; i < 125; i++)
- epson_sendbyte(1, INIT_2[i]);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 2a */
- epson_sendbyte(0, 0xCC);
- for (i = 0; i < 14; i++)
- epson_sendbyte(1, INIT_3[i]);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 3 */
- epson_sendbyte(0, 0xBC);
- epson_sendbyte(1, 0x08);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 4 */
- epson_sendbyte(0, 0x07);
- epson_sendbyte(1, 0x05);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 5 */
- epson_sendbyte(0, 0x94);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 6 */
- epson_sendbyte(0, 0xC6);
- epson_sendbyte(1, 0x80);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- mdelay(100); /* used to be 1000 */
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 7 */
- epson_sendbyte(0, 0x16);
- epson_sendbyte(1, 0x02);
- epson_sendbyte(1, 0x00);
- epson_sendbyte(1, 0xB1);
- epson_sendbyte(1, 0x00);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 8 */
- epson_sendbyte(0, 0x76);
- epson_sendbyte(1, 0x00);
- epson_sendbyte(1, 0x00);
- epson_sendbyte(1, 0xDB);
- epson_sendbyte(1, 0x00);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- /* init LCD phase 9 */
- epson_sendbyte(0, 0xAF);
- gpio_set_value(_A_LCD_SSC_CS, 1);
-}
-
-static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
-{
- return 0;
-}
-
-static void sx1_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static void sx1_panel_disable(struct lcd_panel *panel)
-{
- printk(KERN_INFO "SX1: LCD panel disable\n");
- sx1_setmmipower(0);
- gpio_set_value(_A_LCD_SSC_CS, 1);
-
- epson_sendbyte(0, 0x25);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- epson_sendbyte(0, 0xAE);
- gpio_set_value(_A_LCD_SSC_CS, 1);
- mdelay(100);
- gpio_set_value(_A_LCD_SSC_CS, 0);
-
- epson_sendbyte(0, 0x95);
- gpio_set_value(_A_LCD_SSC_CS, 1);
-}
-
-static int sx1_panel_enable(struct lcd_panel *panel)
-{
- printk(KERN_INFO "lcd_sx1: LCD panel enable\n");
- init_system();
- display_init();
-
- sx1_setmmipower(1);
- sx1_setbacklight(0x18);
- sx1_setkeylight (0x06);
- return 0;
-}
-
-
-static unsigned long sx1_panel_get_caps(struct lcd_panel *panel)
-{
- return 0;
-}
-
-struct lcd_panel sx1_panel = {
- .name = "sx1",
- .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
- OMAP_LCDC_INV_HSYNC | OMAP_LCDC_INV_PIX_CLOCK |
- OMAP_LCDC_INV_OUTPUT_EN,
-
- .x_res = 176,
- .y_res = 220,
- .data_lines = 16,
- .bpp = 16,
- .hsw = 5,
- .hfp = 5,
- .hbp = 5,
- .vsw = 2,
- .vfp = 1,
- .vbp = 1,
- .pixel_clock = 1500,
-
- .init = sx1_panel_init,
- .cleanup = sx1_panel_cleanup,
- .enable = sx1_panel_enable,
- .disable = sx1_panel_disable,
- .get_caps = sx1_panel_get_caps,
-};
-
-static int sx1_panel_probe(struct platform_device *pdev)
-{
- omapfb_register_panel(&sx1_panel);
- return 0;
-}
-
-static int sx1_panel_remove(struct platform_device *pdev)
-{
- return 0;
-}
-
-static int sx1_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
- return 0;
-}
-
-static int sx1_panel_resume(struct platform_device *pdev)
-{
- return 0;
-}
-
-struct platform_driver sx1_panel_driver = {
- .probe = sx1_panel_probe,
- .remove = sx1_panel_remove,
- .suspend = sx1_panel_suspend,
- .resume = sx1_panel_resume,
- .driver = {
- .name = "lcd_sx1",
- .owner = THIS_MODULE,
- },
-};
-
-static int sx1_panel_drv_init(void)
-{
- return platform_driver_register(&sx1_panel_driver);
-}
-
-static void sx1_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&sx1_panel_driver);
-}
-
-module_init(sx1_panel_drv_init);
-module_exit(sx1_panel_drv_cleanup);
static int pxafb_smart_init(struct pxafb_info *fbi)
{
+ if (!(fbi->lccr0 | LCCR0_LCDT))
+ return 0;
+
fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi,
"lcd_refresh");
if (IS_ERR(fbi->smart_thread)) {
fbi->cmap_inverse = inf->cmap_inverse;
fbi->cmap_static = inf->cmap_static;
- switch (lcd_conn & 0xf) {
+ switch (lcd_conn & LCD_TYPE_MASK) {
case LCD_TYPE_MONO_STN:
fbi->lccr0 = LCCR0_CMS;
break;
{ "" }
};
-static struct xenbus_driver xenfb = {
+static struct xenbus_driver xenfb_driver = {
.name = "vfb",
.owner = THIS_MODULE,
.ids = xenfb_ids,
if (xen_initial_domain())
return -ENODEV;
- return xenbus_register_frontend(&xenfb);
+ return xenbus_register_frontend(&xenfb_driver);
}
static void __exit xenfb_cleanup(void)
{
- xenbus_unregister_driver(&xenfb);
+ xenbus_unregister_driver(&xenfb_driver);
}
module_init(xenfb_init);
/* Put a banner in the log (for DEBUG) */
dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs);
- dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n",
- (void*)drvdata->fb_phys, drvdata->fb_virt, fbsize);
+ dev_dbg(dev, "fb: phys=%llx, virt=%p, size=%x\n",
+ (unsigned long long) drvdata->fb_phys, drvdata->fb_virt,
+ fbsize);
return 0; /* success */
config W1_MASTER_DS1WM
tristate "Maxim DS1WM 1-wire busmaster"
- depends on W1 && ARM
+ depends on W1 && ARM && HAVE_CLK
help
Say Y here to enable the DS1WM 1-wire driver, such as that
in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like
spin_unlock(&buffer_mapping->private_lock);
}
}
+EXPORT_SYMBOL(invalidate_inode_buffers);
/*
* Remove any clean buffers from the inode's buffer list. This is called
cFYI(1, ("write_end for page %p from pos %lld with %d bytes",
page, pos, copied));
- if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
+ if (PageChecked(page)) {
+ if (copied == len)
+ SetPageUptodate(page);
+ ClearPageChecked(page);
+ } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
SetPageUptodate(page);
if (!PageUptodate(page)) {
{
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
+ loff_t page_start = pos & PAGE_MASK;
+ loff_t i_size;
+ struct page *page;
+ int rc = 0;
cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
- *pagep = __grab_cache_page(mapping, index);
- if (!*pagep)
- return -ENOMEM;
-
- if (PageUptodate(*pagep))
- return 0;
+ page = __grab_cache_page(mapping, index);
+ if (!page) {
+ rc = -ENOMEM;
+ goto out;
+ }
- /* If we are writing a full page it will be up to date,
- no need to read from the server */
- if (len == PAGE_CACHE_SIZE && flags & AOP_FLAG_UNINTERRUPTIBLE)
- return 0;
+ if (PageUptodate(page))
+ goto out;
- if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
- int rc;
+ /*
+ * If we write a full page it will be up to date, no need to read from
+ * the server. If the write is short, we'll end up doing a sync write
+ * instead.
+ */
+ if (len == PAGE_CACHE_SIZE)
+ goto out;
- /* might as well read a page, it is fast enough */
- rc = cifs_readpage_worker(file, *pagep, &offset);
+ /*
+ * optimize away the read when we have an oplock, and we're not
+ * expecting to use any of the data we'd be reading in. That
+ * is, when the page lies beyond the EOF, or straddles the EOF
+ * and the write will cover all of the existing data.
+ */
+ if (CIFS_I(mapping->host)->clientCanCacheRead) {
+ i_size = i_size_read(mapping->host);
+ if (page_start >= i_size ||
+ (offset == 0 && (pos + len) >= i_size)) {
+ zero_user_segments(page, 0, offset,
+ offset + len,
+ PAGE_CACHE_SIZE);
+ /*
+ * PageChecked means that the parts of the page
+ * to which we're not writing are considered up
+ * to date. Once the data is copied to the
+ * page, it can be set uptodate.
+ */
+ SetPageChecked(page);
+ goto out;
+ }
+ }
- /* we do not need to pass errors back
- e.g. if we do not have read access to the file
- because cifs_write_end will attempt synchronous writes
- -- shaggy */
+ if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
+ /*
+ * might as well read a page, it is fast enough. If we get
+ * an error, we don't need to return it. cifs_write_end will
+ * do a sync write instead since PG_uptodate isn't set.
+ */
+ cifs_readpage_worker(file, page, &page_start);
} else {
/* we could try using another file handle if there is one -
but how would we lock it to prevent close of that handle
racing with this read? In any case
this will be written out by write_end so is fine */
}
-
- return 0;
+out:
+ *pagep = page;
+ return rc;
}
const struct address_space_operations cifs_addr_ops = {
udf_truncate_tail_extent(inode);
unlock_kernel();
write_inode_now(inode, 0);
+ invalidate_inode_buffers(inode);
}
iinfo = UDF_I(inode);
kfree(iinfo->i_ext.i_data);
{.info = {"_BFS", 1, 0}},
{.info = {"_BIF", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER,
9,
- ACPI_RTYPE_STRING, 4, 0}}, /* fixed (9 Int),(4 Str) */
+ ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 4, 0}}, /* fixed (9 Int),(4 Str) */
{.info = {"_BLT", 3, 0}},
{.info = {"_BMC", 1, 0}},
{.info = {"_BMD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* fixed (5 Int) */
/* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */
- {.info = {"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_PACKAGE}},
+ {.info = {"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
{.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0}}, /* fixed (2 Int), but is optional */
{.ret_info = {0, 0, 0, 0, 0, 0}} /* Table terminator */
};
extern void drm_handle_vblank(struct drm_device *dev, int crtc);
extern int drm_vblank_get(struct drm_device *dev, int crtc);
extern void drm_vblank_put(struct drm_device *dev, int crtc);
+extern void drm_vblank_cleanup(struct drm_device *dev);
/* Modesetting support */
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
compat_long_t request,
compat_ulong_t addr, compat_ulong_t data);
-#ifdef __ARCH_WANT_COMPAT_SYS_PTRACE
extern long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
compat_ulong_t addr, compat_ulong_t data);
asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
compat_long_t addr, compat_long_t data);
-#endif /* __ARCH_WANT_COMPAT_SYS_PTRACE */
/*
* epoll (fs/eventpoll.c) compat bits follow ...
#endif /* CONFIG_HIGHMEM */
/* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
+#ifndef clear_user_highpage
static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
{
void *addr = kmap_atomic(page, KM_USER0);
clear_user_page(addr, vaddr, page);
kunmap_atomic(addr, KM_USER0);
}
+#endif
#ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/**
#define IRQ_MOVE_PENDING 0x00200000 /* need to re-target IRQ destination */
#define IRQ_NO_BALANCING 0x00400000 /* IRQ is excluded from balancing */
#define IRQ_SPURIOUS_DISABLED 0x00800000 /* IRQ was disabled by the spurious trap */
-#define IRQ_MOVE_PCNTXT 0x01000000 /* IRQ migration from process context */
+#define IRQ_MOVE_PCNTXT 0x01000000 /* IRQ migration from process context */
+#define IRQ_AFFINITY_SET 0x02000000 /* IRQ affinity was set from userspace*/
#ifdef CONFIG_IRQ_PER_CPU
# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
/**
* struct irq_desc - interrupt descriptor
- *
+ * @irq: interrupt number for this descriptor
* @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()]
* @chip: low level interrupt hardware access
* @msi_desc: MSI descriptor
* @cpu: cpu index useful for balancing
* @pending_mask: pending rebalanced interrupts
* @dir: /proc/irq/ procfs entry
- * @affinity_entry: /proc/irq/smp_affinity procfs entry on SMP
* @name: flow handler name for /proc/interrupts output
*/
struct irq_desc {
#ifdef CONFIG_GENERIC_PENDING_IRQ
-void set_pending_irq(unsigned int irq, cpumask_t mask);
void move_native_irq(int irq);
void move_masked_irq(int irq);
{
}
-static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
-{
-}
-
#endif /* CONFIG_GENERIC_PENDING_IRQ */
#else /* CONFIG_SMP */
#ifdef CONFIG_MEMORY_HOTPLUG
#define hotplug_memory_notifier(fn, pri) { \
- static struct notifier_block fn##_mem_nb = \
+ static __meminitdata struct notifier_block fn##_mem_nb =\
{ .notifier_call = fn, .priority = pri }; \
register_memory_notifier(&fn##_mem_nb); \
}
/*
* audio.h -- Audio Driver for Wolfson WM8350 PMIC
*
- * Copyright 2007 Wolfson Microelectronics PLC
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
#define WM8350_CODEC_ISEL_0_5 3 /* x0.5 */
#define WM8350_VMID_OFF 0
-#define WM8350_VMID_500K 1
-#define WM8350_VMID_100K 2
-#define WM8350_VMID_10K 3
+#define WM8350_VMID_300K 1
+#define WM8350_VMID_50K 2
+#define WM8350_VMID_5K 3
/*
* R40 (0x28) - Clock Control 1
#define WM8350_IRQ_CODEC_MICSCD 41
#define WM8350_IRQ_CODEC_MICD 42
+/*
+ * WM8350 Platform data.
+ *
+ * This must be initialised per platform for best audio performance.
+ * Please see WM8350 datasheet for information.
+ */
+struct wm8350_audio_platform_data {
+ int vmid_discharge_msecs; /* VMID --> OFF discharge time */
+ int drain_msecs; /* OFF drain time */
+ int cap_discharge_msecs; /* Cap ON (from OFF) discharge time */
+ int vmid_charge_msecs; /* vmid power up time */
+ u32 vmid_s_curve:2; /* vmid enable s curve speed */
+ u32 dis_out4:2; /* out4 discharge speed */
+ u32 dis_out3:2; /* out3 discharge speed */
+ u32 dis_out2:2; /* out2 discharge speed */
+ u32 dis_out1:2; /* out1 discharge speed */
+ u32 vroi_out4:1; /* out4 tie off */
+ u32 vroi_out3:1; /* out3 tie off */
+ u32 vroi_out2:1; /* out2 tie off */
+ u32 vroi_out1:1; /* out1 tie off */
+ u32 vroi_enable:1; /* enable tie off */
+ u32 codec_current_on:2; /* current level ON */
+ u32 codec_current_standby:2; /* current level STANDBY */
+ u32 codec_current_charge:2; /* codec current @ vmid charge */
+};
+
+struct snd_soc_codec;
+
struct wm8350_codec {
struct platform_device *pdev;
+ struct snd_soc_codec *codec;
+ struct wm8350_audio_platform_data *platform_data;
};
#endif
struct list_head lru; /* per cgroup LRU list */
};
-void __init pgdat_page_cgroup_init(struct pglist_data *pgdat);
+void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat);
void __init page_cgroup_init(void);
struct page_cgroup *lookup_page_cgroup(struct page *page);
#else /* CONFIG_CGROUP_MEM_RES_CTLR */
struct page_cgroup;
-static inline void pgdat_page_cgroup_init(struct pglist_data *pgdat)
+static inline void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
{
}
--- /dev/null
+#ifndef _L3_H_
+#define _L3_H_ 1
+
+struct l3_pins {
+ void (*setdat)(int);
+ void (*setclk)(int);
+ void (*setmode)(int);
+ int data_hold;
+ int data_setup;
+ int clock_high;
+ int mode_hold;
+ int mode;
+ int mode_setup;
+};
+
+int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len);
+
+#endif
--- /dev/null
+#ifndef _S3C24XX_UDA134X_H_
+#define _S3C24XX_UDA134X_H_ 1
+
+#include <sound/uda134x.h>
+
+struct s3c24xx_uda134x_platform_data {
+ int l3_clk;
+ int l3_mode;
+ int l3_data;
+ void (*power) (int);
+ int model;
+};
+
+#endif
--- /dev/null
+/*
+ * linux/sound/soc-dai.h -- ALSA SoC Layer
+ *
+ * Copyright: 2005-2008 Wolfson Microelectronics. PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Digital Audio Interface (DAI) API.
+ */
+
+#ifndef __LINUX_SND_SOC_DAI_H
+#define __LINUX_SND_SOC_DAI_H
+
+
+#include <linux/list.h>
+
+struct snd_pcm_substream;
+
+/*
+ * DAI hardware audio formats.
+ *
+ * Describes the physical PCM data formating and clocking. Add new formats
+ * to the end.
+ */
+#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
+#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */
+#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
+#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM LRC */
+#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM LRC */
+#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
+
+/* left and right justified also known as MSB and LSB respectively */
+#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
+#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
+
+/*
+ * DAI Clock gating.
+ *
+ * DAI bit clocks can be be gated (disabled) when not the DAI is not
+ * sending or receiving PCM data in a frame. This can be used to save power.
+ */
+#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
+#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated */
+
+/*
+ * DAI Left/Right Clocks.
+ *
+ * Specifies whether the DAI can support different samples for similtanious
+ * playback and capture. This usually requires a seperate physical frame
+ * clock for playback and capture.
+ */
+#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
+#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
+
+/*
+ * TDM
+ *
+ * Time Division Multiplexing. Allows PCM data to be multplexed with other
+ * data on the DAI.
+ */
+#define SND_SOC_DAIFMT_TDM (1 << 6)
+
+/*
+ * DAI hardware signal inversions.
+ *
+ * Specifies whether the DAI can also support inverted clocks for the specified
+ * format.
+ */
+#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */
+#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
+#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
+#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
+
+/*
+ * DAI hardware clock masters.
+ *
+ * This is wrt the codec, the inverse is true for the interface
+ * i.e. if the codec is clk and frm master then the interface is
+ * clk and frame slave.
+ */
+#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */
+#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */
+#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
+#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */
+
+#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
+#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
+#define SND_SOC_DAIFMT_INV_MASK 0x0f00
+#define SND_SOC_DAIFMT_MASTER_MASK 0xf000
+
+/*
+ * Master Clock Directions
+ */
+#define SND_SOC_CLOCK_IN 0
+#define SND_SOC_CLOCK_OUT 1
+
+struct snd_soc_dai_ops;
+struct snd_soc_dai;
+struct snd_ac97_bus_ops;
+
+/* Digital Audio Interface registration */
+int snd_soc_register_dai(struct snd_soc_dai *dai);
+void snd_soc_unregister_dai(struct snd_soc_dai *dai);
+int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count);
+void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count);
+
+/* Digital Audio Interface clocking API.*/
+int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir);
+
+int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
+ int div_id, int div);
+
+int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out);
+
+/* Digital Audio interface formatting */
+int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
+
+int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int mask, int slots);
+
+int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
+
+/* Digital Audio Interface mute */
+int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
+
+/*
+ * Digital Audio Interface.
+ *
+ * Describes the Digital Audio Interface in terms of it's ALSA, DAI and AC97
+ * operations an capabilities. Codec and platfom drivers will register a this
+ * structure for every DAI they have.
+ *
+ * This structure covers the clocking, formating and ALSA operations for each
+ * interface a
+ */
+struct snd_soc_dai_ops {
+ /*
+ * DAI clocking configuration, all optional.
+ * Called by soc_card drivers, normally in their hw_params.
+ */
+ int (*set_sysclk)(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir);
+ int (*set_pll)(struct snd_soc_dai *dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out);
+ int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
+
+ /*
+ * DAI format configuration
+ * Called by soc_card drivers, normally in their hw_params.
+ */
+ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
+ int (*set_tdm_slot)(struct snd_soc_dai *dai,
+ unsigned int mask, int slots);
+ int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
+
+ /*
+ * DAI digital mute - optional.
+ * Called by soc-core to minimise any pops.
+ */
+ int (*digital_mute)(struct snd_soc_dai *dai, int mute);
+
+ /*
+ * ALSA PCM audio operations - all optional.
+ * Called by soc-core during audio PCM operations.
+ */
+ int (*startup)(struct snd_pcm_substream *,
+ struct snd_soc_dai *);
+ void (*shutdown)(struct snd_pcm_substream *,
+ struct snd_soc_dai *);
+ int (*hw_params)(struct snd_pcm_substream *,
+ struct snd_pcm_hw_params *, struct snd_soc_dai *);
+ int (*hw_free)(struct snd_pcm_substream *,
+ struct snd_soc_dai *);
+ int (*prepare)(struct snd_pcm_substream *,
+ struct snd_soc_dai *);
+ int (*trigger)(struct snd_pcm_substream *, int,
+ struct snd_soc_dai *);
+};
+
+/*
+ * Digital Audio Interface runtime data.
+ *
+ * Holds runtime data for a DAI.
+ */
+struct snd_soc_dai {
+ /* DAI description */
+ char *name;
+ unsigned int id;
+ int ac97_control;
+
+ struct device *dev;
+
+ /* DAI callbacks */
+ int (*probe)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
+ void (*remove)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
+ int (*suspend)(struct snd_soc_dai *dai);
+ int (*resume)(struct snd_soc_dai *dai);
+
+ /* ops */
+ struct snd_soc_dai_ops ops;
+
+ /* DAI capabilities */
+ struct snd_soc_pcm_stream capture;
+ struct snd_soc_pcm_stream playback;
+
+ /* DAI runtime info */
+ struct snd_pcm_runtime *runtime;
+ struct snd_soc_codec *codec;
+ unsigned int active;
+ unsigned char pop_wait:1;
+ void *dma_data;
+
+ /* DAI private data */
+ void *private_data;
+
+ /* parent codec/platform */
+ union {
+ struct snd_soc_codec *codec;
+ struct snd_soc_platform *platform;
+ };
+
+ struct list_head list;
+};
+
+#endif
int num);
/* dapm path setup */
-int __deprecated snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
- const char *sink_name, const char *control_name, const char *src_name);
int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
void snd_soc_dapm_free(struct snd_soc_device *socdev);
int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
#include <sound/control.h>
#include <sound/ac97_codec.h>
-#define SND_SOC_VERSION "0.13.2"
-
/*
* Convenience kcontrol builders
*/
SND_SOC_BIAS_OFF,
};
-/*
- * Digital Audio Interface (DAI) types
- */
-#define SND_SOC_DAI_AC97 0x1
-#define SND_SOC_DAI_I2S 0x2
-#define SND_SOC_DAI_PCM 0x4
-#define SND_SOC_DAI_AC97_BUS 0x8 /* for custom i.e. non ac97_codec.c */
-
-/*
- * DAI hardware audio formats
- */
-#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
-#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right justified mode */
-#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
-#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM or LRC */
-#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM or LRC */
-#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
-
-#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
-#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
-
-/*
- * DAI Gating
- */
-#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
-#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */
-
-/*
- * DAI Sync
- * Synchronous LR (Left Right) clocks and Frame signals.
- */
-#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
-#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
-
-/*
- * TDM
- */
-#define SND_SOC_DAIFMT_TDM (1 << 6)
-
-/*
- * DAI hardware signal inversions
- */
-#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bclk + frm */
-#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
-#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
-#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
-
-/*
- * DAI hardware clock masters
- * This is wrt the codec, the inverse is true for the interface
- * i.e. if the codec is clk and frm master then the interface is
- * clk and frame slave.
- */
-#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */
-#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */
-#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
-#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */
-
-#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
-#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
-#define SND_SOC_DAIFMT_INV_MASK 0x0f00
-#define SND_SOC_DAIFMT_MASTER_MASK 0xf000
-
-
-/*
- * Master Clock Directions
- */
-#define SND_SOC_CLOCK_IN 0
-#define SND_SOC_CLOCK_OUT 1
-
-/*
- * AC97 codec ID's bitmask
- */
-#define SND_SOC_DAI_AC97_ID0 (1 << 0)
-#define SND_SOC_DAI_AC97_ID1 (1 << 1)
-#define SND_SOC_DAI_AC97_ID2 (1 << 2)
-#define SND_SOC_DAI_AC97_ID3 (1 << 3)
-
struct snd_soc_device;
struct snd_soc_pcm_stream;
struct snd_soc_ops;
struct snd_soc_dai_mode;
struct snd_soc_pcm_runtime;
struct snd_soc_dai;
+struct snd_soc_platform;
struct snd_soc_codec;
-struct snd_soc_machine_config;
struct soc_enum;
struct snd_soc_ac97_ops;
-struct snd_soc_clock_info;
typedef int (*hw_write_t)(void *,const char* ,int);
typedef int (*hw_read_t)(void *,char* ,int);
extern struct snd_ac97_bus_ops soc_ac97_ops;
+int snd_soc_register_platform(struct snd_soc_platform *platform);
+void snd_soc_unregister_platform(struct snd_soc_platform *platform);
+int snd_soc_register_codec(struct snd_soc_codec *codec);
+void snd_soc_unregister_codec(struct snd_soc_codec *codec);
+
/* pcm <-> DAI connect */
void snd_soc_free_pcms(struct snd_soc_device *socdev);
int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
-int snd_soc_register_card(struct snd_soc_device *socdev);
+int snd_soc_init_card(struct snd_soc_device *socdev);
/* set runtime hw params */
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
struct snd_ac97_bus_ops *ops, int num);
void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
-/* Digital Audio Interface clocking API.*/
-int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
- unsigned int freq, int dir);
-
-int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
- int div_id, int div);
-
-int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
- int pll_id, unsigned int freq_in, unsigned int freq_out);
-
-/* Digital Audio interface formatting */
-int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
-
-int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
- unsigned int mask, int slots);
-
-int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
-
-/* Digital Audio Interface mute */
-int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
-
/*
*Controls
*/
int (*trigger)(struct snd_pcm_substream *, int);
};
-/* ASoC DAI ops */
-struct snd_soc_dai_ops {
- /* DAI clocking configuration */
- int (*set_sysclk)(struct snd_soc_dai *dai,
- int clk_id, unsigned int freq, int dir);
- int (*set_pll)(struct snd_soc_dai *dai,
- int pll_id, unsigned int freq_in, unsigned int freq_out);
- int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
-
- /* DAI format configuration */
- int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
- int (*set_tdm_slot)(struct snd_soc_dai *dai,
- unsigned int mask, int slots);
- int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
-
- /* digital mute */
- int (*digital_mute)(struct snd_soc_dai *dai, int mute);
-};
-
-/* SoC DAI (Digital Audio Interface) */
-struct snd_soc_dai {
- /* DAI description */
- char *name;
- unsigned int id;
- unsigned char type;
-
- /* DAI callbacks */
- int (*probe)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- void (*remove)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- int (*suspend)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- int (*resume)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
-
- /* ops */
- struct snd_soc_ops ops;
- struct snd_soc_dai_ops dai_ops;
-
- /* DAI capabilities */
- struct snd_soc_pcm_stream capture;
- struct snd_soc_pcm_stream playback;
-
- /* DAI runtime info */
- struct snd_pcm_runtime *runtime;
- struct snd_soc_codec *codec;
- unsigned int active;
- unsigned char pop_wait:1;
- void *dma_data;
-
- /* DAI private data */
- void *private_data;
-};
-
/* SoC Audio Codec */
struct snd_soc_codec {
char *name;
struct module *owner;
struct mutex mutex;
+ struct device *dev;
+
+ struct list_head list;
/* callbacks */
int (*set_bias_level)(struct snd_soc_codec *,
short reg_cache_step;
/* dapm */
+ u32 pop_time;
struct list_head dapm_widgets;
struct list_head dapm_paths;
enum snd_soc_bias_level bias_level;
/* codec DAI's */
struct snd_soc_dai *dai;
unsigned int num_dai;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_reg;
+ struct dentry *debugfs_pop_time;
+#endif
};
/* codec device */
/* SoC platform interface */
struct snd_soc_platform {
char *name;
+ struct list_head list;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
- int (*suspend)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- int (*resume)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
+ int (*suspend)(struct snd_soc_dai *dai);
+ int (*resume)(struct snd_soc_dai *dai);
/* pcm creation and destruction */
int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
struct snd_pcm *pcm;
};
-/* SoC machine */
-struct snd_soc_machine {
+/* SoC card */
+struct snd_soc_card {
char *name;
+ struct device *dev;
+
+ struct list_head list;
+
+ int instantiated;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
int (*resume_post)(struct platform_device *pdev);
/* callbacks */
- int (*set_bias_level)(struct snd_soc_machine *,
+ int (*set_bias_level)(struct snd_soc_card *,
enum snd_soc_bias_level level);
/* CPU <--> Codec DAI links */
struct snd_soc_dai_link *dai_link;
int num_links;
+
+ struct snd_soc_device *socdev;
+
+ struct snd_soc_platform *platform;
+ struct delayed_work delayed_work;
+ struct work_struct deferred_resume_work;
};
/* SoC Device - the audio subsystem */
struct snd_soc_device {
struct device *dev;
- struct snd_soc_machine *machine;
- struct snd_soc_platform *platform;
+ struct snd_soc_card *card;
struct snd_soc_codec *codec;
struct snd_soc_codec_device *codec_dev;
- struct delayed_work delayed_work;
- struct work_struct deferred_resume_work;
void *codec_data;
};
void *dapm;
};
+#include <sound/soc-dai.h>
+
#endif
--- /dev/null
+/*
+ * uda134x.h -- UDA134x ALSA SoC Codec driver
+ *
+ * Copyright 2007 Dension Audio Systems Ltd.
+ * Author: Zoltan Devai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _UDA134X_H
+#define _UDA134X_H
+
+#include <sound/l3.h>
+
+struct uda134x_platform_data {
+ struct l3_pins l3;
+ void (*power) (int);
+ int model;
+#define UDA134X_UDA1340 1
+#define UDA134X_UDA1341 2
+#define UDA134X_UDA1344 3
+};
+
+#endif /* _UDA134X_H */
* It must be called by the arch code on the new cpu, before the new cpu
* enables interrupts and before the "boot" cpu returns from __cpu_up().
*/
-void notify_cpu_starting(unsigned int cpu)
+void __cpuinit notify_cpu_starting(unsigned int cpu)
{
unsigned long val = CPU_STARTING;
int i, j, k; /* indices for partition finding loops */
cpumask_t *doms; /* resulting partition; i.e. sched domains */
struct sched_domain_attr *dattr; /* attributes for custom domains */
- int ndoms; /* number of sched domains in result */
+ int ndoms = 0; /* number of sched domains in result */
int nslot; /* next empty doms[] cpumask_t slot */
doms = NULL;
struct irqaction *action) { }
#endif
+extern int irq_select_affinity_usr(unsigned int irq);
+
/*
* Debugging printout:
*/
int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
{
struct irq_desc *desc = irq_to_desc(irq);
+ unsigned long flags;
if (!desc->chip->set_affinity)
return -EINVAL;
+ spin_lock_irqsave(&desc->lock, flags);
+
#ifdef CONFIG_GENERIC_PENDING_IRQ
if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) {
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
desc->affinity = cpumask;
desc->chip->set_affinity(irq, cpumask);
- spin_unlock_irqrestore(&desc->lock, flags);
- } else
- set_pending_irq(irq, cpumask);
+ } else {
+ desc->status |= IRQ_MOVE_PENDING;
+ desc->pending_mask = cpumask;
+ }
#else
desc->affinity = cpumask;
desc->chip->set_affinity(irq, cpumask);
#endif
+ desc->status |= IRQ_AFFINITY_SET;
+ spin_unlock_irqrestore(&desc->lock, flags);
return 0;
}
/*
* Generic version of the affinity autoselector.
*/
-int irq_select_affinity(unsigned int irq)
+int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc)
{
cpumask_t mask;
- struct irq_desc *desc;
if (!irq_can_set_affinity(irq))
return 0;
cpus_and(mask, cpu_online_map, irq_default_affinity);
- desc = irq_to_desc(irq);
+ /*
+ * Preserve an userspace affinity setup, but make sure that
+ * one of the targets is online.
+ */
+ if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) {
+ if (cpus_intersects(desc->affinity, cpu_online_map))
+ mask = desc->affinity;
+ else
+ desc->status &= ~IRQ_AFFINITY_SET;
+ }
+
desc->affinity = mask;
desc->chip->set_affinity(irq, mask);
return 0;
}
+#else
+static inline int do_irq_select_affinity(unsigned int irq, struct irq_desc *d)
+{
+ return irq_select_affinity(irq);
+}
#endif
+/*
+ * Called when affinity is set via /proc/irq
+ */
+int irq_select_affinity_usr(unsigned int irq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ ret = do_irq_select_affinity(irq, desc);
+ spin_unlock_irqrestore(&desc->lock, flags);
+
+ return ret;
+}
+
+#else
+static inline int do_irq_select_affinity(int irq, struct irq_desc *desc)
+{
+ return 0;
+}
#endif
/**
* IRQF_TRIGGER_* but the PIC does not support multiple
* flow-types?
*/
- pr_warning("No set_type function for IRQ %d (%s)\n", irq,
+ pr_debug("No set_type function for IRQ %d (%s)\n", irq,
chip ? (chip->name ? : "unknown") : "unknown");
return 0;
}
/* Undo nested disables: */
desc->depth = 1;
+ /* Exclude IRQ from balancing if requested */
+ if (new->flags & IRQF_NOBALANCING)
+ desc->status |= IRQ_NO_BALANCING;
+
/* Set default affinity mask once everything is setup */
- irq_select_affinity(irq);
+ do_irq_select_affinity(irq, desc);
} else if ((new->flags & IRQF_TRIGGER_MASK)
&& (new->flags & IRQF_TRIGGER_MASK)
*p = new;
- /* Exclude IRQ from balancing */
- if (new->flags & IRQF_NOBALANCING)
- desc->status |= IRQ_NO_BALANCING;
-
/* Reset broken irq detection when installing new handler */
desc->irq_count = 0;
desc->irqs_unhandled = 0;
#include <linux/irq.h>
-void set_pending_irq(unsigned int irq, cpumask_t mask)
-{
- struct irq_desc *desc = irq_to_desc(irq);
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
- desc->status |= IRQ_MOVE_PENDING;
- desc->pending_mask = mask;
- spin_unlock_irqrestore(&desc->lock, flags);
-}
-
void move_masked_irq(int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
if (!cpus_intersects(new_value, cpu_online_map))
/* Special case for empty set - allow the architecture
code to set default SMP affinity. */
- return irq_select_affinity(irq) ? -EINVAL : count;
+ return irq_select_affinity_usr(irq) ? -EINVAL : count;
irq_set_affinity(irq, new_value);
{
printk("Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar\n");
- printk("... MAX_LOCKDEP_SUBCLASSES: %lu\n", MAX_LOCKDEP_SUBCLASSES);
+ printk("... MAX_LOCKDEP_SUBCLASSES: %lu\n", MAX_LOCKDEP_SUBCLASSES);
printk("... MAX_LOCK_DEPTH: %lu\n", MAX_LOCK_DEPTH);
printk("... MAX_LOCKDEP_KEYS: %lu\n", MAX_LOCKDEP_KEYS);
- printk("... CLASSHASH_SIZE: %lu\n", CLASSHASH_SIZE);
+ printk("... CLASSHASH_SIZE: %lu\n", CLASSHASH_SIZE);
printk("... MAX_LOCKDEP_ENTRIES: %lu\n", MAX_LOCKDEP_ENTRIES);
printk("... MAX_LOCKDEP_CHAINS: %lu\n", MAX_LOCKDEP_CHAINS);
printk("... CHAINHASH_SIZE: %lu\n", CHAINHASH_SIZE);
put_cpu();
}
-static int __devinit profile_cpu_callback(struct notifier_block *info,
+static int __cpuinit profile_cpu_callback(struct notifier_block *info,
unsigned long action, void *__cpu)
{
int node, cpu = (unsigned long)__cpu;
#define create_hash_tables() ({ 0; })
#endif
-int create_proc_profile(void)
+int __ref create_proc_profile(void) /* false positive from hotcpu_notifier */
{
struct proc_dir_entry *entry;
return (copied == sizeof(data)) ? 0 : -EIO;
}
-#if defined CONFIG_COMPAT && defined __ARCH_WANT_COMPAT_SYS_PTRACE
+#if defined CONFIG_COMPAT
#include <linux/compat.h>
int compat_ptrace_request(struct task_struct *child, compat_long_t request,
unlock_kernel();
return ret;
}
-#endif /* CONFIG_COMPAT && __ARCH_WANT_COMPAT_SYS_PTRACE */
+#endif /* CONFIG_COMPAT */
static unsigned long cpu_avg_load_per_task(int cpu)
{
struct rq *rq = cpu_rq(cpu);
+ unsigned long nr_running = ACCESS_ONCE(rq->nr_running);
- if (rq->nr_running)
- rq->avg_load_per_task = rq->load.weight / rq->nr_running;
+ if (nr_running)
+ rq->avg_load_per_task = rq->load.weight / nr_running;
else
rq->avg_load_per_task = 0;
out:
if (resched)
- preempt_enable_notrace();
+ preempt_enable_no_resched_notrace();
else
preempt_enable_notrace();
return NULL;
static struct trace_array *mmio_trace_array;
static bool overrun_detected;
+static unsigned long prev_overruns;
static void mmio_reset_data(struct trace_array *tr)
{
int cpu;
overrun_detected = false;
+ prev_overruns = 0;
tr->time_start = ftrace_now(tr->cpu);
for_each_online_cpu(cpu)
static unsigned long count_overruns(struct trace_iterator *iter)
{
- int cpu;
unsigned long cnt = 0;
-/* FIXME: */
-#if 0
- for_each_online_cpu(cpu) {
- cnt += iter->overrun[cpu];
- iter->overrun[cpu] = 0;
- }
-#endif
- (void)cpu;
+ unsigned long over = ring_buffer_overruns(iter->tr->buffer);
+
+ if (over > prev_overruns)
+ cnt = over - prev_overruns;
+ prev_overruns = over;
return cnt;
}
static void *
t_next(struct seq_file *m, void *v, loff_t *pos)
{
- long i = (long)m->private;
+ long i;
(*pos)++;
- i++;
+ if (v == SEQ_START_TOKEN)
+ i = 0;
+ else {
+ i = *(long *)v;
+ i++;
+ }
if (i >= max_stack_trace.nr_entries ||
stack_dump_trace[i] == ULONG_MAX)
static void *t_start(struct seq_file *m, loff_t *pos)
{
- void *t = &m->private;
+ void *t = SEQ_START_TOKEN;
loff_t l = 0;
local_irq_disable();
__raw_spin_lock(&max_stack_lock);
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
for (; t && l < *pos; t = t_next(m, t, &l))
;
static int t_show(struct seq_file *m, void *v)
{
- long i = *(long *)v;
+ long i;
int size;
- if (i < 0) {
+ if (v == SEQ_START_TOKEN) {
seq_printf(m, " Depth Size Location"
" (%d entries)\n"
" ----- ---- --------\n",
return 0;
}
+ i = *(long *)v;
+
if (i >= max_stack_trace.nr_entries ||
stack_dump_trace[i] == ULONG_MAX)
return 0;
int ret;
ret = seq_open(file, &stack_trace_seq_ops);
- if (!ret) {
- struct seq_file *m = file->private_data;
- m->private = (void *)-1;
- }
return ret;
}
pgdat->node_start_pfn;
}
-static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
+static int __meminit __add_zone(struct zone *zone, unsigned long phys_start_pfn)
{
struct pglist_data *pgdat = zone->zone_pgdat;
int nr_pages = PAGES_PER_SECTION;
return 0;
}
-static int __add_section(struct zone *zone, unsigned long phys_start_pfn)
+static int __meminit __add_section(struct zone *zone, unsigned long phys_start_pfn)
{
int nr_pages = PAGES_PER_SECTION;
int ret;
* call this function after deciding the zone to which to
* add the new pages.
*/
-int __add_pages(struct zone *zone, unsigned long phys_start_pfn,
+int __ref __add_pages(struct zone *zone, unsigned long phys_start_pfn,
unsigned long nr_pages)
{
unsigned long i;
}
-int add_memory(int nid, u64 start, u64 size)
+/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
+int __ref add_memory(int nid, u64 start, u64 size)
{
pg_data_t *pgdat = NULL;
int new_pgdat = 0;
#if !defined(CONFIG_SPARSEMEM)
-void __init pgdat_page_cgroup_init(struct pglist_data *pgdat)
+void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
{
pgdat->node_page_cgroup = NULL;
}
return section->page_cgroup + pfn;
}
-int __meminit init_section_page_cgroup(unsigned long pfn)
+/* __alloc_bootmem...() is protected by !slab_available() */
+int __init_refok init_section_page_cgroup(unsigned long pfn)
{
struct mem_section *section;
struct page_cgroup *base, *pc;
}
}
-int online_page_cgroup(unsigned long start_pfn,
+int __meminit online_page_cgroup(unsigned long start_pfn,
unsigned long nr_pages,
int nid)
{
return -ENOMEM;
}
-int offline_page_cgroup(unsigned long start_pfn,
+int __meminit offline_page_cgroup(unsigned long start_pfn,
unsigned long nr_pages, int nid)
{
unsigned long start, end, pfn;
}
-static int page_cgroup_callback(struct notifier_block *self,
+static int __meminit page_cgroup_callback(struct notifier_block *self,
unsigned long action, void *arg)
{
struct memory_notify *mn = arg;
" want\n");
}
-void __init pgdat_page_cgroup_init(struct pglist_data *pgdat)
+void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
{
return;
}
* set. If this is <=0, then that means that the passed-in
* map was not consumed and must be freed.
*/
-int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
+int __meminit sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
int nr_pages)
{
unsigned long section_nr = pfn_to_section_nr(start_pfn);
list_add(&page->lru, &l_inactive);
}
+ spin_lock_irq(&zone->lru_lock);
/*
* Count referenced pages from currently used mappings as
* rotated, even though they are moved to the inactive list.
pgmoved = 0;
lru = LRU_BASE + file * LRU_FILE;
- spin_lock_irq(&zone->lru_lock);
while (!list_empty(&l_inactive)) {
page = lru_to_page(&l_inactive);
prefetchw_prev_lru_page(page, &l_inactive, flags);
{
hda_nid_t *d;
- snd_hda_codec_write(codec, nid, 0, verb, val);
+ snd_hda_codec_write_cache(codec, nid, 0, verb, val);
d = codec->slave_dig_outs;
if (!d)
return;
for (; *d; d++)
- snd_hda_codec_write(codec, *d, 0, verb, val);
+ snd_hda_codec_write_cache(codec, *d, 0, verb, val);
}
static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
enum {
STAC_92HD73XX_REF,
- STAC_DELL_M6,
+ STAC_DELL_M6_AMIC,
+ STAC_DELL_M6_DMIC,
+ STAC_DELL_M6_BOTH,
STAC_DELL_EQ,
STAC_92HD73XX_MODELS
};
STAC_92HD71BXX_REF,
STAC_DELL_M4_1,
STAC_DELL_M4_2,
+ STAC_DELL_M4_3,
STAC_HP_M4,
STAC_92HD71BXX_MODELS
};
unsigned int num_mixers;
int board_config;
+ unsigned int eapd_switch: 1;
unsigned int surr_switch: 1;
unsigned int line_switch: 1;
unsigned int mic_switch: 1;
static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
[STAC_92HD73XX_REF] = ref92hd73xx_pin_configs,
- [STAC_DELL_M6] = dell_m6_pin_configs,
+ [STAC_DELL_M6_AMIC] = dell_m6_pin_configs,
+ [STAC_DELL_M6_DMIC] = dell_m6_pin_configs,
+ [STAC_DELL_M6_BOTH] = dell_m6_pin_configs,
[STAC_DELL_EQ] = dell_m6_pin_configs,
};
static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
[STAC_92HD73XX_REF] = "ref",
- [STAC_DELL_M6] = "dell-m6",
+ [STAC_DELL_M6_AMIC] = "dell-m6-amic",
+ [STAC_DELL_M6_DMIC] = "dell-m6-dmic",
+ [STAC_DELL_M6_BOTH] = "dell-m6",
[STAC_DELL_EQ] = "dell-eq",
};
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD73XX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
- "unknown Dell", STAC_DELL_M6),
+ "Dell Studio 1535", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_BOTH),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_BOTH),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_AMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_AMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271,
- "unknown Dell", STAC_DELL_M6),
+ "unknown Dell", STAC_DELL_M6_DMIC),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0272,
+ "unknown Dell", STAC_DELL_M6_DMIC),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x029f,
+ "Dell Studio 1537", STAC_DELL_M6_DMIC),
{} /* terminator */
};
0x40f000f0, 0x044413b0, 0x044413b0,
};
+static unsigned int dell_m4_3_pin_configs[11] = {
+ 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
+ 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0,
+ 0x40f000f0, 0x044413b0, 0x044413b0,
+};
+
static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
[STAC_92HD71BXX_REF] = ref92hd71bxx_pin_configs,
[STAC_DELL_M4_1] = dell_m4_1_pin_configs,
[STAC_DELL_M4_2] = dell_m4_2_pin_configs,
+ [STAC_DELL_M4_3] = dell_m4_3_pin_configs,
[STAC_HP_M4] = NULL,
};
[STAC_92HD71BXX_REF] = "ref",
[STAC_DELL_M4_1] = "dell-m4-1",
[STAC_DELL_M4_2] = "dell-m4-2",
+ [STAC_DELL_M4_3] = "dell-m4-3",
[STAC_HP_M4] = "hp-m4",
};
"unknown Dell", STAC_DELL_M4_2),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264,
"unknown Dell", STAC_DELL_M4_2),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02aa,
+ "unknown Dell", STAC_DELL_M4_3),
{} /* terminator */
};
cfg->hp_outs && !spec->multiout.hp_nid)
spec->multiout.hp_nid = nid;
- if (cfg->hp_outs > 1) {
+ if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) {
err = stac92xx_add_control(spec,
STAC_CTL_WIDGET_HP_SWITCH,
"Headphone as Line Out Switch",
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
}
+static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
+ int enable);
+
static int stac92xx_init(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
+ unsigned int gpio;
int i;
snd_hda_sequence_write(codec, spec->init);
snd_hda_codec_write_cache(codec,
spec->adc_nids[i], 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+
+ /* set up GPIO */
+ gpio = spec->gpio_data;
+ /* turn on EAPD statically when spec->eapd_switch isn't set.
+ * otherwise, unsol event will turn it on/off dynamically
+ */
+ if (!spec->eapd_switch)
+ gpio |= spec->eapd_mask;
+ stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio);
+
/* set up pins */
if (spec->hp_detect) {
/* Enable unsolicited responses on the HP widget */
for (i = 0; i < spec->num_dmics; i++)
stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
AC_PINCTL_IN_EN);
+ if (cfg->dig_out_pin)
+ stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
+ AC_PINCTL_OUT_EN);
+ if (cfg->dig_in_pin)
+ stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
+ AC_PINCTL_IN_EN);
for (i = 0; i < spec->num_pwrs; i++) {
- int event = is_nid_hp_pin(cfg, spec->pwr_nids[i])
- ? STAC_HP_EVENT : STAC_PWR_EVENT;
- int pinctl = snd_hda_codec_read(codec, spec->pwr_nids[i],
- 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i],
- 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- def_conf = get_defcfg_connect(def_conf);
+ hda_nid_t nid = spec->pwr_nids[i];
+ int pinctl, def_conf;
+ int event = STAC_PWR_EVENT;
+
+ if (is_nid_hp_pin(cfg, nid) && spec->hp_detect)
+ continue; /* already has an unsol event */
+
+ pinctl = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
/* outputs are only ports capable of power management
* any attempts on powering down a input port cause the
* referenced VREF to act quirky.
*/
if (pinctl & AC_PINCTL_IN_EN)
continue;
+ def_conf = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
+ def_conf = get_defcfg_connect(def_conf);
/* skip any ports that don't have jacks since presence
* detection is useless */
- if (def_conf && def_conf != AC_JACK_PORT_FIXED)
+ if (def_conf != AC_JACK_PORT_COMPLEX) {
+ if (def_conf != AC_JACK_PORT_NONE)
+ stac_toggle_power_map(codec, nid, 1);
continue;
+ }
enable_pin_detect(codec, spec->pwr_nids[i], event | i);
codec->patch_ops.unsol_event(codec, (event | i) << 26);
}
if (spec->dac_list)
stac92xx_power_down(codec);
- if (cfg->dig_out_pin)
- stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
- AC_PINCTL_OUT_EN);
- if (cfg->dig_in_pin)
- stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
- AC_PINCTL_IN_EN);
-
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data);
-
return 0;
}
for (i = 0; i < cfg->speaker_outs; i++)
stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
AC_PINCTL_OUT_EN);
- if (spec->eapd_mask)
+ if (spec->eapd_mask && spec->eapd_switch)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data &
~spec->eapd_mask);
for (i = 0; i < cfg->speaker_outs; i++)
stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
AC_PINCTL_OUT_EN);
- if (spec->eapd_mask)
+ if (spec->eapd_mask && spec->eapd_switch)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data |
spec->eapd_mask);
}
}
-static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
+static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
+ int enable)
{
struct sigmatel_spec *spec = codec->spec;
- hda_nid_t nid = spec->pwr_nids[idx];
- int presence, val;
- val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0)
- & 0x000000ff;
- presence = get_hp_pin_presence(codec, nid);
+ unsigned int idx, val;
+
+ for (idx = 0; idx < spec->num_pwrs; idx++) {
+ if (spec->pwr_nids[idx] == nid)
+ break;
+ }
+ if (idx >= spec->num_pwrs)
+ return;
/* several codecs have two power down bits */
if (spec->pwr_mapping)
else
idx = 1 << idx;
- if (presence)
+ val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff;
+ if (enable)
val &= ~idx;
else
val |= idx;
/* power down unused output ports */
snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val);
-};
+}
+
+static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
+{
+ stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid));
+}
static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
{
case STAC_DELL_EQ:
spec->init = dell_eq_core_init;
/* fallthru */
- case STAC_DELL_M6:
+ case STAC_DELL_M6_AMIC:
+ case STAC_DELL_M6_DMIC:
+ case STAC_DELL_M6_BOTH:
spec->num_smuxes = 0;
spec->mixer = &stac92hd73xx_6ch_mixer[DELL_M6_MIXER];
spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP];
+ spec->eapd_switch = 0;
spec->num_amps = 1;
if (!spec->init)
spec->init = dell_m6_core_init;
- switch (codec->subsystem_id) {
- case 0x1028025e: /* Analog Mics */
- case 0x1028025f:
+ switch (spec->board_config) {
+ case STAC_DELL_M6_AMIC: /* Analog Mics */
stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
spec->num_dmics = 0;
spec->private_dimux.num_items = 1;
break;
- case 0x10280271: /* Digital Mics */
- case 0x10280272:
- case 0x10280254:
- case 0x10280255:
+ case STAC_DELL_M6_DMIC: /* Digital Mics */
stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
spec->num_dmics = 1;
spec->private_dimux.num_items = 2;
break;
- case 0x10280256: /* Both */
- case 0x10280057:
+ case STAC_DELL_M6_BOTH: /* Both */
stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
spec->num_dmics = 1;
default:
spec->num_dmics = STAC92HD73XX_NUM_DMICS;
spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids);
+ spec->eapd_switch = 1;
}
if (spec->board_config > STAC_92HD73XX_REF) {
/* GPIO0 High = Enable EAPD */
static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state)
{
+ struct sigmatel_spec *spec = codec->spec;
+
stac92hd71xx_set_power_state(codec, AC_PWRST_D3);
+ if (spec->eapd_mask)
+ stac_gpio_set(codec, spec->gpio_mask,
+ spec->gpio_dir, spec->gpio_data &
+ ~spec->eapd_mask);
return 0;
};
switch (spec->board_config) {
case STAC_HP_M4:
- spec->num_dmics = 0;
- spec->num_smuxes = 0;
- spec->num_dmuxes = 0;
-
/* enable internal microphone */
stac92xx_set_config_reg(codec, 0x0e, 0x01813040);
stac92xx_auto_set_pinctl(codec, 0x0e,
AC_PINCTL_IN_EN | AC_PINCTL_VREF_80);
+ /* fallthru */
+ case STAC_DELL_M4_2:
+ spec->num_dmics = 0;
+ spec->num_smuxes = 0;
+ spec->num_dmuxes = 0;
+ break;
+ case STAC_DELL_M4_1:
+ case STAC_DELL_M4_3:
+ spec->num_dmics = 1;
+ spec->num_smuxes = 0;
+ spec->num_dmuxes = 0;
break;
default:
spec->num_dmics = STAC92HD71BXX_NUM_DMICS;
spec->num_pwrs = 0;
spec->aloopback_mask = 0x40;
spec->aloopback_shift = 0;
+ spec->eapd_switch = 1;
err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
if (!err) {
spec->aloopback_mask = 0x40;
spec->aloopback_shift = 0;
+ spec->eapd_switch = 1;
spec->multiout.dac_nids = spec->dac_nids;
switch (spec->board_config){
config SND_SOC_AC97_BUS
bool
-# All the supported Soc's
-source "sound/soc/at32/Kconfig"
-source "sound/soc/at91/Kconfig"
+# All the supported SoCs
+source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
+source "sound/soc/blackfin/Kconfig"
+source "sound/soc/davinci/Kconfig"
+source "sound/soc/fsl/Kconfig"
+source "sound/soc/omap/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/s3c24xx/Kconfig"
source "sound/soc/sh/Kconfig"
-source "sound/soc/fsl/Kconfig"
-source "sound/soc/davinci/Kconfig"
-source "sound/soc/omap/Kconfig"
-source "sound/soc/blackfin/Kconfig"
# Supported codecs
source "sound/soc/codecs/Kconfig"
snd-soc-core-objs := soc-core.o soc-dapm.o
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
-obj-$(CONFIG_SND_SOC) += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
-obj-$(CONFIG_SND_SOC) += omap/ au1x/ blackfin/
+obj-$(CONFIG_SND_SOC) += codecs/
+obj-$(CONFIG_SND_SOC) += atmel/
+obj-$(CONFIG_SND_SOC) += au1x/
+obj-$(CONFIG_SND_SOC) += blackfin/
+obj-$(CONFIG_SND_SOC) += davinci/
+obj-$(CONFIG_SND_SOC) += fsl/
+obj-$(CONFIG_SND_SOC) += omap/
+obj-$(CONFIG_SND_SOC) += pxa/
+obj-$(CONFIG_SND_SOC) += s3c24xx/
+obj-$(CONFIG_SND_SOC) += sh/
+++ /dev/null
-config SND_AT32_SOC
- tristate "SoC Audio for the Atmel AT32 System-on-a-Chip"
- depends on AVR32 && SND_SOC
- help
- Say Y or M if you want to add support for codecs attached to
- the AT32 SSC interface. You will also need to
- to select the audio interfaces to support below.
-
-
-config SND_AT32_SOC_SSC
- tristate
-
-
-
-config SND_AT32_SOC_PLAYPAQ
- tristate "SoC Audio support for PlayPaq with WM8510"
- depends on SND_AT32_SOC && BOARD_PLAYPAQ
- select SND_AT32_SOC_SSC
- select SND_SOC_WM8510
- help
- Say Y or M here if you want to add support for SoC audio
- on the LRS PlayPaq.
-
-
-
-config SND_AT32_SOC_PLAYPAQ_SLAVE
- bool "Run CODEC on PlayPaq in slave mode"
- depends on SND_AT32_SOC_PLAYPAQ
- default n
- help
- Say Y if you want to run with the AT32 SSC generating the BCLK
- and FRAME signals on the PlayPaq. Unless you want to play
- with the AT32 as the SSC master, you probably want to say N here,
- as this will give you better sound quality.
+++ /dev/null
-# AT32 Platform Support
-snd-soc-at32-objs := at32-pcm.o
-snd-soc-at32-ssc-objs := at32-ssc.o
-
-obj-$(CONFIG_SND_AT32_SOC) += snd-soc-at32.o
-obj-$(CONFIG_SND_AT32_SOC_SSC) += snd-soc-at32-ssc.o
-
-# AT32 Machine Support
-snd-soc-playpaq-objs := playpaq_wm8510.o
-
-obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
+++ /dev/null
-/* sound/soc/at32/at32-pcm.c
- * ASoC PCM interface for Atmel AT32 SoC
- *
- * Copyright (C) 2008 Long Range Systems
- * Geoffrey Wossum <gwossum@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Note that this is basically a port of the sound/soc/at91-pcm.c to
- * the AVR32 kernel. Thanks to Frank Mandarino for that code.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include "at32-pcm.h"
-
-
-
-/*--------------------------------------------------------------------------*\
- * Hardware definition
-\*--------------------------------------------------------------------------*/
-/* TODO: These values were taken from the AT91 platform driver, check
- * them against real values for AT32
- */
-static const struct snd_pcm_hardware at32_pcm_hardware = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_PAUSE),
-
- .formats = SNDRV_PCM_FMTBIT_S16,
- .period_bytes_min = 32,
- .period_bytes_max = 8192, /* 512 frames * 16 bytes / frame */
- .periods_min = 2,
- .periods_max = 1024,
- .buffer_bytes_max = 32 * 1024,
-};
-
-
-
-/*--------------------------------------------------------------------------*\
- * Data types
-\*--------------------------------------------------------------------------*/
-struct at32_runtime_data {
- struct at32_pcm_dma_params *params;
- dma_addr_t dma_buffer; /* physical address of DMA buffer */
- dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
- size_t period_size;
-
- dma_addr_t period_ptr; /* physical address of next period */
- int periods; /* period index of period_ptr */
-
- /* Save PDC registers (for power management) */
- u32 pdc_xpr_save;
- u32 pdc_xcr_save;
- u32 pdc_xnpr_save;
- u32 pdc_xncr_save;
-};
-
-
-
-/*--------------------------------------------------------------------------*\
- * Helper functions
-\*--------------------------------------------------------------------------*/
-static int at32_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *dmabuf = &substream->dma_buffer;
- size_t size = at32_pcm_hardware.buffer_bytes_max;
-
- dmabuf->dev.type = SNDRV_DMA_TYPE_DEV;
- dmabuf->dev.dev = pcm->card->dev;
- dmabuf->private_data = NULL;
- dmabuf->area = dma_alloc_coherent(pcm->card->dev, size,
- &dmabuf->addr, GFP_KERNEL);
- pr_debug("at32_pcm: preallocate_dma_buffer: "
- "area=%p, addr=%p, size=%ld\n",
- (void *)dmabuf->area, (void *)dmabuf->addr, size);
-
- if (!dmabuf->area)
- return -ENOMEM;
-
- dmabuf->bytes = size;
- return 0;
-}
-
-
-
-/*--------------------------------------------------------------------------*\
- * ISR
-\*--------------------------------------------------------------------------*/
-static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *rtd = substream->runtime;
- struct at32_runtime_data *prtd = rtd->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
- static int count;
-
- count++;
- if (ssc_sr & params->mask->ssc_endbuf) {
- pr_warning("at32-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "underrun" : "overrun", params->name, ssc_sr, count);
-
- /* re-start the PDC */
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end)
- prtd->period_ptr = prtd->dma_buffer;
-
-
- ssc_writex(params->ssc->regs, params->pdc->xpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
- }
-
-
- if (ssc_sr & params->mask->ssc_endx) {
- /* Load the PDC next pointer and counter registers */
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end)
- prtd->period_ptr = prtd->dma_buffer;
- ssc_writex(params->ssc->regs, params->pdc->xnpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
- }
-
-
- snd_pcm_period_elapsed(substream);
-}
-
-
-
-/*--------------------------------------------------------------------------*\
- * PCM operations
-\*--------------------------------------------------------------------------*/
-static int at32_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at32_runtime_data *prtd = runtime->private_data;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
- /* this may get called several times by oss emulation
- * with different params
- */
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- prtd->params = rtd->dai->cpu_dai->dma_data;
- prtd->params->dma_intr_handler = at32_pcm_dma_irq;
-
- prtd->dma_buffer = runtime->dma_addr;
- prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
- prtd->period_size = params_period_bytes(params);
-
- pr_debug("hw_params: DMA for %s initialized "
- "(dma_bytes=%ld, period_size=%ld)\n",
- prtd->params->name, runtime->dma_bytes, prtd->period_size);
-
- return 0;
-}
-
-
-
-static int at32_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct at32_runtime_data *prtd = substream->runtime->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
-
- if (params != NULL) {
- ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
- params->mask->pdc_disable);
- prtd->params->dma_intr_handler = NULL;
- }
-
- return 0;
-}
-
-
-
-static int at32_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct at32_runtime_data *prtd = substream->runtime->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
-
- ssc_writex(params->ssc->regs, SSC_IDR,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
-
- return 0;
-}
-
-
-static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_pcm_runtime *rtd = substream->runtime;
- struct at32_runtime_data *prtd = rtd->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
- int ret = 0;
-
- pr_debug("at32_pcm_trigger: buffer_size = %ld, "
- "dma_area = %p, dma_bytes = %ld\n",
- rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- prtd->period_ptr = prtd->dma_buffer;
-
- ssc_writex(params->ssc->regs, params->pdc->xpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- prtd->period_ptr += prtd->period_size;
- ssc_writex(params->ssc->regs, params->pdc->xnpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
-
- pr_debug("trigger: period_ptr=%lx, xpr=%x, "
- "xcr=%d, xnpr=%x, xncr=%d\n",
- (unsigned long)prtd->period_ptr,
- ssc_readx(params->ssc->regs, params->pdc->xpr),
- ssc_readx(params->ssc->regs, params->pdc->xcr),
- ssc_readx(params->ssc->regs, params->pdc->xnpr),
- ssc_readx(params->ssc->regs, params->pdc->xncr));
-
- ssc_writex(params->ssc->regs, SSC_IER,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
- ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
- params->mask->pdc_enable);
-
- pr_debug("sr=%x, imr=%x\n",
- ssc_readx(params->ssc->regs, SSC_SR),
- ssc_readx(params->ssc->regs, SSC_IER));
- break; /* SNDRV_PCM_TRIGGER_START */
-
-
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- break;
-
-
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
- break;
-
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-
-
-static snd_pcm_uframes_t at32_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at32_runtime_data *prtd = runtime->private_data;
- struct at32_pcm_dma_params *params = prtd->params;
- dma_addr_t ptr;
- snd_pcm_uframes_t x;
-
- ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
- x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-
- if (x == runtime->buffer_size)
- x = 0;
-
- return x;
-}
-
-
-
-static int at32_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at32_runtime_data *prtd;
- int ret = 0;
-
- snd_soc_set_runtime_hwparams(substream, &at32_pcm_hardware);
-
- /* ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- goto out;
-
- prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
- if (prtd == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- runtime->private_data = prtd;
-
-
-out:
- return ret;
-}
-
-
-
-static int at32_pcm_close(struct snd_pcm_substream *substream)
-{
- struct at32_runtime_data *prtd = substream->runtime->private_data;
-
- kfree(prtd);
- return 0;
-}
-
-
-static int at32_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return remap_pfn_range(vma, vma->vm_start,
- substream->dma_buffer.addr >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
-
-
-static struct snd_pcm_ops at32_pcm_ops = {
- .open = at32_pcm_open,
- .close = at32_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = at32_pcm_hw_params,
- .hw_free = at32_pcm_hw_free,
- .prepare = at32_pcm_prepare,
- .trigger = at32_pcm_trigger,
- .pointer = at32_pcm_pointer,
- .mmap = at32_pcm_mmap,
-};
-
-
-
-/*--------------------------------------------------------------------------*\
- * ASoC platform driver
-\*--------------------------------------------------------------------------*/
-static u64 at32_pcm_dmamask = 0xffffffff;
-
-static int at32_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai,
- struct snd_pcm *pcm)
-{
- int ret = 0;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &at32_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
-
- if (dai->playback.channels_min) {
- ret = at32_pcm_preallocate_dma_buffer(
- pcm, SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
-
- if (dai->capture.channels_min) {
- pr_debug("at32-pcm: Allocating PCM capture DMA buffer\n");
- ret = at32_pcm_preallocate_dma_buffer(
- pcm, SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
-
-
-out:
- return ret;
-}
-
-
-
-static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (substream == NULL)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
- dma_free_coherent(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
-
-
-#ifdef CONFIG_PM
-static int at32_pcm_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at32_runtime_data *prtd;
- struct at32_pcm_dma_params *params;
-
- if (runtime == NULL)
- return 0;
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* Disable the PDC and save the PDC registers */
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
-
- prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
- prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
- prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
- prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
-
- return 0;
-}
-
-
-
-static int at32_pcm_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at32_runtime_data *prtd;
- struct at32_pcm_dma_params *params;
-
- if (runtime == NULL)
- return 0;
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* Restore the PDC registers and enable the PDC */
- ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
- ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
- ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
- ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
-
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, params->mask->pdc_enable);
- return 0;
-}
-#else /* CONFIG_PM */
-# define at32_pcm_suspend NULL
-# define at32_pcm_resume NULL
-#endif /* CONFIG_PM */
-
-
-
-struct snd_soc_platform at32_soc_platform = {
- .name = "at32-audio",
- .pcm_ops = &at32_pcm_ops,
- .pcm_new = at32_pcm_new,
- .pcm_free = at32_pcm_free_dma_buffers,
- .suspend = at32_pcm_suspend,
- .resume = at32_pcm_resume,
-};
-EXPORT_SYMBOL_GPL(at32_soc_platform);
-
-
-
-MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
-MODULE_DESCRIPTION("Atmel AT32 PCM module");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/* sound/soc/at32/at32-pcm.h
- * ASoC PCM interface for Atmel AT32 SoC
- *
- * Copyright (C) 2008 Long Range Systems
- * Geoffrey Wossum <gwossum@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __SOUND_SOC_AT32_AT32_PCM_H
-#define __SOUND_SOC_AT32_AT32_PCM_H __FILE__
-
-#include <linux/atmel-ssc.h>
-
-
-/*
- * Registers and status bits that are required by the PCM driver
- * TODO: Is ptcr really used?
- */
-struct at32_pdc_regs {
- u32 xpr; /* PDC RX/TX pointer */
- u32 xcr; /* PDC RX/TX counter */
- u32 xnpr; /* PDC next RX/TX pointer */
- u32 xncr; /* PDC next RX/TX counter */
- u32 ptcr; /* PDC transfer control */
-};
-
-
-
-/*
- * SSC mask info
- */
-struct at32_ssc_mask {
- u32 ssc_enable; /* SSC RX/TX enable */
- u32 ssc_disable; /* SSC RX/TX disable */
- u32 ssc_endx; /* SSC ENDTX or ENDRX */
- u32 ssc_endbuf; /* SSC TXBUFF or RXBUFF */
- u32 pdc_enable; /* PDC RX/TX enable */
- u32 pdc_disable; /* PDC RX/TX disable */
-};
-
-
-
-/*
- * This structure, shared between the PCM driver and the interface,
- * contains all information required by the PCM driver to perform the
- * PDC DMA operation. All fields except dma_intr_handler() are initialized
- * by the interface. The dms_intr_handler() pointer is set by the PCM
- * driver and called by the interface SSC interrupt handler if it is
- * non-NULL.
- */
-struct at32_pcm_dma_params {
- char *name; /* stream identifier */
- int pdc_xfer_size; /* PDC counter increment in bytes */
- struct ssc_device *ssc; /* SSC device for stream */
- struct at32_pdc_regs *pdc; /* PDC register info */
- struct at32_ssc_mask *mask; /* SSC mask info */
- struct snd_pcm_substream *substream;
- void (*dma_intr_handler) (u32, struct snd_pcm_substream *);
-};
-
-
-
-/*
- * The AT32 ASoC platform driver
- */
-extern struct snd_soc_platform at32_soc_platform;
-
-
-
-/*
- * SSC register access (since ssc_writel() / ssc_readl() require literal name)
- */
-#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
-#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
-
-#endif /* __SOUND_SOC_AT32_AT32_PCM_H */
+++ /dev/null
-/* sound/soc/at32/at32-ssc.c
- * ASoC platform driver for AT32 using SSC as DAI
- *
- * Copyright (C) 2008 Long Range Systems
- * Geoffrey Wossum <gwossum@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Note that this is basically a port of the sound/soc/at91-ssc.c to
- * the AVR32 kernel. Thanks to Frank Mandarino for that code.
- */
-
-/* #define DEBUG */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/atmel_pdc.h>
-#include <linux/atmel-ssc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-
-#include "at32-pcm.h"
-#include "at32-ssc.h"
-
-
-
-/*-------------------------------------------------------------------------*\
- * Constants
-\*-------------------------------------------------------------------------*/
-#define NUM_SSC_DEVICES 3
-
-/*
- * SSC direction masks
- */
-#define SSC_DIR_MASK_UNUSED 0
-#define SSC_DIR_MASK_PLAYBACK 1
-#define SSC_DIR_MASK_CAPTURE 2
-
-/*
- * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
- * are expected to be used with SSC_BF
- */
-/* START bit field values */
-#define SSC_START_CONTINUOUS 0
-#define SSC_START_TX_RX 1
-#define SSC_START_LOW_RF 2
-#define SSC_START_HIGH_RF 3
-#define SSC_START_FALLING_RF 4
-#define SSC_START_RISING_RF 5
-#define SSC_START_LEVEL_RF 6
-#define SSC_START_EDGE_RF 7
-#define SSS_START_COMPARE_0 8
-
-/* CKI bit field values */
-#define SSC_CKI_FALLING 0
-#define SSC_CKI_RISING 1
-
-/* CKO bit field values */
-#define SSC_CKO_NONE 0
-#define SSC_CKO_CONTINUOUS 1
-#define SSC_CKO_TRANSFER 2
-
-/* CKS bit field values */
-#define SSC_CKS_DIV 0
-#define SSC_CKS_CLOCK 1
-#define SSC_CKS_PIN 2
-
-/* FSEDGE bit field values */
-#define SSC_FSEDGE_POSITIVE 0
-#define SSC_FSEDGE_NEGATIVE 1
-
-/* FSOS bit field values */
-#define SSC_FSOS_NONE 0
-#define SSC_FSOS_NEGATIVE 1
-#define SSC_FSOS_POSITIVE 2
-#define SSC_FSOS_LOW 3
-#define SSC_FSOS_HIGH 4
-#define SSC_FSOS_TOGGLE 5
-
-#define START_DELAY 1
-
-
-
-/*-------------------------------------------------------------------------*\
- * Module data
-\*-------------------------------------------------------------------------*/
-/*
- * SSC PDC registered required by the PCM DMA engine
- */
-static struct at32_pdc_regs pdc_tx_reg = {
- .xpr = SSC_PDC_TPR,
- .xcr = SSC_PDC_TCR,
- .xnpr = SSC_PDC_TNPR,
- .xncr = SSC_PDC_TNCR,
-};
-
-
-
-static struct at32_pdc_regs pdc_rx_reg = {
- .xpr = SSC_PDC_RPR,
- .xcr = SSC_PDC_RCR,
- .xnpr = SSC_PDC_RNPR,
- .xncr = SSC_PDC_RNCR,
-};
-
-
-
-/*
- * SSC and PDC status bits for transmit and receive
- */
-static struct at32_ssc_mask ssc_tx_mask = {
- .ssc_enable = SSC_BIT(CR_TXEN),
- .ssc_disable = SSC_BIT(CR_TXDIS),
- .ssc_endx = SSC_BIT(SR_ENDTX),
- .ssc_endbuf = SSC_BIT(SR_TXBUFE),
- .pdc_enable = SSC_BIT(PDC_PTCR_TXTEN),
- .pdc_disable = SSC_BIT(PDC_PTCR_TXTDIS),
-};
-
-
-
-static struct at32_ssc_mask ssc_rx_mask = {
- .ssc_enable = SSC_BIT(CR_RXEN),
- .ssc_disable = SSC_BIT(CR_RXDIS),
- .ssc_endx = SSC_BIT(SR_ENDRX),
- .ssc_endbuf = SSC_BIT(SR_RXBUFF),
- .pdc_enable = SSC_BIT(PDC_PTCR_RXTEN),
- .pdc_disable = SSC_BIT(PDC_PTCR_RXTDIS),
-};
-
-
-
-/*
- * DMA parameters for each SSC
- */
-static struct at32_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
- {
- {
- .name = "SSC0 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC0 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- },
- },
- {
- {
- .name = "SSC1 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC1 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- },
- },
- {
- {
- .name = "SSC2 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC2 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- },
- },
-};
-
-
-
-static struct at32_ssc_info ssc_info[NUM_SSC_DEVICES] = {
- {
- .name = "ssc0",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
- {
- .name = "ssc1",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
- {
- .name = "ssc2",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
-};
-
-
-
-
-/*-------------------------------------------------------------------------*\
- * ISR
-\*-------------------------------------------------------------------------*/
-/*
- * SSC interrupt handler. Passes PDC interrupts to the DMA interrupt
- * handler in the PCM driver.
- */
-static irqreturn_t at32_ssc_interrupt(int irq, void *dev_id)
-{
- struct at32_ssc_info *ssc_p = dev_id;
- struct at32_pcm_dma_params *dma_params;
- u32 ssc_sr;
- u32 ssc_substream_mask;
- int i;
-
- ssc_sr = (ssc_readl(ssc_p->ssc->regs, SR) &
- ssc_readl(ssc_p->ssc->regs, IMR));
-
- /*
- * Loop through substreams attached to this SSC. If a DMA-related
- * interrupt occured on that substream, call the DMA interrupt
- * handler function, if one has been registered in the dma_param
- * structure by the PCM driver.
- */
- for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
- dma_params = ssc_p->dma_params[i];
-
- if ((dma_params != NULL) &&
- (dma_params->dma_intr_handler != NULL)) {
- ssc_substream_mask = (dma_params->mask->ssc_endx |
- dma_params->mask->ssc_endbuf);
- if (ssc_sr & ssc_substream_mask) {
- dma_params->dma_intr_handler(ssc_sr,
- dma_params->
- substream);
- }
- }
- }
-
-
- return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*\
- * DAI functions
-\*-------------------------------------------------------------------------*/
-/*
- * Startup. Only that one substream allowed in each direction.
- */
-static int at32_ssc_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- int dir_mask;
-
- dir_mask = ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- SSC_DIR_MASK_PLAYBACK : SSC_DIR_MASK_CAPTURE);
-
- spin_lock_irq(&ssc_p->lock);
- if (ssc_p->dir_mask & dir_mask) {
- spin_unlock_irq(&ssc_p->lock);
- return -EBUSY;
- }
- ssc_p->dir_mask |= dir_mask;
- spin_unlock_irq(&ssc_p->lock);
-
- return 0;
-}
-
-
-
-/*
- * Shutdown. Clear DMA parameters and shutdown the SSC if there
- * are no other substreams open.
- */
-static void at32_ssc_shutdown(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at32_pcm_dma_params *dma_params;
- int dir_mask;
-
- dma_params = ssc_p->dma_params[substream->stream];
-
- if (dma_params != NULL) {
- ssc_writel(dma_params->ssc->regs, CR,
- dma_params->mask->ssc_disable);
- pr_debug("%s disabled SSC_SR=0x%08x\n",
- (substream->stream ? "receiver" : "transmit"),
- ssc_readl(ssc_p->ssc->regs, SR));
-
- dma_params->ssc = NULL;
- dma_params->substream = NULL;
- ssc_p->dma_params[substream->stream] = NULL;
- }
-
-
- dir_mask = 1 << substream->stream;
- spin_lock_irq(&ssc_p->lock);
- ssc_p->dir_mask &= ~dir_mask;
- if (!ssc_p->dir_mask) {
- /* Shutdown the SSC clock */
- pr_debug("at32-ssc: Stopping user %d clock\n",
- ssc_p->ssc->user);
- clk_disable(ssc_p->ssc->clk);
-
- if (ssc_p->initialized) {
- free_irq(ssc_p->ssc->irq, ssc_p);
- ssc_p->initialized = 0;
- }
-
- /* Reset the SSC */
- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
-
- /* clear the SSC dividers */
- ssc_p->cmr_div = 0;
- ssc_p->tcmr_period = 0;
- ssc_p->rcmr_period = 0;
- }
- spin_unlock_irq(&ssc_p->lock);
-}
-
-
-
-/*
- * Set the SSC system clock rate
- */
-static int at32_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
- int clk_id, unsigned int freq, int dir)
-{
- /* TODO: What the heck do I do here? */
- return 0;
-}
-
-
-
-/*
- * Record DAI format for use by hw_params()
- */
-static int at32_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
- unsigned int fmt)
-{
- struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- ssc_p->daifmt = fmt;
- return 0;
-}
-
-
-
-/*
- * Record SSC clock dividers for use in hw_params()
- */
-static int at32_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
- int div_id, int div)
-{
- struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- switch (div_id) {
- case AT32_SSC_CMR_DIV:
- /*
- * The same master clock divider is used for both
- * transmit and receive, so if a value has already
- * been set, it must match this value
- */
- if (ssc_p->cmr_div == 0)
- ssc_p->cmr_div = div;
- else if (div != ssc_p->cmr_div)
- return -EBUSY;
- break;
-
- case AT32_SSC_TCMR_PERIOD:
- ssc_p->tcmr_period = div;
- break;
-
- case AT32_SSC_RCMR_PERIOD:
- ssc_p->rcmr_period = div;
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-
-
-/*
- * Configure the SSC
- */
-static int at32_ssc_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- int id = rtd->dai->cpu_dai->id;
- struct at32_ssc_info *ssc_p = &ssc_info[id];
- struct at32_pcm_dma_params *dma_params;
- int channels, bits;
- u32 tfmr, rfmr, tcmr, rcmr;
- int start_event;
- int ret;
-
-
- /*
- * Currently, there is only one set of dma_params for each direction.
- * If more are added, this code will have to be changed to select
- * the proper set
- */
- dma_params = &ssc_dma_params[id][substream->stream];
- dma_params->ssc = ssc_p->ssc;
- dma_params->substream = substream;
-
- ssc_p->dma_params[substream->stream] = dma_params;
-
-
- /*
- * The cpu_dai->dma_data field is only used to communicate the
- * appropriate DMA parameters to the PCM driver's hw_params()
- * function. It should not be used for other purposes as it
- * is common to all substreams.
- */
- rtd->dai->cpu_dai->dma_data = dma_params;
-
- channels = params_channels(params);
-
-
- /*
- * Determine sample size in bits and the PDC increment
- */
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
- bits = 8;
- dma_params->pdc_xfer_size = 1;
- break;
-
- case SNDRV_PCM_FORMAT_S16:
- bits = 16;
- dma_params->pdc_xfer_size = 2;
- break;
-
- case SNDRV_PCM_FORMAT_S24:
- bits = 24;
- dma_params->pdc_xfer_size = 4;
- break;
-
- case SNDRV_PCM_FORMAT_S32:
- bits = 32;
- dma_params->pdc_xfer_size = 4;
- break;
-
- default:
- pr_warning("at32-ssc: Unsupported PCM format %d",
- params_format(params));
- return -EINVAL;
- }
- pr_debug("at32-ssc: bits = %d, pdc_xfer_size = %d, channels = %d\n",
- bits, dma_params->pdc_xfer_size, channels);
-
-
- /*
- * The SSC only supports up to 16-bit samples in I2S format, due
- * to the size of the Frame Mode Register FSLEN field.
- */
- if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
- if (bits > 16) {
- pr_warning("at32-ssc: "
- "sample size %d is too large for I2S\n",
- bits);
- return -EINVAL;
- }
-
-
- /*
- * Compute the SSC register settings
- */
- switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK |
- SND_SOC_DAIFMT_MASTER_MASK)) {
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * I2S format, SSC provides BCLK and LRS clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line
- */
- pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME master\n");
- rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
- SSC_BF(RCMR_STTDLY, START_DELAY) |
- SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
- SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
- SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
- SSC_BF(RCMR_CKS, SSC_CKS_DIV));
-
- rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
- SSC_BF(RFMR_FSLEN, bits - 1) |
- SSC_BF(RFMR_DATNB, channels - 1) |
- SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
-
- tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
- SSC_BF(TCMR_STTDLY, START_DELAY) |
- SSC_BF(TCMR_START, SSC_START_FALLING_RF) |
- SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
- SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
- SSC_BF(TCMR_CKS, SSC_CKS_DIV));
-
- tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
- SSC_BF(TFMR_FSLEN, bits - 1) |
- SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) |
- SSC_BF(TFMR_DATLEN, bits - 1));
- break;
-
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
- /*
- * I2S format, CODEC supplies BCLK and LRC clock.
- *
- * The SSC transmit clock is obtained from the BCLK signal
- * on the TK line, and the SSC receive clock is generated from
- * the transmit clock.
- *
- * For single channel data, one sample is transferred on the
- * falling edge of the LRC clock. For two channel data, one
- * sample is transferred on both edges of the LRC clock.
- */
- pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME slave\n");
- start_event = ((channels == 1) ?
- SSC_START_FALLING_RF : SSC_START_EDGE_RF);
-
- rcmr = (SSC_BF(RCMR_STTDLY, START_DELAY) |
- SSC_BF(RCMR_START, start_event) |
- SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
- SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
- SSC_BF(RCMR_CKS, SSC_CKS_CLOCK));
-
- rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) |
- SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
-
- tcmr = (SSC_BF(TCMR_STTDLY, START_DELAY) |
- SSC_BF(TCMR_START, start_event) |
- SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
- SSC_BF(TCMR_CKO, SSC_CKO_NONE) |
- SSC_BF(TCMR_CKS, SSC_CKS_PIN));
-
- tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) |
- SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
- break;
-
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line
- */
- pr_debug("at32-ssc: SSC mode is DSP A BCLK / FRAME master\n");
- rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
- SSC_BF(RCMR_STTDLY, 1) |
- SSC_BF(RCMR_START, SSC_START_RISING_RF) |
- SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
- SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
- SSC_BF(RCMR_CKS, SSC_CKS_DIV));
-
- rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) |
- SSC_BF(RFMR_DATNB, channels - 1) |
- SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
-
- tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
- SSC_BF(TCMR_STTDLY, 1) |
- SSC_BF(TCMR_START, SSC_START_RISING_RF) |
- SSC_BF(TCMR_CKI, SSC_CKI_RISING) |
- SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
- SSC_BF(TCMR_CKS, SSC_CKS_DIV));
-
- tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
- SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) |
- SSC_BF(TFMR_DATNB, channels - 1) |
- SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
- break;
-
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
- default:
- pr_warning("at32-ssc: unsupported DAI format 0x%x\n",
- ssc_p->daifmt);
- return -EINVAL;
- break;
- }
- pr_debug("at32-ssc: RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
- rcmr, rfmr, tcmr, tfmr);
-
-
- if (!ssc_p->initialized) {
- /* enable peripheral clock */
- pr_debug("at32-ssc: Starting clock\n");
- clk_enable(ssc_p->ssc->clk);
-
- /* Reset the SSC and its PDC registers */
- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
-
- ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
-
- ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
-
- ret = request_irq(ssc_p->ssc->irq, at32_ssc_interrupt, 0,
- ssc_p->name, ssc_p);
- if (ret < 0) {
- pr_warning("at32-ssc: request irq failed (%d)\n", ret);
- pr_debug("at32-ssc: Stopping clock\n");
- clk_disable(ssc_p->ssc->clk);
- return ret;
- }
-
- ssc_p->initialized = 1;
- }
-
- /* Set SSC clock mode register */
- ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
-
- /* set receive clock mode and format */
- ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
- ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
-
- /* set transmit clock mode and format */
- ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
- ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
-
- pr_debug("at32-ssc: SSC initialized\n");
- return 0;
-}
-
-
-
-static int at32_ssc_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at32_pcm_dma_params *dma_params;
-
- dma_params = ssc_p->dma_params[substream->stream];
-
- ssc_writel(dma_params->ssc->regs, CR, dma_params->mask->ssc_enable);
-
- return 0;
-}
-
-
-
-#ifdef CONFIG_PM
-static int at32_ssc_suspend(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at32_ssc_info *ssc_p;
-
- if (!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- /* Save the status register before disabling transmit and receive */
- ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
-
- /* Save the current interrupt mask, then disable unmasked interrupts */
- ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
- ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
-
- ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
- ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
- ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
- ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
- ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
-
- return 0;
-}
-
-
-
-static int at32_ssc_resume(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at32_ssc_info *ssc_p;
- u32 cr;
-
- if (!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- /* restore SSC register settings */
- ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
- ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
- ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
- ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
- ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
-
- /* re-enable interrupts */
- ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
-
- /* Re-enable recieve and transmit as appropriate */
- cr = 0;
- cr |=
- (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
- cr |=
- (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
- ssc_writel(ssc_p->ssc->regs, CR, cr);
-
- return 0;
-}
-#else /* CONFIG_PM */
-# define at32_ssc_suspend NULL
-# define at32_ssc_resume NULL
-#endif /* CONFIG_PM */
-
-
-#define AT32_SSC_RATES \
- (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
- SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-
-
-#define AT32_SSC_FORMATS \
- (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16 | \
- SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_S32)
-
-
-struct snd_soc_dai at32_ssc_dai[NUM_SSC_DEVICES] = {
- {
- .name = "at32-ssc0",
- .id = 0,
- .type = SND_SOC_DAI_PCM,
- .suspend = at32_ssc_suspend,
- .resume = at32_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .ops = {
- .startup = at32_ssc_startup,
- .shutdown = at32_ssc_shutdown,
- .prepare = at32_ssc_prepare,
- .hw_params = at32_ssc_hw_params,
- },
- .dai_ops = {
- .set_sysclk = at32_ssc_set_dai_sysclk,
- .set_fmt = at32_ssc_set_dai_fmt,
- .set_clkdiv = at32_ssc_set_dai_clkdiv,
- },
- .private_data = &ssc_info[0],
- },
- {
- .name = "at32-ssc1",
- .id = 1,
- .type = SND_SOC_DAI_PCM,
- .suspend = at32_ssc_suspend,
- .resume = at32_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .ops = {
- .startup = at32_ssc_startup,
- .shutdown = at32_ssc_shutdown,
- .prepare = at32_ssc_prepare,
- .hw_params = at32_ssc_hw_params,
- },
- .dai_ops = {
- .set_sysclk = at32_ssc_set_dai_sysclk,
- .set_fmt = at32_ssc_set_dai_fmt,
- .set_clkdiv = at32_ssc_set_dai_clkdiv,
- },
- .private_data = &ssc_info[1],
- },
- {
- .name = "at32-ssc2",
- .id = 2,
- .type = SND_SOC_DAI_PCM,
- .suspend = at32_ssc_suspend,
- .resume = at32_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT32_SSC_RATES,
- .formats = AT32_SSC_FORMATS,
- },
- .ops = {
- .startup = at32_ssc_startup,
- .shutdown = at32_ssc_shutdown,
- .prepare = at32_ssc_prepare,
- .hw_params = at32_ssc_hw_params,
- },
- .dai_ops = {
- .set_sysclk = at32_ssc_set_dai_sysclk,
- .set_fmt = at32_ssc_set_dai_fmt,
- .set_clkdiv = at32_ssc_set_dai_clkdiv,
- },
- .private_data = &ssc_info[2],
- },
-};
-EXPORT_SYMBOL_GPL(at32_ssc_dai);
-
-
-MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
-MODULE_DESCRIPTION("AT32 SSC ASoC Interface");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/* sound/soc/at32/at32-ssc.h
- * ASoC SSC interface for Atmel AT32 SoC
- *
- * Copyright (C) 2008 Long Range Systems
- * Geoffrey Wossum <gwossum@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __SOUND_SOC_AT32_AT32_SSC_H
-#define __SOUND_SOC_AT32_AT32_SSC_H __FILE__
-
-#include <linux/types.h>
-#include <linux/atmel-ssc.h>
-
-#include "at32-pcm.h"
-
-
-
-struct at32_ssc_state {
- u32 ssc_cmr;
- u32 ssc_rcmr;
- u32 ssc_rfmr;
- u32 ssc_tcmr;
- u32 ssc_tfmr;
- u32 ssc_sr;
- u32 ssc_imr;
-};
-
-
-
-struct at32_ssc_info {
- char *name;
- struct ssc_device *ssc;
- spinlock_t lock; /* lock for dir_mask */
- unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
- unsigned short initialized; /* true if SSC has been initialized */
- unsigned short daifmt;
- unsigned short cmr_div;
- unsigned short tcmr_period;
- unsigned short rcmr_period;
- struct at32_pcm_dma_params *dma_params[2];
- struct at32_ssc_state ssc_state;
-};
-
-
-/* SSC divider ids */
-#define AT32_SSC_CMR_DIV 0 /* MCK divider for BCLK */
-#define AT32_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
-#define AT32_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
-
-
-extern struct snd_soc_dai at32_ssc_dai[];
-
-
-
-#endif /* __SOUND_SOC_AT32_AT32_SSC_H */
+++ /dev/null
-config SND_AT91_SOC
- tristate "SoC Audio for the Atmel AT91 System-on-Chip"
- depends on ARCH_AT91
- help
- Say Y or M if you want to add support for codecs attached to
- the AT91 SSC interface. You will also need
- to select the audio interfaces to support below.
-
-config SND_AT91_SOC_SSC
- tristate
+++ /dev/null
-# AT91 Platform Support
-snd-soc-at91-objs := at91-pcm.o
-snd-soc-at91-ssc-objs := at91-ssc.o
-
-obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
-obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
+++ /dev/null
-/*
- * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Mar 3, 2006
- *
- * Based on pxa2xx-pcm.c by:
- *
- * Author: Nicolas Pitre
- * Created: Nov 30, 2004
- * Copyright: (C) 2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <mach/hardware.h>
-#include <mach/at91_ssc.h>
-
-#include "at91-pcm.h"
-
-#if 0
-#define DBG(x...) printk(KERN_INFO "at91-pcm: " x)
-#else
-#define DBG(x...)
-#endif
-
-static const struct snd_pcm_hardware at91_pcm_hardware = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .period_bytes_min = 32,
- .period_bytes_max = 8192,
- .periods_min = 2,
- .periods_max = 1024,
- .buffer_bytes_max = 32 * 1024,
-};
-
-struct at91_runtime_data {
- struct at91_pcm_dma_params *params;
- dma_addr_t dma_buffer; /* physical address of dma buffer */
- dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
- size_t period_size;
- dma_addr_t period_ptr; /* physical address of next period */
- u32 pdc_xpr_save; /* PDC register save */
- u32 pdc_xcr_save;
- u32 pdc_xnpr_save;
- u32 pdc_xncr_save;
-};
-
-static void at91_pcm_dma_irq(u32 ssc_sr,
- struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
- static int count = 0;
-
- count++;
-
- if (ssc_sr & params->mask->ssc_endbuf) {
-
- printk(KERN_WARNING
- "at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK
- ? "underrun" : "overrun",
- params->name, ssc_sr, count);
-
- /* re-start the PDC */
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
-
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end) {
- prtd->period_ptr = prtd->dma_buffer;
- }
-
- at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
- }
-
- if (ssc_sr & params->mask->ssc_endx) {
-
- /* Load the PDC next pointer and counter registers */
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end) {
- prtd->period_ptr = prtd->dma_buffer;
- }
- at91_ssc_write(params->ssc_base + params->pdc->xnpr,
- prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
- }
-
- snd_pcm_period_elapsed(substream);
-}
-
-static int at91_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at91_runtime_data *prtd = runtime->private_data;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
- /* this may get called several times by oss emulation
- * with different params */
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- prtd->params = rtd->dai->cpu_dai->dma_data;
- prtd->params->dma_intr_handler = at91_pcm_dma_irq;
-
- prtd->dma_buffer = runtime->dma_addr;
- prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
- prtd->period_size = params_period_bytes(params);
-
- DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n",
- prtd->params->name, runtime->dma_bytes, prtd->period_size);
- return 0;
-}
-
-static int at91_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
-
- if (params != NULL) {
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
- prtd->params->dma_intr_handler = NULL;
- }
-
- return 0;
-}
-
-static int at91_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
-
- at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
- return 0;
-}
-
-static int at91_pcm_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
- int ret = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- prtd->period_ptr = prtd->dma_buffer;
-
- at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- prtd->period_ptr += prtd->period_size;
- at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
-
- DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n",
- (unsigned long) prtd->period_ptr,
- at91_ssc_read(params->ssc_base + params->pdc->xpr),
- at91_ssc_read(params->ssc_base + params->pdc->xcr),
- at91_ssc_read(params->ssc_base + params->pdc->xnpr),
- at91_ssc_read(params->ssc_base + params->pdc->xncr));
-
- at91_ssc_write(params->ssc_base + AT91_SSC_IER,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
-
- DBG("sr=%lx imr=%lx\n",
- at91_ssc_read(params->ssc_base + AT91_SSC_SR),
- at91_ssc_read(params->ssc_base + AT91_SSC_IMR));
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
- break;
-
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
- break;
-
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static snd_pcm_uframes_t at91_pcm_pointer(
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at91_runtime_data *prtd = runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
- dma_addr_t ptr;
- snd_pcm_uframes_t x;
-
- ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr);
- x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-
- if (x == runtime->buffer_size)
- x = 0;
- return x;
-}
-
-static int at91_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at91_runtime_data *prtd;
- int ret = 0;
-
- snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware);
-
- /* ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- goto out;
-
- prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL);
- if (prtd == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- runtime->private_data = prtd;
-
- out:
- return ret;
-}
-
-static int at91_pcm_close(struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
-
- kfree(prtd);
- return 0;
-}
-
-static int at91_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- return dma_mmap_writecombine(substream->pcm->card->dev, vma,
- runtime->dma_area,
- runtime->dma_addr,
- runtime->dma_bytes);
-}
-
-struct snd_pcm_ops at91_pcm_ops = {
- .open = at91_pcm_open,
- .close = at91_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = at91_pcm_hw_params,
- .hw_free = at91_pcm_hw_free,
- .prepare = at91_pcm_prepare,
- .trigger = at91_pcm_trigger,
- .pointer = at91_pcm_pointer,
- .mmap = at91_pcm_mmap,
-};
-
-static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
- int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = at91_pcm_hardware.buffer_bytes_max;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_writecombine(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
-
- DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
- (void *) buf->area,
- (void *) buf->addr,
- size);
-
- if (!buf->area)
- return -ENOMEM;
-
- buf->bytes = size;
- return 0;
-}
-
-static u64 at91_pcm_dmamask = 0xffffffff;
-
-static int at91_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
-{
- int ret = 0;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &at91_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
-
- if (dai->playback.channels_min) {
- ret = at91_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
-
- if (dai->capture.channels_min) {
- ret = at91_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
- out:
- return ret;
-}
-
-static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
-
- dma_free_writecombine(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
-#ifdef CONFIG_PM
-static int at91_pcm_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at91_runtime_data *prtd;
- struct at91_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* disable the PDC and save the PDC registers */
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
-
- prtd->pdc_xpr_save = at91_ssc_read(params->ssc_base + params->pdc->xpr);
- prtd->pdc_xcr_save = at91_ssc_read(params->ssc_base + params->pdc->xcr);
- prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr);
- prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr);
-
- return 0;
-}
-
-static int at91_pcm_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at91_runtime_data *prtd;
- struct at91_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* restore the PDC registers and enable the PDC */
- at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->pdc_xpr_save);
- at91_ssc_write(params->ssc_base + params->pdc->xcr, prtd->pdc_xcr_save);
- at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
- at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
- return 0;
-}
-#else
-#define at91_pcm_suspend NULL
-#define at91_pcm_resume NULL
-#endif
-
-struct snd_soc_platform at91_soc_platform = {
- .name = "at91-audio",
- .pcm_ops = &at91_pcm_ops,
- .pcm_new = at91_pcm_new,
- .pcm_free = at91_pcm_free_dma_buffers,
- .suspend = at91_pcm_suspend,
- .resume = at91_pcm_resume,
-};
-
-EXPORT_SYMBOL_GPL(at91_soc_platform);
-
-MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
-MODULE_DESCRIPTION("Atmel AT91 PCM module");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Mar 3, 2006
- *
- * Based on pxa2xx-pcm.h by:
- *
- * Author: Nicolas Pitre
- * Created: Nov 30, 2004
- * Copyright: MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _AT91_PCM_H
-#define _AT91_PCM_H
-
-#include <mach/hardware.h>
-
-struct at91_ssc_periph {
- void __iomem *base;
- u32 pid;
-};
-
-/*
- * Registers and status bits that are required by the PCM driver.
- */
-struct at91_pdc_regs {
- unsigned int xpr; /* PDC recv/trans pointer */
- unsigned int xcr; /* PDC recv/trans counter */
- unsigned int xnpr; /* PDC next recv/trans pointer */
- unsigned int xncr; /* PDC next recv/trans counter */
- unsigned int ptcr; /* PDC transfer control */
-};
-
-struct at91_ssc_mask {
- u32 ssc_enable; /* SSC recv/trans enable */
- u32 ssc_disable; /* SSC recv/trans disable */
- u32 ssc_endx; /* SSC ENDTX or ENDRX */
- u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
- u32 pdc_enable; /* PDC recv/trans enable */
- u32 pdc_disable; /* PDC recv/trans disable */
-};
-
-/*
- * This structure, shared between the PCM driver and the interface,
- * contains all information required by the PCM driver to perform the
- * PDC DMA operation. All fields except dma_intr_handler() are initialized
- * by the interface. The dms_intr_handler() pointer is set by the PCM
- * driver and called by the interface SSC interrupt handler if it is
- * non-NULL.
- */
-struct at91_pcm_dma_params {
- char *name; /* stream identifier */
- int pdc_xfer_size; /* PDC counter increment in bytes */
- void __iomem *ssc_base; /* SSC base address */
- struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */
- struct at91_ssc_mask *mask;/* SSC & PDC status bits */
- struct snd_pcm_substream *substream;
- void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
-};
-
-extern struct snd_soc_platform at91_soc_platform;
-
-#define at91_ssc_read(a) ((unsigned long) __raw_readl(a))
-#define at91_ssc_write(a,v) __raw_writel((v),(a))
-
-#endif /* _AT91_PCM_H */
+++ /dev/null
-/*
- * at91-ssc.c -- ALSA SoC AT91 SSC Audio Layer Platform driver
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- *
- * Based on pxa2xx Platform drivers by
- * Liam Girdwood <lrg@slimlogic.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/atmel_pdc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-
-#include <mach/hardware.h>
-#include <mach/at91_pmc.h>
-#include <mach/at91_ssc.h>
-
-#include "at91-pcm.h"
-#include "at91-ssc.h"
-
-#if 0
-#define DBG(x...) printk(KERN_DEBUG "at91-ssc:" x)
-#else
-#define DBG(x...)
-#endif
-
-#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
-#define NUM_SSC_DEVICES 1
-#else
-#define NUM_SSC_DEVICES 3
-#endif
-
-
-/*
- * SSC PDC registers required by the PCM DMA engine.
- */
-static struct at91_pdc_regs pdc_tx_reg = {
- .xpr = ATMEL_PDC_TPR,
- .xcr = ATMEL_PDC_TCR,
- .xnpr = ATMEL_PDC_TNPR,
- .xncr = ATMEL_PDC_TNCR,
-};
-
-static struct at91_pdc_regs pdc_rx_reg = {
- .xpr = ATMEL_PDC_RPR,
- .xcr = ATMEL_PDC_RCR,
- .xnpr = ATMEL_PDC_RNPR,
- .xncr = ATMEL_PDC_RNCR,
-};
-
-/*
- * SSC & PDC status bits for transmit and receive.
- */
-static struct at91_ssc_mask ssc_tx_mask = {
- .ssc_enable = AT91_SSC_TXEN,
- .ssc_disable = AT91_SSC_TXDIS,
- .ssc_endx = AT91_SSC_ENDTX,
- .ssc_endbuf = AT91_SSC_TXBUFE,
- .pdc_enable = ATMEL_PDC_TXTEN,
- .pdc_disable = ATMEL_PDC_TXTDIS,
-};
-
-static struct at91_ssc_mask ssc_rx_mask = {
- .ssc_enable = AT91_SSC_RXEN,
- .ssc_disable = AT91_SSC_RXDIS,
- .ssc_endx = AT91_SSC_ENDRX,
- .ssc_endbuf = AT91_SSC_RXBUFF,
- .pdc_enable = ATMEL_PDC_RXTEN,
- .pdc_disable = ATMEL_PDC_RXTDIS,
-};
-
-
-/*
- * DMA parameters.
- */
-static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
- {{
- .name = "SSC0 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC0 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- }},
-#if NUM_SSC_DEVICES == 3
- {{
- .name = "SSC1 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC1 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- }},
- {{
- .name = "SSC2 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC2 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- }},
-#endif
-};
-
-struct at91_ssc_state {
- u32 ssc_cmr;
- u32 ssc_rcmr;
- u32 ssc_rfmr;
- u32 ssc_tcmr;
- u32 ssc_tfmr;
- u32 ssc_sr;
- u32 ssc_imr;
-};
-
-static struct at91_ssc_info {
- char *name;
- struct at91_ssc_periph ssc;
- spinlock_t lock; /* lock for dir_mask */
- unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
- unsigned short initialized; /* 1=SSC has been initialized */
- unsigned short daifmt;
- unsigned short cmr_div;
- unsigned short tcmr_period;
- unsigned short rcmr_period;
- struct at91_pcm_dma_params *dma_params[2];
- struct at91_ssc_state ssc_state;
-
-} ssc_info[NUM_SSC_DEVICES] = {
- {
- .name = "ssc0",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
- .dir_mask = 0,
- .initialized = 0,
- },
-#if NUM_SSC_DEVICES == 3
- {
- .name = "ssc1",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
- .dir_mask = 0,
- .initialized = 0,
- },
- {
- .name = "ssc2",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
- .dir_mask = 0,
- .initialized = 0,
- },
-#endif
-};
-
-static unsigned int at91_ssc_sysclk;
-
-/*
- * SSC interrupt handler. Passes PDC interrupts to the DMA
- * interrupt handler in the PCM driver.
- */
-static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id)
-{
- struct at91_ssc_info *ssc_p = dev_id;
- struct at91_pcm_dma_params *dma_params;
- u32 ssc_sr;
- int i;
-
- ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)
- & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
-
- /*
- * Loop through the substreams attached to this SSC. If
- * a DMA-related interrupt occurred on that substream, call
- * the DMA interrupt handler function, if one has been
- * registered in the dma_params structure by the PCM driver.
- */
- for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
- dma_params = ssc_p->dma_params[i];
-
- if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
- (ssc_sr &
- (dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
-
- dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
- }
-
- return IRQ_HANDLED;
-}
-
-/*
- * Startup. Only that one substream allowed in each direction.
- */
-static int at91_ssc_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- int dir_mask;
-
- DBG("ssc_startup: SSC_SR=0x%08lx\n",
- at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
- dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
-
- spin_lock_irq(&ssc_p->lock);
- if (ssc_p->dir_mask & dir_mask) {
- spin_unlock_irq(&ssc_p->lock);
- return -EBUSY;
- }
- ssc_p->dir_mask |= dir_mask;
- spin_unlock_irq(&ssc_p->lock);
-
- return 0;
-}
-
-/*
- * Shutdown. Clear DMA parameters and shutdown the SSC if there
- * are no other substreams open.
- */
-static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at91_pcm_dma_params *dma_params;
- int dir, dir_mask;
-
- dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
- dma_params = ssc_p->dma_params[dir];
-
- if (dma_params != NULL) {
- at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
- dma_params->mask->ssc_disable);
- DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
- at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
-
- dma_params->ssc_base = NULL;
- dma_params->substream = NULL;
- ssc_p->dma_params[dir] = NULL;
- }
-
- dir_mask = 1 << dir;
-
- spin_lock_irq(&ssc_p->lock);
- ssc_p->dir_mask &= ~dir_mask;
- if (!ssc_p->dir_mask) {
- /* Shutdown the SSC clock. */
- DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
- at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
-
- if (ssc_p->initialized) {
- free_irq(ssc_p->ssc.pid, ssc_p);
- ssc_p->initialized = 0;
- }
-
- /* Reset the SSC */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
-
- /* Clear the SSC dividers */
- ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
- }
- spin_unlock_irq(&ssc_p->lock);
-}
-
-/*
- * Record the SSC system clock rate.
- */
-static int at91_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
- int clk_id, unsigned int freq, int dir)
-{
- /*
- * The only clock supplied to the SSC is the AT91 master clock,
- * which is only used if the SSC is generating BCLK and/or
- * LRC clocks.
- */
- switch (clk_id) {
- case AT91_SYSCLK_MCK:
- at91_ssc_sysclk = freq;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Record the DAI format for use in hw_params().
- */
-static int at91_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
- unsigned int fmt)
-{
- struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- ssc_p->daifmt = fmt;
- return 0;
-}
-
-/*
- * Record SSC clock dividers for use in hw_params().
- */
-static int at91_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
- int div_id, int div)
-{
- struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- switch (div_id) {
- case AT91SSC_CMR_DIV:
- /*
- * The same master clock divider is used for both
- * transmit and receive, so if a value has already
- * been set, it must match this value.
- */
- if (ssc_p->cmr_div == 0)
- ssc_p->cmr_div = div;
- else
- if (div != ssc_p->cmr_div)
- return -EBUSY;
- break;
-
- case AT91SSC_TCMR_PERIOD:
- ssc_p->tcmr_period = div;
- break;
-
- case AT91SSC_RCMR_PERIOD:
- ssc_p->rcmr_period = div;
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Configure the SSC.
- */
-static int at91_ssc_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- int id = rtd->dai->cpu_dai->id;
- struct at91_ssc_info *ssc_p = &ssc_info[id];
- struct at91_pcm_dma_params *dma_params;
- int dir, channels, bits;
- u32 tfmr, rfmr, tcmr, rcmr;
- int start_event;
- int ret;
-
- /*
- * Currently, there is only one set of dma params for
- * each direction. If more are added, this code will
- * have to be changed to select the proper set.
- */
- dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
-
- dma_params = &ssc_dma_params[id][dir];
- dma_params->ssc_base = ssc_p->ssc.base;
- dma_params->substream = substream;
-
- ssc_p->dma_params[dir] = dma_params;
-
- /*
- * The cpu_dai->dma_data field is only used to communicate the
- * appropriate DMA parameters to the pcm driver hw_params()
- * function. It should not be used for other purposes
- * as it is common to all substreams.
- */
- rtd->dai->cpu_dai->dma_data = dma_params;
-
- channels = params_channels(params);
-
- /*
- * Determine sample size in bits and the PDC increment.
- */
- switch(params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
- bits = 8;
- dma_params->pdc_xfer_size = 1;
- break;
- case SNDRV_PCM_FORMAT_S16_LE:
- bits = 16;
- dma_params->pdc_xfer_size = 2;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- bits = 24;
- dma_params->pdc_xfer_size = 4;
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- bits = 32;
- dma_params->pdc_xfer_size = 4;
- break;
- default:
- printk(KERN_WARNING "at91-ssc: unsupported PCM format\n");
- return -EINVAL;
- }
-
- /*
- * The SSC only supports up to 16-bit samples in I2S format, due
- * to the size of the Frame Mode Register FSLEN field.
- */
- if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
- && bits > 16) {
- printk(KERN_WARNING
- "at91-ssc: sample size %d is too large for I2S\n", bits);
- return -EINVAL;
- }
-
- /*
- * Compute SSC register settings.
- */
- switch (ssc_p->daifmt
- & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * I2S format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line.
- */
- rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
- | (((bits - 1) << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_LOOP)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
- tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( 0 << 23) & AT91_SSC_FSDEN)
- | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
- | (((bits - 1) << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_DATDEF)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
- break;
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
- /*
- * I2S format, CODEC supplies BCLK and LRC clocks.
- *
- * The SSC transmit clock is obtained from the BCLK signal on
- * on the TK line, and the SSC receive clock is generated from the
- * transmit clock.
- *
- * For single channel data, one sample is transferred on the falling
- * edge of the LRC clock. For two channel data, one sample is
- * transferred on both edges of the LRC clock.
- */
- start_event = channels == 1
- ? AT91_SSC_START_FALLING_RF
- : AT91_SSC_START_EDGE_RF;
-
- rcmr = (( 0 << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( start_event ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS);
-
- rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (( 0 << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_LOOP)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
- tcmr = (( 0 << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( start_event ) & AT91_SSC_START)
- | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_PIN ) & AT91_SSC_CKS);
-
- tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( 0 << 23) & AT91_SSC_FSDEN)
- | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (( 0 << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_DATDEF)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
- break;
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line.
- */
- rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_LOOP)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
- tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( 0 << 23) & AT91_SSC_FSDEN)
- | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_DATDEF)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
-
-
- break;
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
- default:
- printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n",
- ssc_p->daifmt);
- return -EINVAL;
- break;
- }
- DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
-
- if (!ssc_p->initialized) {
-
- /* Enable PMC peripheral clock for this SSC */
- DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
- at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
-
- /* Reset the SSC and its PDC registers */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
-
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RCR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNCR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TCR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
-
- if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt,
- 0, ssc_p->name, ssc_p)) < 0) {
- printk(KERN_WARNING "at91-ssc: request_irq failure\n");
-
- DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
- at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
- return ret;
- }
-
- ssc_p->initialized = 1;
- }
-
- /* set SSC clock mode register */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
-
- /* set receive clock mode and format */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
-
- /* set transmit clock mode and format */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
-
- DBG("hw_params: SSC initialized\n");
- return 0;
-}
-
-
-static int at91_ssc_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at91_pcm_dma_params *dma_params;
- int dir;
-
- dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
- dma_params = ssc_p->dma_params[dir];
-
- at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
- dma_params->mask->ssc_enable);
-
- DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
- at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
- return 0;
-}
-
-
-#ifdef CONFIG_PM
-static int at91_ssc_suspend(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at91_ssc_info *ssc_p;
-
- if(!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- /* Save the status register before disabling transmit and receive. */
- ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
- AT91_SSC_TXDIS | AT91_SSC_RXDIS);
-
- /* Save the current interrupt mask, then disable unmasked interrupts. */
- ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr);
-
- ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
- ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
- ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
- ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
- ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
-
- return 0;
-}
-
-static int at91_ssc_resume(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at91_ssc_info *ssc_p;
-
- if(!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr);
-
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr);
-
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
- ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
- ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
-
- return 0;
-}
-
-#else
-#define at91_ssc_suspend NULL
-#define at91_ssc_resume NULL
-#endif
-
-#define AT91_SSC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
- SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
- SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
- SNDRV_PCM_RATE_96000)
-
-#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-
-struct snd_soc_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
- { .name = "at91-ssc0",
- .id = 0,
- .type = SND_SOC_DAI_PCM,
- .suspend = at91_ssc_suspend,
- .resume = at91_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .ops = {
- .startup = at91_ssc_startup,
- .shutdown = at91_ssc_shutdown,
- .prepare = at91_ssc_prepare,
- .hw_params = at91_ssc_hw_params,},
- .dai_ops = {
- .set_sysclk = at91_ssc_set_dai_sysclk,
- .set_fmt = at91_ssc_set_dai_fmt,
- .set_clkdiv = at91_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[0].ssc,
- },
-#if NUM_SSC_DEVICES == 3
- { .name = "at91-ssc1",
- .id = 1,
- .type = SND_SOC_DAI_PCM,
- .suspend = at91_ssc_suspend,
- .resume = at91_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .ops = {
- .startup = at91_ssc_startup,
- .shutdown = at91_ssc_shutdown,
- .prepare = at91_ssc_prepare,
- .hw_params = at91_ssc_hw_params,},
- .dai_ops = {
- .set_sysclk = at91_ssc_set_dai_sysclk,
- .set_fmt = at91_ssc_set_dai_fmt,
- .set_clkdiv = at91_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[1].ssc,
- },
- { .name = "at91-ssc2",
- .id = 2,
- .type = SND_SOC_DAI_PCM,
- .suspend = at91_ssc_suspend,
- .resume = at91_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .ops = {
- .startup = at91_ssc_startup,
- .shutdown = at91_ssc_shutdown,
- .prepare = at91_ssc_prepare,
- .hw_params = at91_ssc_hw_params,},
- .dai_ops = {
- .set_sysclk = at91_ssc_set_dai_sysclk,
- .set_fmt = at91_ssc_set_dai_fmt,
- .set_clkdiv = at91_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[2].ssc,
- },
-#endif
-};
-
-EXPORT_SYMBOL_GPL(at91_ssc_dai);
-
-/* Module information */
-MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
-MODULE_DESCRIPTION("AT91 SSC ASoC Interface");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Jan 9, 2007
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _AT91_SSC_H
-#define _AT91_SSC_H
-
-/* SSC system clock ids */
-#define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
-
-/* SSC divider ids */
-#define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */
-#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
-#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
-
-extern struct snd_soc_dai at91_ssc_dai[];
-
-#endif /* _AT91_SSC_H */
-
--- /dev/null
+config SND_ATMEL_SOC
+ tristate "SoC Audio for the Atmel System-on-Chip"
+ depends on ARCH_AT91 || AVR32
+ help
+ Say Y or M if you want to add support for codecs attached to
+ the ATMEL SSC interface. You will also need
+ to select the audio interfaces to support below.
+
+config SND_ATMEL_SOC_SSC
+ tristate
+ depends on SND_ATMEL_SOC
+ help
+ Say Y or M if you want to add support for codecs the
+ ATMEL SSC interface. You will also needs to select the individual
+ machine drivers to support below.
+
+config SND_AT91_SOC_SAM9G20_WM8731
+ tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
+ depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC
+ select SND_ATMEL_SOC_SSC
+ select SND_SOC_WM8731
+ help
+ Say Y if you want to add support for SoC audio on WM8731-based
+ AT91sam9g20 evaluation board.
+
+config SND_AT32_SOC_PLAYPAQ
+ tristate "SoC Audio support for PlayPaq with WM8510"
+ depends on SND_ATMEL_SOC && BOARD_PLAYPAQ
+ select SND_ATMEL_SOC_SSC
+ select SND_SOC_WM8510
+ help
+ Say Y or M here if you want to add support for SoC audio
+ on the LRS PlayPaq.
+
+config SND_AT32_SOC_PLAYPAQ_SLAVE
+ bool "Run CODEC on PlayPaq in slave mode"
+ depends on SND_AT32_SOC_PLAYPAQ
+ default n
+ help
+ Say Y if you want to run with the AT32 SSC generating the BCLK
+ and FRAME signals on the PlayPaq. Unless you want to play
+ with the AT32 as the SSC master, you probably want to say N here,
+ as this will give you better sound quality.
--- /dev/null
+# AT91 Platform Support
+snd-soc-atmel-pcm-objs := atmel-pcm.o
+snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
+
+obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o
+obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
+
+# AT91 Machine Support
+snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
+
+# AT32 Machine Support
+snd-soc-playpaq-objs := playpaq_wm8510.o
+
+obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
+obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
--- /dev/null
+/*
+ * atmel-pcm.c -- ALSA PCM interface for the Atmel atmel SoC.
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ *
+ * Based on at91-pcm. by:
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Copyright 2006 Endrelia Technologies Inc.
+ *
+ * Based on pxa2xx-pcm.c by:
+ *
+ * Author: Nicolas Pitre
+ * Created: Nov 30, 2004
+ * Copyright: (C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
+#include <linux/atmel-ssc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <mach/hardware.h>
+
+#include "atmel-pcm.h"
+
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+/* TODO: These values were taken from the AT91 platform driver, check
+ * them against real values for AT32
+ */
+static const struct snd_pcm_hardware atmel_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .period_bytes_min = 32,
+ .period_bytes_max = 8192,
+ .periods_min = 2,
+ .periods_max = 1024,
+ .buffer_bytes_max = 32 * 1024,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * Data types
+\*--------------------------------------------------------------------------*/
+struct atmel_runtime_data {
+ struct atmel_pcm_dma_params *params;
+ dma_addr_t dma_buffer; /* physical address of dma buffer */
+ dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
+ size_t period_size;
+
+ dma_addr_t period_ptr; /* physical address of next period */
+ int periods; /* period index of period_ptr */
+
+ /* PDC register save */
+ u32 pdc_xpr_save;
+ u32 pdc_xcr_save;
+ u32 pdc_xnpr_save;
+ u32 pdc_xncr_save;
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * Helper functions
+\*--------------------------------------------------------------------------*/
+static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
+ int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = atmel_pcm_hardware.buffer_bytes_max;
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_coherent(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ pr_debug("atmel-pcm:"
+ "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
+ (void *) buf->area,
+ (void *) buf->addr,
+ size);
+
+ if (!buf->area)
+ return -ENOMEM;
+
+ buf->bytes = size;
+ return 0;
+}
+/*--------------------------------------------------------------------------*\
+ * ISR
+\*--------------------------------------------------------------------------*/
+static void atmel_pcm_dma_irq(u32 ssc_sr,
+ struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+ static int count;
+
+ count++;
+
+ if (ssc_sr & params->mask->ssc_endbuf) {
+ pr_warning("atmel-pcm: buffer %s on %s"
+ " (SSC_SR=%#x, count=%d)\n",
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+ ? "underrun" : "overrun",
+ params->name, ssc_sr, count);
+
+ /* re-start the PDC */
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end)
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_enable);
+ }
+
+ if (ssc_sr & params->mask->ssc_endx) {
+ /* Load the PDC next pointer and counter registers */
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end)
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xnpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+ }
+
+ snd_pcm_period_elapsed(substream);
+}
+
+
+/*--------------------------------------------------------------------------*\
+ * PCM operations
+\*--------------------------------------------------------------------------*/
+static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atmel_runtime_data *prtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+ /* this may get called several times by oss emulation
+ * with different params */
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = params_buffer_bytes(params);
+
+ prtd->params = rtd->dai->cpu_dai->dma_data;
+ prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
+
+ prtd->dma_buffer = runtime->dma_addr;
+ prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
+ prtd->period_size = params_period_bytes(params);
+
+ pr_debug("atmel-pcm: "
+ "hw_params: DMA for %s initialized "
+ "(dma_bytes=%u, period_size=%u)\n",
+ prtd->params->name,
+ runtime->dma_bytes,
+ prtd->period_size);
+ return 0;
+}
+
+static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+
+ if (params != NULL) {
+ ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+ params->mask->pdc_disable);
+ prtd->params->dma_intr_handler = NULL;
+ }
+
+ return 0;
+}
+
+static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+
+ ssc_writex(params->ssc->regs, SSC_IDR,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ return 0;
+}
+
+static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct snd_pcm_runtime *rtd = substream->runtime;
+ struct atmel_runtime_data *prtd = rtd->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+ int ret = 0;
+
+ pr_debug("atmel-pcm:buffer_size = %ld,"
+ "dma_area = %p, dma_bytes = %u\n",
+ rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ prtd->period_ptr += prtd->period_size;
+ ssc_writex(params->ssc->regs, params->pdc->xnpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ pr_debug("atmel-pcm: trigger: "
+ "period_ptr=%lx, xpr=%u, "
+ "xcr=%u, xnpr=%u, xncr=%u\n",
+ (unsigned long)prtd->period_ptr,
+ ssc_readx(params->ssc->regs, params->pdc->xpr),
+ ssc_readx(params->ssc->regs, params->pdc->xcr),
+ ssc_readx(params->ssc->regs, params->pdc->xnpr),
+ ssc_readx(params->ssc->regs, params->pdc->xncr));
+
+ ssc_writex(params->ssc->regs, SSC_IER,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+ ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+ params->mask->pdc_enable);
+
+ pr_debug("sr=%u imr=%u\n",
+ ssc_readx(params->ssc->regs, SSC_SR),
+ ssc_readx(params->ssc->regs, SSC_IER));
+ break; /* SNDRV_PCM_TRIGGER_START */
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ break;
+
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_enable);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static snd_pcm_uframes_t atmel_pcm_pointer(
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atmel_runtime_data *prtd = runtime->private_data;
+ struct atmel_pcm_dma_params *params = prtd->params;
+ dma_addr_t ptr;
+ snd_pcm_uframes_t x;
+
+ ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
+ x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
+
+ if (x == runtime->buffer_size)
+ x = 0;
+
+ return x;
+}
+
+static int atmel_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atmel_runtime_data *prtd;
+ int ret = 0;
+
+ snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
+
+ /* ensure that buffer size is a multiple of period size */
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ goto out;
+
+ prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
+ if (prtd == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ runtime->private_data = prtd;
+
+ out:
+ return ret;
+}
+
+static int atmel_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct atmel_runtime_data *prtd = substream->runtime->private_data;
+
+ kfree(prtd);
+ return 0;
+}
+
+static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ return remap_pfn_range(vma, vma->vm_start,
+ substream->dma_buffer.addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+}
+
+struct snd_pcm_ops atmel_pcm_ops = {
+ .open = atmel_pcm_open,
+ .close = atmel_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = atmel_pcm_hw_params,
+ .hw_free = atmel_pcm_hw_free,
+ .prepare = atmel_pcm_prepare,
+ .trigger = atmel_pcm_trigger,
+ .pointer = atmel_pcm_pointer,
+ .mmap = atmel_pcm_mmap,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * ASoC platform driver
+\*--------------------------------------------------------------------------*/
+static u64 atmel_pcm_dmamask = 0xffffffff;
+
+static int atmel_pcm_new(struct snd_card *card,
+ struct snd_soc_dai *dai, struct snd_pcm *pcm)
+{
+ int ret = 0;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &atmel_pcm_dmamask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = 0xffffffff;
+
+ if (dai->playback.channels_min) {
+ ret = atmel_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+ if (dai->capture.channels_min) {
+ pr_debug("at32-pcm:"
+ "Allocating PCM capture DMA buffer\n");
+ ret = atmel_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+ out:
+ return ret;
+}
+
+static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+ dma_free_coherent(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+
+#ifdef CONFIG_PM
+static int atmel_pcm_suspend(struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct atmel_runtime_data *prtd;
+ struct atmel_pcm_dma_params *params;
+
+ if (!runtime)
+ return 0;
+
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* disable the PDC and save the PDC registers */
+
+ ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
+
+ prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
+ prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
+ prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
+ prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
+
+ return 0;
+}
+
+static int atmel_pcm_resume(struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct atmel_runtime_data *prtd;
+ struct atmel_pcm_dma_params *params;
+
+ if (!runtime)
+ return 0;
+
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* restore the PDC registers and enable the PDC */
+ ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
+
+ ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
+ return 0;
+}
+#else
+#define atmel_pcm_suspend NULL
+#define atmel_pcm_resume NULL
+#endif
+
+struct snd_soc_platform atmel_soc_platform = {
+ .name = "atmel-audio",
+ .pcm_ops = &atmel_pcm_ops,
+ .pcm_new = atmel_pcm_new,
+ .pcm_free = atmel_pcm_free_dma_buffers,
+ .suspend = atmel_pcm_suspend,
+ .resume = atmel_pcm_resume,
+};
+EXPORT_SYMBOL_GPL(atmel_soc_platform);
+
+static int __init atmel_pcm_modinit(void)
+{
+ return snd_soc_register_platform(&atmel_soc_platform);
+}
+module_init(atmel_pcm_modinit);
+
+static void __exit atmel_pcm_modexit(void)
+{
+ snd_soc_unregister_platform(&atmel_soc_platform);
+}
+module_exit(atmel_pcm_modexit);
+
+MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
+MODULE_DESCRIPTION("Atmel PCM module");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC.
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ *
+ * Based on at91-pcm. by:
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Copyright 2006 Endrelia Technologies Inc.
+ *
+ * Based on pxa2xx-pcm.c by:
+ *
+ * Author: Nicolas Pitre
+ * Created: Nov 30, 2004
+ * Copyright: (C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ATMEL_PCM_H
+#define _ATMEL_PCM_H
+
+#include <linux/atmel-ssc.h>
+
+/*
+ * Registers and status bits that are required by the PCM driver.
+ */
+struct atmel_pdc_regs {
+ unsigned int xpr; /* PDC recv/trans pointer */
+ unsigned int xcr; /* PDC recv/trans counter */
+ unsigned int xnpr; /* PDC next recv/trans pointer */
+ unsigned int xncr; /* PDC next recv/trans counter */
+ unsigned int ptcr; /* PDC transfer control */
+};
+
+struct atmel_ssc_mask {
+ u32 ssc_enable; /* SSC recv/trans enable */
+ u32 ssc_disable; /* SSC recv/trans disable */
+ u32 ssc_endx; /* SSC ENDTX or ENDRX */
+ u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
+ u32 pdc_enable; /* PDC recv/trans enable */
+ u32 pdc_disable; /* PDC recv/trans disable */
+};
+
+/*
+ * This structure, shared between the PCM driver and the interface,
+ * contains all information required by the PCM driver to perform the
+ * PDC DMA operation. All fields except dma_intr_handler() are initialized
+ * by the interface. The dms_intr_handler() pointer is set by the PCM
+ * driver and called by the interface SSC interrupt handler if it is
+ * non-NULL.
+ */
+struct atmel_pcm_dma_params {
+ char *name; /* stream identifier */
+ int pdc_xfer_size; /* PDC counter increment in bytes */
+ struct ssc_device *ssc; /* SSC device for stream */
+ struct atmel_pdc_regs *pdc; /* PDC receive or transmit registers */
+ struct atmel_ssc_mask *mask; /* SSC & PDC status bits */
+ struct snd_pcm_substream *substream;
+ void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
+};
+
+extern struct snd_soc_platform atmel_soc_platform;
+
+
+/*
+ * SSC register access (since ssc_writel() / ssc_readl() require literal name)
+ */
+#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
+#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
+
+#endif /* _ATMEL_PCM_H */
--- /dev/null
+/*
+ * atmel_ssc_dai.c -- ALSA SoC ATMEL SSC Audio Layer Platform driver
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ * ATMEL CORP.
+ *
+ * Based on at91-ssc.c by
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Based on pxa2xx Platform drivers by
+ * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/atmel_pdc.h>
+
+#include <linux/atmel-ssc.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <mach/hardware.h>
+
+#include "atmel-pcm.h"
+#include "atmel_ssc_dai.h"
+
+
+#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
+#define NUM_SSC_DEVICES 1
+#else
+#define NUM_SSC_DEVICES 3
+#endif
+
+/*
+ * SSC PDC registers required by the PCM DMA engine.
+ */
+static struct atmel_pdc_regs pdc_tx_reg = {
+ .xpr = ATMEL_PDC_TPR,
+ .xcr = ATMEL_PDC_TCR,
+ .xnpr = ATMEL_PDC_TNPR,
+ .xncr = ATMEL_PDC_TNCR,
+};
+
+static struct atmel_pdc_regs pdc_rx_reg = {
+ .xpr = ATMEL_PDC_RPR,
+ .xcr = ATMEL_PDC_RCR,
+ .xnpr = ATMEL_PDC_RNPR,
+ .xncr = ATMEL_PDC_RNCR,
+};
+
+/*
+ * SSC & PDC status bits for transmit and receive.
+ */
+static struct atmel_ssc_mask ssc_tx_mask = {
+ .ssc_enable = SSC_BIT(CR_TXEN),
+ .ssc_disable = SSC_BIT(CR_TXDIS),
+ .ssc_endx = SSC_BIT(SR_ENDTX),
+ .ssc_endbuf = SSC_BIT(SR_TXBUFE),
+ .pdc_enable = ATMEL_PDC_TXTEN,
+ .pdc_disable = ATMEL_PDC_TXTDIS,
+};
+
+static struct atmel_ssc_mask ssc_rx_mask = {
+ .ssc_enable = SSC_BIT(CR_RXEN),
+ .ssc_disable = SSC_BIT(CR_RXDIS),
+ .ssc_endx = SSC_BIT(SR_ENDRX),
+ .ssc_endbuf = SSC_BIT(SR_RXBUFF),
+ .pdc_enable = ATMEL_PDC_RXTEN,
+ .pdc_disable = ATMEL_PDC_RXTDIS,
+};
+
+
+/*
+ * DMA parameters.
+ */
+static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
+ {{
+ .name = "SSC0 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC0 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ } },
+#if NUM_SSC_DEVICES == 3
+ {{
+ .name = "SSC1 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC1 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ } },
+ {{
+ .name = "SSC2 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC2 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ } },
+#endif
+};
+
+
+static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
+ {
+ .name = "ssc0",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
+ .dir_mask = SSC_DIR_MASK_UNUSED,
+ .initialized = 0,
+ },
+#if NUM_SSC_DEVICES == 3
+ {
+ .name = "ssc1",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
+ .dir_mask = SSC_DIR_MASK_UNUSED,
+ .initialized = 0,
+ },
+ {
+ .name = "ssc2",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
+ .dir_mask = SSC_DIR_MASK_UNUSED,
+ .initialized = 0,
+ },
+#endif
+};
+
+
+/*
+ * SSC interrupt handler. Passes PDC interrupts to the DMA
+ * interrupt handler in the PCM driver.
+ */
+static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
+{
+ struct atmel_ssc_info *ssc_p = dev_id;
+ struct atmel_pcm_dma_params *dma_params;
+ u32 ssc_sr;
+ u32 ssc_substream_mask;
+ int i;
+
+ ssc_sr = (unsigned long)ssc_readl(ssc_p->ssc->regs, SR)
+ & (unsigned long)ssc_readl(ssc_p->ssc->regs, IMR);
+
+ /*
+ * Loop through the substreams attached to this SSC. If
+ * a DMA-related interrupt occurred on that substream, call
+ * the DMA interrupt handler function, if one has been
+ * registered in the dma_params structure by the PCM driver.
+ */
+ for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
+ dma_params = ssc_p->dma_params[i];
+
+ if ((dma_params != NULL) &&
+ (dma_params->dma_intr_handler != NULL)) {
+ ssc_substream_mask = (dma_params->mask->ssc_endx |
+ dma_params->mask->ssc_endbuf);
+ if (ssc_sr & ssc_substream_mask) {
+ dma_params->dma_intr_handler(ssc_sr,
+ dma_params->
+ substream);
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+/*-------------------------------------------------------------------------*\
+ * DAI functions
+\*-------------------------------------------------------------------------*/
+/*
+ * Startup. Only that one substream allowed in each direction.
+ */
+static int atmel_ssc_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ int dir_mask;
+
+ pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
+ ssc_readl(ssc_p->ssc->regs, SR));
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir_mask = SSC_DIR_MASK_PLAYBACK;
+ else
+ dir_mask = SSC_DIR_MASK_CAPTURE;
+
+ spin_lock_irq(&ssc_p->lock);
+ if (ssc_p->dir_mask & dir_mask) {
+ spin_unlock_irq(&ssc_p->lock);
+ return -EBUSY;
+ }
+ ssc_p->dir_mask |= dir_mask;
+ spin_unlock_irq(&ssc_p->lock);
+
+ return 0;
+}
+
+/*
+ * Shutdown. Clear DMA parameters and shutdown the SSC if there
+ * are no other substreams open.
+ */
+static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ struct atmel_pcm_dma_params *dma_params;
+ int dir, dir_mask;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = 0;
+ else
+ dir = 1;
+
+ dma_params = ssc_p->dma_params[dir];
+
+ if (dma_params != NULL) {
+ ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
+ pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n",
+ (dir ? "receive" : "transmit"),
+ ssc_readl(ssc_p->ssc->regs, SR));
+
+ dma_params->ssc = NULL;
+ dma_params->substream = NULL;
+ ssc_p->dma_params[dir] = NULL;
+ }
+
+ dir_mask = 1 << dir;
+
+ spin_lock_irq(&ssc_p->lock);
+ ssc_p->dir_mask &= ~dir_mask;
+ if (!ssc_p->dir_mask) {
+ if (ssc_p->initialized) {
+ /* Shutdown the SSC clock. */
+ pr_debug("atmel_ssc_dau: Stopping clock\n");
+ clk_disable(ssc_p->ssc->clk);
+
+ free_irq(ssc_p->ssc->irq, ssc_p);
+ ssc_p->initialized = 0;
+ }
+
+ /* Reset the SSC */
+ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
+ /* Clear the SSC dividers */
+ ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
+ }
+ spin_unlock_irq(&ssc_p->lock);
+}
+
+
+/*
+ * Record the DAI format for use in hw_params().
+ */
+static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+ ssc_p->daifmt = fmt;
+ return 0;
+}
+
+/*
+ * Record SSC clock dividers for use in hw_params().
+ */
+static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
+ int div_id, int div)
+{
+ struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+ switch (div_id) {
+ case ATMEL_SSC_CMR_DIV:
+ /*
+ * The same master clock divider is used for both
+ * transmit and receive, so if a value has already
+ * been set, it must match this value.
+ */
+ if (ssc_p->cmr_div == 0)
+ ssc_p->cmr_div = div;
+ else
+ if (div != ssc_p->cmr_div)
+ return -EBUSY;
+ break;
+
+ case ATMEL_SSC_TCMR_PERIOD:
+ ssc_p->tcmr_period = div;
+ break;
+
+ case ATMEL_SSC_RCMR_PERIOD:
+ ssc_p->rcmr_period = div;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Configure the SSC.
+ */
+static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ int id = rtd->dai->cpu_dai->id;
+ struct atmel_ssc_info *ssc_p = &ssc_info[id];
+ struct atmel_pcm_dma_params *dma_params;
+ int dir, channels, bits;
+ u32 tfmr, rfmr, tcmr, rcmr;
+ int start_event;
+ int ret;
+
+ /*
+ * Currently, there is only one set of dma params for
+ * each direction. If more are added, this code will
+ * have to be changed to select the proper set.
+ */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = 0;
+ else
+ dir = 1;
+
+ dma_params = &ssc_dma_params[id][dir];
+ dma_params->ssc = ssc_p->ssc;
+ dma_params->substream = substream;
+
+ ssc_p->dma_params[dir] = dma_params;
+
+ /*
+ * The cpu_dai->dma_data field is only used to communicate the
+ * appropriate DMA parameters to the pcm driver hw_params()
+ * function. It should not be used for other purposes
+ * as it is common to all substreams.
+ */
+ rtd->dai->cpu_dai->dma_data = dma_params;
+
+ channels = params_channels(params);
+
+ /*
+ * Determine sample size in bits and the PDC increment.
+ */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ bits = 8;
+ dma_params->pdc_xfer_size = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ bits = 16;
+ dma_params->pdc_xfer_size = 2;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ bits = 24;
+ dma_params->pdc_xfer_size = 4;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ bits = 32;
+ dma_params->pdc_xfer_size = 4;
+ break;
+ default:
+ printk(KERN_WARNING "atmel_ssc_dai: unsupported PCM format");
+ return -EINVAL;
+ }
+
+ /*
+ * The SSC only supports up to 16-bit samples in I2S format, due
+ * to the size of the Frame Mode Register FSLEN field.
+ */
+ if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
+ && bits > 16) {
+ printk(KERN_WARNING
+ "atmel_ssc_dai: sample size %d"
+ "is too large for I2S\n", bits);
+ return -EINVAL;
+ }
+
+ /*
+ * Compute SSC register settings.
+ */
+ switch (ssc_p->daifmt
+ & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
+
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
+ /*
+ * I2S format, SSC provides BCLK and LRC clocks.
+ *
+ * The SSC transmit and receive clocks are generated
+ * from the MCK divider, and the BCLK signal
+ * is output on the SSC TK line.
+ */
+ rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
+ | SSC_BF(RCMR_STTDLY, START_DELAY)
+ | SSC_BF(RCMR_START, SSC_START_FALLING_RF)
+ | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
+ | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
+ | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
+
+ rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
+ | SSC_BF(RFMR_FSLEN, (bits - 1))
+ | SSC_BF(RFMR_DATNB, (channels - 1))
+ | SSC_BIT(RFMR_MSBF)
+ | SSC_BF(RFMR_LOOP, 0)
+ | SSC_BF(RFMR_DATLEN, (bits - 1));
+
+ tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
+ | SSC_BF(TCMR_STTDLY, START_DELAY)
+ | SSC_BF(TCMR_START, SSC_START_FALLING_RF)
+ | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
+ | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
+ | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
+
+ tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(TFMR_FSDEN, 0)
+ | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
+ | SSC_BF(TFMR_FSLEN, (bits - 1))
+ | SSC_BF(TFMR_DATNB, (channels - 1))
+ | SSC_BIT(TFMR_MSBF)
+ | SSC_BF(TFMR_DATDEF, 0)
+ | SSC_BF(TFMR_DATLEN, (bits - 1));
+ break;
+
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
+ /*
+ * I2S format, CODEC supplies BCLK and LRC clocks.
+ *
+ * The SSC transmit clock is obtained from the BCLK signal on
+ * on the TK line, and the SSC receive clock is
+ * generated from the transmit clock.
+ *
+ * For single channel data, one sample is transferred
+ * on the falling edge of the LRC clock.
+ * For two channel data, one sample is
+ * transferred on both edges of the LRC clock.
+ */
+ start_event = ((channels == 1)
+ ? SSC_START_FALLING_RF
+ : SSC_START_EDGE_RF);
+
+ rcmr = SSC_BF(RCMR_PERIOD, 0)
+ | SSC_BF(RCMR_STTDLY, START_DELAY)
+ | SSC_BF(RCMR_START, start_event)
+ | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
+ | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
+ | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK);
+
+ rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
+ | SSC_BF(RFMR_FSLEN, 0)
+ | SSC_BF(RFMR_DATNB, 0)
+ | SSC_BIT(RFMR_MSBF)
+ | SSC_BF(RFMR_LOOP, 0)
+ | SSC_BF(RFMR_DATLEN, (bits - 1));
+
+ tcmr = SSC_BF(TCMR_PERIOD, 0)
+ | SSC_BF(TCMR_STTDLY, START_DELAY)
+ | SSC_BF(TCMR_START, start_event)
+ | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
+ | SSC_BF(TCMR_CKO, SSC_CKO_NONE)
+ | SSC_BF(TCMR_CKS, SSC_CKS_PIN);
+
+ tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(TFMR_FSDEN, 0)
+ | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
+ | SSC_BF(TFMR_FSLEN, 0)
+ | SSC_BF(TFMR_DATNB, 0)
+ | SSC_BIT(TFMR_MSBF)
+ | SSC_BF(TFMR_DATDEF, 0)
+ | SSC_BF(TFMR_DATLEN, (bits - 1));
+ break;
+
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
+ /*
+ * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
+ *
+ * The SSC transmit and receive clocks are generated from the
+ * MCK divider, and the BCLK signal is output
+ * on the SSC TK line.
+ */
+ rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
+ | SSC_BF(RCMR_STTDLY, 1)
+ | SSC_BF(RCMR_START, SSC_START_RISING_RF)
+ | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
+ | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
+ | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
+
+ rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE)
+ | SSC_BF(RFMR_FSLEN, 0)
+ | SSC_BF(RFMR_DATNB, (channels - 1))
+ | SSC_BIT(RFMR_MSBF)
+ | SSC_BF(RFMR_LOOP, 0)
+ | SSC_BF(RFMR_DATLEN, (bits - 1));
+
+ tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
+ | SSC_BF(TCMR_STTDLY, 1)
+ | SSC_BF(TCMR_START, SSC_START_RISING_RF)
+ | SSC_BF(TCMR_CKI, SSC_CKI_RISING)
+ | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
+ | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
+
+ tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+ | SSC_BF(TFMR_FSDEN, 0)
+ | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE)
+ | SSC_BF(TFMR_FSLEN, 0)
+ | SSC_BF(TFMR_DATNB, (channels - 1))
+ | SSC_BIT(TFMR_MSBF)
+ | SSC_BF(TFMR_DATDEF, 0)
+ | SSC_BF(TFMR_DATLEN, (bits - 1));
+ break;
+
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
+ default:
+ printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
+ ssc_p->daifmt);
+ return -EINVAL;
+ break;
+ }
+ pr_debug("atmel_ssc_hw_params: "
+ "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
+ rcmr, rfmr, tcmr, tfmr);
+
+ if (!ssc_p->initialized) {
+
+ /* Enable PMC peripheral clock for this SSC */
+ pr_debug("atmel_ssc_dai: Starting clock\n");
+ clk_enable(ssc_p->ssc->clk);
+
+ /* Reset the SSC and its PDC registers */
+ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
+
+ ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
+
+ ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
+
+ ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0,
+ ssc_p->name, ssc_p);
+ if (ret < 0) {
+ printk(KERN_WARNING
+ "atmel_ssc_dai: request_irq failure\n");
+ pr_debug("Atmel_ssc_dai: Stoping clock\n");
+ clk_disable(ssc_p->ssc->clk);
+ return ret;
+ }
+
+ ssc_p->initialized = 1;
+ }
+
+ /* set SSC clock mode register */
+ ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
+
+ /* set receive clock mode and format */
+ ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
+ ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
+
+ /* set transmit clock mode and format */
+ ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
+ ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
+
+ pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n");
+ return 0;
+}
+
+
+static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ struct atmel_pcm_dma_params *dma_params;
+ int dir;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = 0;
+ else
+ dir = 1;
+
+ dma_params = ssc_p->dma_params[dir];
+
+ ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+
+ pr_debug("%s enabled SSC_SR=0x%08x\n",
+ dir ? "receive" : "transmit",
+ ssc_readl(ssc_p->ssc->regs, SR));
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
+{
+ struct atmel_ssc_info *ssc_p;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ ssc_p = &ssc_info[cpu_dai->id];
+
+ /* Save the status register before disabling transmit and receive */
+ ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
+ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
+
+ /* Save the current interrupt mask, then disable unmasked interrupts */
+ ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
+ ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
+
+ ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
+ ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
+ ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
+ ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
+ ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
+
+ return 0;
+}
+
+
+
+static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
+{
+ struct atmel_ssc_info *ssc_p;
+ u32 cr;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ ssc_p = &ssc_info[cpu_dai->id];
+
+ /* restore SSC register settings */
+ ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
+ ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
+ ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
+ ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
+ ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
+
+ /* re-enable interrupts */
+ ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
+
+ /* Re-enable recieve and transmit as appropriate */
+ cr = 0;
+ cr |=
+ (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
+ cr |=
+ (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
+ ssc_writel(ssc_p->ssc->regs, CR, cr);
+
+ return 0;
+}
+#else /* CONFIG_PM */
+# define atmel_ssc_suspend NULL
+# define atmel_ssc_resume NULL
+#endif /* CONFIG_PM */
+
+
+#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
+
+#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
+ { .name = "atmel-ssc0",
+ .id = 0,
+ .suspend = atmel_ssc_suspend,
+ .resume = atmel_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .ops = {
+ .startup = atmel_ssc_startup,
+ .shutdown = atmel_ssc_shutdown,
+ .prepare = atmel_ssc_prepare,
+ .hw_params = atmel_ssc_hw_params,
+ .set_fmt = atmel_ssc_set_dai_fmt,
+ .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
+ .private_data = &ssc_info[0],
+ },
+#if NUM_SSC_DEVICES == 3
+ { .name = "atmel-ssc1",
+ .id = 1,
+ .suspend = atmel_ssc_suspend,
+ .resume = atmel_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .ops = {
+ .startup = atmel_ssc_startup,
+ .shutdown = atmel_ssc_shutdown,
+ .prepare = atmel_ssc_prepare,
+ .hw_params = atmel_ssc_hw_params,
+ .set_fmt = atmel_ssc_set_dai_fmt,
+ .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
+ .private_data = &ssc_info[1],
+ },
+ { .name = "atmel-ssc2",
+ .id = 2,
+ .suspend = atmel_ssc_suspend,
+ .resume = atmel_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ATMEL_SSC_RATES,
+ .formats = ATMEL_SSC_FORMATS,},
+ .ops = {
+ .startup = atmel_ssc_startup,
+ .shutdown = atmel_ssc_shutdown,
+ .prepare = atmel_ssc_prepare,
+ .hw_params = atmel_ssc_hw_params,
+ .set_fmt = atmel_ssc_set_dai_fmt,
+ .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
+ .private_data = &ssc_info[2],
+ },
+#endif
+};
+EXPORT_SYMBOL_GPL(atmel_ssc_dai);
+
+static int __init atmel_ssc_modinit(void)
+{
+ return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
+}
+module_init(atmel_ssc_modinit);
+
+static void __exit atmel_ssc_modexit(void)
+{
+ snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
+}
+module_exit(atmel_ssc_modexit);
+
+/* Module information */
+MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
+MODULE_DESCRIPTION("ATMEL SSC ASoC Interface");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * atmel_ssc_dai.h - ALSA SSC interface for the Atmel SoC
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ * ATMEL CORP.
+ *
+ * Based on at91-ssc.c by
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Based on pxa2xx Platform drivers by
+ * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ATMEL_SSC_DAI_H
+#define _ATMEL_SSC_DAI_H
+
+#include <linux/types.h>
+#include <linux/atmel-ssc.h>
+
+#include "atmel-pcm.h"
+
+/* SSC system clock ids */
+#define ATMEL_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
+
+/* SSC divider ids */
+#define ATMEL_SSC_CMR_DIV 0 /* MCK divider for BCLK */
+#define ATMEL_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
+#define ATMEL_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
+/*
+ * SSC direction masks
+ */
+#define SSC_DIR_MASK_UNUSED 0
+#define SSC_DIR_MASK_PLAYBACK 1
+#define SSC_DIR_MASK_CAPTURE 2
+
+/*
+ * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
+ * are expected to be used with SSC_BF
+ */
+/* START bit field values */
+#define SSC_START_CONTINUOUS 0
+#define SSC_START_TX_RX 1
+#define SSC_START_LOW_RF 2
+#define SSC_START_HIGH_RF 3
+#define SSC_START_FALLING_RF 4
+#define SSC_START_RISING_RF 5
+#define SSC_START_LEVEL_RF 6
+#define SSC_START_EDGE_RF 7
+#define SSS_START_COMPARE_0 8
+
+/* CKI bit field values */
+#define SSC_CKI_FALLING 0
+#define SSC_CKI_RISING 1
+
+/* CKO bit field values */
+#define SSC_CKO_NONE 0
+#define SSC_CKO_CONTINUOUS 1
+#define SSC_CKO_TRANSFER 2
+
+/* CKS bit field values */
+#define SSC_CKS_DIV 0
+#define SSC_CKS_CLOCK 1
+#define SSC_CKS_PIN 2
+
+/* FSEDGE bit field values */
+#define SSC_FSEDGE_POSITIVE 0
+#define SSC_FSEDGE_NEGATIVE 1
+
+/* FSOS bit field values */
+#define SSC_FSOS_NONE 0
+#define SSC_FSOS_NEGATIVE 1
+#define SSC_FSOS_POSITIVE 2
+#define SSC_FSOS_LOW 3
+#define SSC_FSOS_HIGH 4
+#define SSC_FSOS_TOGGLE 5
+
+#define START_DELAY 1
+
+struct atmel_ssc_state {
+ u32 ssc_cmr;
+ u32 ssc_rcmr;
+ u32 ssc_rfmr;
+ u32 ssc_tcmr;
+ u32 ssc_tfmr;
+ u32 ssc_sr;
+ u32 ssc_imr;
+};
+
+
+struct atmel_ssc_info {
+ char *name;
+ struct ssc_device *ssc;
+ spinlock_t lock; /* lock for dir_mask */
+ unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
+ unsigned short initialized; /* true if SSC has been initialized */
+ unsigned short daifmt;
+ unsigned short cmr_div;
+ unsigned short tcmr_period;
+ unsigned short rcmr_period;
+ struct atmel_pcm_dma_params *dma_params[2];
+ struct atmel_ssc_state ssc_state;
+};
+extern struct snd_soc_dai atmel_ssc_dai[];
+
+#endif /* _AT91_SSC_DAI_H */
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <mach/portmux.h>
#include "../codecs/wm8510.h"
-#include "at32-pcm.h"
-#include "at32-ssc.h"
+#include "atmel-pcm.h"
+#include "atmel_ssc_dai.h"
/*-------------------------------------------------------------------------*\
-static struct snd_soc_machine snd_soc_machine_playpaq = {
+static struct snd_soc_card snd_soc_playpaq = {
.name = "LRS_PlayPaq_WM8510",
+ .platform = &at32_soc_platform,
.dai_link = &playpaq_wm8510_dai,
.num_links = 1,
};
static struct snd_soc_device playpaq_wm8510_snd_devdata = {
- .machine = &snd_soc_machine_playpaq,
- .platform = &at32_soc_platform,
+ .card = &snd_soc_playpaq,
.codec_dev = &soc_codec_dev_wm8510,
.codec_data = &playpaq_wm8510_setup,
};
--- /dev/null
+/*
+ * sam9g20_wm8731 -- SoC audio for AT91SAM9G20-based
+ * ATMEL AT91SAM9G20ek board.
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2008 Atmel
+ *
+ * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ *
+ * Based on ati_b1_wm8731.c by:
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Copyright 2006 Endrelia Technologies Inc.
+ * Based on corgi.c by:
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <linux/atmel-ssc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+
+#include "../codecs/wm8731.h"
+#include "atmel-pcm.h"
+#include "atmel_ssc_dai.h"
+
+
+static int at91sam9g20ek_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ int ret;
+
+ /* codec system clock is supplied by PCK0, set to 12MHz */
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
+ 12000000, SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+
+ dev_dbg(rtd->socdev->dev, "shutdown");
+}
+
+static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct atmel_ssc_info *ssc_p = cpu_dai->private_data;
+ struct ssc_device *ssc = ssc_p->ssc;
+ int ret;
+
+ unsigned int rate;
+ int cmr_div, period;
+
+ if (ssc == NULL) {
+ printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n");
+ return -EINVAL;
+ }
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * The SSC clock dividers depend on the sample rate. The CMR.DIV
+ * field divides the system master clock MCK to drive the SSC TK
+ * signal which provides the codec BCLK. The TCMR.PERIOD and
+ * RCMR.PERIOD fields further divide the BCLK signal to drive
+ * the SSC TF and RF signals which provide the codec DACLRC and
+ * ADCLRC clocks.
+ *
+ * The dividers were determined through trial and error, where a
+ * CMR.DIV value is chosen such that the resulting BCLK value is
+ * divisible, or almost divisible, by (2 * sample rate), and then
+ * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
+ */
+ rate = params_rate(params);
+
+ switch (rate) {
+ case 8000:
+ cmr_div = 55; /* BCLK = 133MHz/(2*55) = 1.209MHz */
+ period = 74; /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */
+ break;
+ case 11025:
+ cmr_div = 67; /* BCLK = 133MHz/(2*60) = 1.108MHz */
+ period = 45; /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */
+ break;
+ case 16000:
+ cmr_div = 63; /* BCLK = 133MHz/(2*63) = 1.055MHz */
+ period = 32; /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */
+ break;
+ case 22050:
+ cmr_div = 52; /* BCLK = 133MHz/(2*52) = 1.278MHz */
+ period = 28; /* LRC = BCLK/(2*(28+1)) = 22049Hz */
+ break;
+ case 32000:
+ cmr_div = 66; /* BCLK = 133MHz/(2*66) = 1.007MHz */
+ period = 15; /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */
+ break;
+ case 44100:
+ cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
+ period = 25; /* LRC = BCLK/(2*(25+1)) = 44098Hz */
+ break;
+ case 48000:
+ cmr_div = 33; /* BCLK = 133MHz/(2*33) = 2.015MHz */
+ period = 20; /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */
+ break;
+ case 88200:
+ cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
+ period = 12; /* LRC = BCLK/(2*(12+1)) = 88196Hz */
+ break;
+ case 96000:
+ cmr_div = 23; /* BCLK = 133MHz/(2*23) = 2.891MHz */
+ period = 14; /* LRC = BCLK/(2*(14+1)) = 96376Hz */
+ break;
+ default:
+ printk(KERN_WARNING "unsupported rate %d"
+ " on at91sam9g20ek board\n", rate);
+ return -EINVAL;
+ }
+
+ /* set the MCK divider for BCLK */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div);
+ if (ret < 0)
+ return ret;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* set the BCLK divider for DACLRC */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai,
+ ATMEL_SSC_TCMR_PERIOD, period);
+ } else {
+ /* set the BCLK divider for ADCLRC */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai,
+ ATMEL_SSC_RCMR_PERIOD, period);
+ }
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops at91sam9g20ek_ops = {
+ .startup = at91sam9g20ek_startup,
+ .hw_params = at91sam9g20ek_hw_params,
+ .shutdown = at91sam9g20ek_shutdown,
+};
+
+
+static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Int Mic", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+
+ /* speaker connected to LHPOUT */
+ {"Ext Spk", NULL, "LHPOUT"},
+
+ /* mic is connected to Mic Jack, with WM8731 Mic Bias */
+ {"MICIN", NULL, "Mic Bias"},
+ {"Mic Bias", NULL, "Int Mic"},
+};
+
+/*
+ * Logic for a wm8731 as connected on a at91sam9g20ek board.
+ */
+static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
+{
+ printk(KERN_DEBUG
+ "at91sam9g20ek_wm8731 "
+ ": at91sam9g20ek_wm8731_init() called\n");
+
+ /* Add specific widgets */
+ snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets,
+ ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
+ /* Set up specific audio path interconnects */
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+ /* not connected */
+ snd_soc_dapm_disable_pin(codec, "RLINEIN");
+ snd_soc_dapm_disable_pin(codec, "LLINEIN");
+
+ /* always connected */
+ snd_soc_dapm_enable_pin(codec, "Int Mic");
+ snd_soc_dapm_enable_pin(codec, "Ext Spk");
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link at91sam9g20ek_dai = {
+ .name = "WM8731",
+ .stream_name = "WM8731 PCM",
+ .cpu_dai = &atmel_ssc_dai[0],
+ .codec_dai = &wm8731_dai,
+ .init = at91sam9g20ek_wm8731_init,
+ .ops = &at91sam9g20ek_ops,
+};
+
+static struct snd_soc_card snd_soc_at91sam9g20ek = {
+ .name = "WM8731",
+ .platform = &atmel_soc_platform,
+ .dai_link = &at91sam9g20ek_dai,
+ .num_links = 1,
+};
+
+static struct wm8731_setup_data at91sam9g20ek_wm8731_setup = {
+ .i2c_bus = 0,
+ .i2c_address = 0x1b,
+};
+
+static struct snd_soc_device at91sam9g20ek_snd_devdata = {
+ .card = &snd_soc_at91sam9g20ek,
+ .codec_dev = &soc_codec_dev_wm8731,
+ .codec_data = &at91sam9g20ek_wm8731_setup,
+};
+
+static struct platform_device *at91sam9g20ek_snd_device;
+
+static int __init at91sam9g20ek_init(void)
+{
+ struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
+ struct ssc_device *ssc = NULL;
+ int ret;
+
+ /*
+ * Request SSC device
+ */
+ ssc = ssc_request(0);
+ if (IS_ERR(ssc)) {
+ ret = PTR_ERR(ssc);
+ ssc = NULL;
+ goto err_ssc;
+ }
+ ssc_p->ssc = ssc;
+
+ at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!at91sam9g20ek_snd_device) {
+ printk(KERN_DEBUG
+ "platform device allocation failed\n");
+ ret = -ENOMEM;
+ }
+
+ platform_set_drvdata(at91sam9g20ek_snd_device,
+ &at91sam9g20ek_snd_devdata);
+ at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev;
+
+ ret = platform_device_add(at91sam9g20ek_snd_device);
+ if (ret) {
+ printk(KERN_DEBUG
+ "platform device allocation failed\n");
+ platform_device_put(at91sam9g20ek_snd_device);
+ }
+
+ return ret;
+
+err_ssc:
+ return ret;
+}
+
+static void __exit at91sam9g20ek_exit(void)
+{
+ struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
+ struct ssc_device *ssc;
+
+ if (ssc_p != NULL) {
+ ssc = ssc_p->ssc;
+ if (ssc != NULL)
+ ssc_free(ssc);
+ ssc_p->ssc = NULL;
+ }
+
+ platform_device_unregister(at91sam9g20ek_snd_device);
+ at91sam9g20ek_snd_device = NULL;
+}
+
+module_init(at91sam9g20ek_init);
+module_exit(at91sam9g20ek_exit);
+
+/* Module information */
+MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
+MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
+MODULE_LICENSE("GPL");
{
au1xpsc_audio_pcmdma[PCM_TX] = NULL;
au1xpsc_audio_pcmdma[PCM_RX] = NULL;
- return 0;
+ return snd_soc_register_platform(&au1xpsc_soc_platform);
}
static void __exit au1xpsc_audio_dbdma_exit(void)
{
+ snd_soc_unregister_platform(&au1xpsc_soc_platform);
}
module_init(au1xpsc_audio_dbdma_init);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
/* FIXME */
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
}
static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
- int cmd)
+ int cmd, struct snd_soc_dai *dai)
{
/* FIXME */
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
au1xpsc_ac97_workdata = NULL;
}
-static int au1xpsc_ac97_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai)
{
/* save interesting registers and disable PSC */
au1xpsc_ac97_workdata->pm[0] =
return 0;
}
-static int au1xpsc_ac97_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int au1xpsc_ac97_resume(struct snd_soc_dai *dai)
{
/* restore PSC clock config */
au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE,
struct snd_soc_dai au1xpsc_ac97_dai = {
.name = "au1xpsc_ac97",
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.probe = au1xpsc_ac97_probe,
.remove = au1xpsc_ac97_remove,
.suspend = au1xpsc_ac97_suspend,
static int __init au1xpsc_ac97_init(void)
{
au1xpsc_ac97_workdata = NULL;
- return 0;
+ return snd_soc_register_dai(&au1xpsc_ac97_dai);
}
static void __exit au1xpsc_ac97_exit(void)
{
+ snd_soc_unregister_dai(&au1xpsc_ac97_dai);
}
module_init(au1xpsc_ac97_init);
}
static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
return 0;
}
-static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
int ret, stype = SUBSTREAM_TYPE(substream);
au1xpsc_i2s_workdata = NULL;
}
-static int au1xpsc_i2s_suspend(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
+static int au1xpsc_i2s_suspend(struct snd_soc_dai *cpu_dai)
{
/* save interesting register and disable PSC */
au1xpsc_i2s_workdata->pm[0] =
return 0;
}
-static int au1xpsc_i2s_resume(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
+static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai)
{
/* select I2S mode and PSC clock */
au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
struct snd_soc_dai au1xpsc_i2s_dai = {
.name = "au1xpsc_i2s",
- .type = SND_SOC_DAI_I2S,
.probe = au1xpsc_i2s_probe,
.remove = au1xpsc_i2s_remove,
.suspend = au1xpsc_i2s_suspend,
.ops = {
.trigger = au1xpsc_i2s_trigger,
.hw_params = au1xpsc_i2s_hw_params,
- },
- .dai_ops = {
.set_fmt = au1xpsc_i2s_set_fmt,
},
};
static int __init au1xpsc_i2s_init(void)
{
au1xpsc_i2s_workdata = NULL;
- return 0;
+ return snd_soc_register_dai(&au1xpsc_i2s_dai);
}
static void __exit au1xpsc_i2s_exit(void)
{
+ snd_soc_unregister_dai(&au1xpsc_i2s_dai);
}
module_init(au1xpsc_i2s_init);
.ops = NULL,
};
-static struct snd_soc_machine au1xpsc_sample_ac97_machine = {
+static struct snd_soc_card au1xpsc_sample_ac97_machine = {
.name = "Au1xxx PSC AC97 Audio",
.dai_link = &au1xpsc_sample_ac97_dai,
.num_links = 1,
};
static struct snd_soc_device au1xpsc_sample_ac97_devdata = {
- .machine = &au1xpsc_sample_ac97_machine,
+ .card = &au1xpsc_sample_ac97_machine,
.platform = &au1xpsc_soc_platform, /* see dbdma2.c */
.codec_dev = &soc_codec_dev_ac97,
};
config SND_BF5XX_I2S
tristate "SoC I2S Audio for the ADI BF5xx chip"
- depends on BLACKFIN && SND_SOC
+ depends on BLACKFIN
help
Say Y or M if you want to add support for codecs attached to
the Blackfin SPORT (synchronous serial ports) interface in I2S
select SND_BF5XX_SOC_I2S
select SND_SOC_SSM2602
select I2C
- select I2C_BLACKFIN_TWI
help
Say Y if you want to add support for SoC audio on BF527-EZKIT.
config SND_BF5XX_AC97
tristate "SoC AC97 Audio for the ADI BF5xx chip"
- depends on BLACKFIN && SND_SOC
+ depends on BLACKFIN
help
Say Y or M if you want to add support for codecs attached to
the Blackfin SPORT (synchronous serial ports) interface in slot 16
properly with this driver. This driver is known to work with the
Analog Devices line of AC97 codecs.
-config SND_MMAP_SUPPORT
+config SND_BF5XX_MMAP_SUPPORT
bool "Enable MMAP Support"
depends on SND_BF5XX_AC97
default y
Say y if you want AC97 driver to support mmap mode.
We introduce an intermediate buffer to simulate mmap.
+config SND_BF5XX_MULTICHAN_SUPPORT
+ bool "Enable Multichannel Support"
+ depends on SND_BF5XX_AC97
+ default n
+ help
+ Say y if you want AC97 driver to support up to 5.1 channel audio.
+ this mode will consume much more memory for DMA.
+
config SND_BF5XX_SOC_SPORT
tristate
-
+
config SND_BF5XX_SOC_I2S
tristate
select SND_BF5XX_SOC_SPORT
int "Set a SPORT for Sound chip"
depends on (SND_BF5XX_I2S || SND_BF5XX_AC97)
range 0 3 if BF54x
- range 0 1 if (BF53x || BF561)
+ range 0 1 if !BF54x
default 0
help
Set the correct SPORT for sound chip.
depends on SND_BF5XX_AC97
default y if BFIN548_EZKIT
default n if !BFIN548_EZKIT
-
+
config SND_BF5XX_RESET_GPIO_NUM
int "Set a GPIO for cold reset"
depends on SND_BF5XX_HAVE_COLD_RESET
range 0 159
default 19 if BFIN548_EZKIT
default 5 if BFIN537_STAMP
+ default 0
help
Set the correct GPIO for RESET the sound chip.
#include "bf5xx-ac97.h"
#include "bf5xx-sport.h"
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+static unsigned int ac97_chan_mask[] = {
+ SP_FL, /* Mono */
+ SP_STEREO, /* Stereo */
+ SP_2DOT1, /* 2.1*/
+ SP_QUAD,/*Quadraquic*/
+ SP_FL | SP_FR | SP_FC | SP_SL | SP_SR,/*5 channels */
+ SP_5DOT1, /* 5.1 */
+};
+
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
snd_pcm_uframes_t count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct sport_device *sport = runtime->private_data;
+ unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- bf5xx_pcm_to_ac97(
- (struct ac97_frame *)sport->tx_dma_buf + sport->tx_pos,
- (__u32 *)runtime->dma_area + sport->tx_pos, count);
+ bf5xx_pcm_to_ac97((struct ac97_frame *)sport->tx_dma_buf +
+ sport->tx_pos, (__u16 *)runtime->dma_area + sport->tx_pos *
+ runtime->channels, count, chan_mask);
sport->tx_pos += runtime->period_size;
if (sport->tx_pos >= runtime->buffer_size)
sport->tx_pos %= runtime->buffer_size;
sport->tx_delay_pos = sport->tx_pos;
} else {
- bf5xx_ac97_to_pcm(
- (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
- (__u32 *)runtime->dma_area + sport->rx_pos, count);
+ bf5xx_ac97_to_pcm((struct ac97_frame *)sport->rx_dma_buf +
+ sport->rx_pos, (__u16 *)runtime->dma_area + sport->rx_pos *
+ runtime->channels, count);
sport->rx_pos += runtime->period_size;
if (sport->rx_pos >= runtime->buffer_size)
sport->rx_pos %= runtime->buffer_size;
static void bf5xx_dma_irq(void *data)
{
struct snd_pcm_substream *pcm = data;
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
struct snd_pcm_runtime *runtime = pcm->runtime;
struct sport_device *sport = runtime->private_data;
bf5xx_mmap_copy(pcm, runtime->period_size);
* The total rx/tx buffer is for ac97 frame to hold all pcm data
* is 0x20000 * sizeof(struct ac97_frame) / 4.
*/
-#ifdef CONFIG_SND_MMAP_SUPPORT
static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_BLOCK_TRANSFER,
-#else
-static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER,
#endif
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
+
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.period_bytes_min = 32,
.period_bytes_max = 0x10000,
static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
{
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct sport_device *sport = runtime->private_data;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- memset(runtime->dma_area, 0, runtime->buffer_size);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ sport->once = 0;
+ if (runtime->dma_area)
+ memset(runtime->dma_area, 0, runtime->buffer_size);
+ memset(sport->tx_dma_buf, 0, runtime->buffer_size *
+ sizeof(struct ac97_frame));
+ } else
+ memset(sport->rx_dma_buf, 0, runtime->buffer_size *
+ sizeof(struct ac97_frame));
+#endif
snd_pcm_lib_free_pages(substream);
return 0;
}
/* An intermediate buffer is introduced for implementing mmap for
* SPORT working in TMD mode(include AC97).
*/
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
bf5xx_mmap_copy(substream, runtime->period_size);
- snd_pcm_period_elapsed(substream);
sport->tx_delay_pos = 0;
+#endif
sport_tx_start(sport);
- }
- else
+ } else
sport_rx_start(sport);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
sport->tx_pos = 0;
#endif
sport_tx_stop(sport);
} else {
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
sport->rx_pos = 0;
#endif
sport_rx_stop(sport);
struct sport_device *sport = runtime->private_data;
unsigned int curr;
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
curr = sport->tx_delay_pos;
else
return ret;
}
-static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct sport_device *sport = runtime->private_data;
-
- pr_debug("%s enter\n", __func__);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- sport->once = 0;
- memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
- } else
- memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
-
- return 0;
-}
-
-#ifdef CONFIG_SND_MMAP_SUPPORT
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
void __user *buf, snd_pcm_uframes_t count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
-
+ unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
pr_debug("%s copy pos:0x%lx count:0x%lx\n",
substream->stream ? "Capture" : "Playback", pos, count);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- bf5xx_pcm_to_ac97(
- (struct ac97_frame *)runtime->dma_area + pos,
- buf, count);
+ bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos,
+ (__u16 *)buf, count, chan_mask);
else
- bf5xx_ac97_to_pcm(
- (struct ac97_frame *)runtime->dma_area + pos,
- buf, count);
+ bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos,
+ (__u16 *)buf, count);
return 0;
}
#endif
struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
.open = bf5xx_pcm_open,
- .close = bf5xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = bf5xx_pcm_hw_params,
.hw_free = bf5xx_pcm_hw_free,
.prepare = bf5xx_pcm_prepare,
.trigger = bf5xx_pcm_trigger,
.pointer = bf5xx_pcm_pointer,
-#ifdef CONFIG_SND_MMAP_SUPPORT
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
.mmap = bf5xx_pcm_mmap,
#else
.copy = bf5xx_pcm_copy,
* Need to allocate local buffer when enable
* MMAP for SPORT working in TMD mode (include AC97).
*/
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (!sport_handle->tx_dma_buf) {
sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
int stream;
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
size_t size = bf5xx_pcm_hardware.buffer_bytes_max *
sizeof(struct ac97_frame) / 4;
#endif
continue;
dma_free_coherent(NULL, buf->bytes, buf->area, 0);
buf->area = NULL;
-#if defined(CONFIG_SND_MMAP_SUPPORT)
+#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (sport_handle->tx_dma_buf)
dma_free_coherent(NULL, size, \
};
EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform);
+static int __init bfin_ac97_init(void)
+{
+ return snd_soc_register_platform(&bf5xx_ac97_soc_platform);
+}
+module_init(bfin_ac97_init);
+
+static void __exit bfin_ac97_exit(void)
+{
+ snd_soc_unregister_platform(&bf5xx_ac97_soc_platform);
+}
+module_exit(bfin_ac97_exit);
+
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
MODULE_LICENSE("GPL");
static int *cmd_count;
static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
-#if defined(CONFIG_BF54x)
+static u16 sport_req[][7] = {
+ PIN_REQ_SPORT_0,
+#ifdef PIN_REQ_SPORT_1
+ PIN_REQ_SPORT_1,
+#endif
+#ifdef PIN_REQ_SPORT_2
+ PIN_REQ_SPORT_2,
+#endif
+#ifdef PIN_REQ_SPORT_3
+ PIN_REQ_SPORT_3,
+#endif
+ };
+
static struct sport_param sport_params[4] = {
{
.dma_rx_chan = CH_SPORT0_RX,
.dma_tx_chan = CH_SPORT0_TX,
- .err_irq = IRQ_SPORT0_ERR,
+ .err_irq = IRQ_SPORT0_ERROR,
.regs = (struct sport_register *)SPORT0_TCR1,
},
+#ifdef PIN_REQ_SPORT_1
{
.dma_rx_chan = CH_SPORT1_RX,
.dma_tx_chan = CH_SPORT1_TX,
- .err_irq = IRQ_SPORT1_ERR,
+ .err_irq = IRQ_SPORT1_ERROR,
.regs = (struct sport_register *)SPORT1_TCR1,
},
+#endif
+#ifdef PIN_REQ_SPORT_2
{
.dma_rx_chan = CH_SPORT2_RX,
.dma_tx_chan = CH_SPORT2_TX,
- .err_irq = IRQ_SPORT2_ERR,
+ .err_irq = IRQ_SPORT2_ERROR,
.regs = (struct sport_register *)SPORT2_TCR1,
},
+#endif
+#ifdef PIN_REQ_SPORT_3
{
.dma_rx_chan = CH_SPORT3_RX,
.dma_tx_chan = CH_SPORT3_TX,
- .err_irq = IRQ_SPORT3_ERR,
+ .err_irq = IRQ_SPORT3_ERROR,
.regs = (struct sport_register *)SPORT3_TCR1,
}
-};
-#else
-static struct sport_param sport_params[2] = {
- {
- .dma_rx_chan = CH_SPORT0_RX,
- .dma_tx_chan = CH_SPORT0_TX,
- .err_irq = IRQ_SPORT0_ERROR,
- .regs = (struct sport_register *)SPORT0_TCR1,
- },
- {
- .dma_rx_chan = CH_SPORT1_RX,
- .dma_tx_chan = CH_SPORT1_TX,
- .err_irq = IRQ_SPORT1_ERROR,
- .regs = (struct sport_register *)SPORT1_TCR1,
- }
-};
#endif
+};
-void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \
- size_t count)
+void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src,
+ size_t count, unsigned int chan_mask)
{
while (count--) {
- dst->ac97_tag = TAG_VALID | TAG_PCM;
- (dst++)->ac97_pcm = *src++;
+ dst->ac97_tag = TAG_VALID;
+ if (chan_mask & SP_FL) {
+ dst->ac97_pcm_r = *src++;
+ dst->ac97_tag |= TAG_PCM_RIGHT;
+ }
+ if (chan_mask & SP_FR) {
+ dst->ac97_pcm_l = *src++;
+ dst->ac97_tag |= TAG_PCM_LEFT;
+
+ }
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+ if (chan_mask & SP_SR) {
+ dst->ac97_sl = *src++;
+ dst->ac97_tag |= TAG_PCM_SL;
+ }
+ if (chan_mask & SP_SL) {
+ dst->ac97_sr = *src++;
+ dst->ac97_tag |= TAG_PCM_SR;
+ }
+ if (chan_mask & SP_LFE) {
+ dst->ac97_lfe = *src++;
+ dst->ac97_tag |= TAG_PCM_LFE;
+ }
+ if (chan_mask & SP_FC) {
+ dst->ac97_center = *src++;
+ dst->ac97_tag |= TAG_PCM_CENTER;
+ }
+#endif
+ dst++;
}
}
EXPORT_SYMBOL(bf5xx_pcm_to_ac97);
-void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \
+void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst,
size_t count)
{
- while (count--)
- *(dst++) = (src++)->ac97_pcm;
+ while (count--) {
+ *(dst++) = src->ac97_pcm_l;
+ *(dst++) = src->ac97_pcm_r;
+ src++;
+ }
}
EXPORT_SYMBOL(bf5xx_ac97_to_pcm);
static unsigned int sport_tx_curr_frag(struct sport_device *sport)
{
- return sport->tx_curr_frag = sport_curr_offset_tx(sport) / \
+ return sport->tx_curr_frag = sport_curr_offset_tx(sport) /
sport->tx_fragsize;
}
sport_incfrag(sport, &nextfrag, 1);
- nextwrite = (struct ac97_frame *)(sport->tx_buf + \
+ nextwrite = (struct ac97_frame *)(sport->tx_buf +
nextfrag * sport->tx_fragsize);
pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n",
sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
#ifdef CONFIG_PM
-static int bf5xx_ac97_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
{
struct sport_device *sport =
(struct sport_device *)dai->private_data;
return 0;
}
-static int bf5xx_ac97_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
{
int ret;
struct sport_device *sport =
static int bf5xx_ac97_probe(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
- int ret;
-#if defined(CONFIG_BF54x)
- u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1,
- PIN_REQ_SPORT_2, PIN_REQ_SPORT_3};
-#else
- u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1};
-#endif
+ int ret = 0;
cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
if (cmd_count == NULL)
return -ENOMEM;
if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
pr_err("Requesting Peripherals failed\n");
- return -EFAULT;
+ ret = -EFAULT;
+ goto peripheral_err;
}
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) {
pr_err("Failed to request GPIO_%d for reset\n",
CONFIG_SND_BF5XX_RESET_GPIO_NUM);
- peripheral_free_list(&sport_req[sport_num][0]);
- return -1;
+ ret = -1;
+ goto gpio_err;
}
gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1);
#endif
sport_handle = sport_init(&sport_params[sport_num], 2, \
sizeof(struct ac97_frame), NULL);
if (!sport_handle) {
- peripheral_free_list(&sport_req[sport_num][0]);
-#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
- gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
-#endif
- return -ENODEV;
+ ret = -ENODEV;
+ goto sport_err;
}
/*SPORT works in TDM mode to simulate AC97 transfers*/
ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
if (ret) {
pr_err("SPORT is busy!\n");
- kfree(sport_handle);
- peripheral_free_list(&sport_req[sport_num][0]);
-#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
- gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
-#endif
- return -EBUSY;
+ ret = -EBUSY;
+ goto sport_config_err;
}
ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1));
if (ret) {
pr_err("SPORT is busy!\n");
- kfree(sport_handle);
- peripheral_free_list(&sport_req[sport_num][0]);
-#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
- gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
-#endif
- return -EBUSY;
+ ret = -EBUSY;
+ goto sport_config_err;
}
ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1));
if (ret) {
pr_err("SPORT is busy!\n");
- kfree(sport_handle);
- peripheral_free_list(&sport_req[sport_num][0]);
-#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
- gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
-#endif
- return -EBUSY;
+ ret = -EBUSY;
+ goto sport_config_err;
}
+
return 0;
+
+sport_config_err:
+ kfree(sport_handle);
+sport_err:
+#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
+ gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
+#endif
+gpio_err:
+ peripheral_free_list(&sport_req[sport_num][0]);
+peripheral_err:
+ free_page((unsigned long)cmd_count);
+ cmd_count = NULL;
+
+ return ret;
}
static void bf5xx_ac97_remove(struct platform_device *pdev,
{
free_page((unsigned long)cmd_count);
cmd_count = NULL;
+ peripheral_free_list(&sport_req[sport_num][0]);
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
#endif
struct snd_soc_dai bfin_ac97_dai = {
.name = "bf5xx-ac97",
.id = 0,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.probe = bf5xx_ac97_probe,
.remove = bf5xx_ac97_remove,
.suspend = bf5xx_ac97_suspend,
.playback = {
.stream_name = "AC97 Playback",
.channels_min = 2,
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+ .channels_max = 6,
+#else
.channels_max = 2,
+#endif
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
.capture = {
};
EXPORT_SYMBOL_GPL(bfin_ac97_dai);
+static int __init bfin_ac97_init(void)
+{
+ return snd_soc_register_dai(&bfin_ac97_dai);
+}
+module_init(bfin_ac97_init);
+
+static void __exit bfin_ac97_exit(void)
+{
+ snd_soc_unregister_dai(&bfin_ac97_dai);
+}
+module_exit(bfin_ac97_exit);
+
MODULE_AUTHOR("Roy Huang");
MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
MODULE_LICENSE("GPL");
u16 ac97_tag; /* slot 0 */
u16 ac97_addr; /* slot 1 */
u16 ac97_data; /* slot 2 */
- u32 ac97_pcm; /* slot 3 and 4: left and right pcm data */
+ u16 ac97_pcm_l; /*slot 3:front left*/
+ u16 ac97_pcm_r; /*slot 4:front left*/
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+ u16 ac97_mdm_l1;
+ u16 ac97_center; /*slot 6:center*/
+ u16 ac97_sl; /*slot 7:surround left*/
+ u16 ac97_sr; /*slot 8:surround right*/
+ u16 ac97_lfe; /*slot 9:lfe*/
+#endif
} __attribute__ ((packed));
+/* Speaker location */
+#define SP_FL 0x0001
+#define SP_FR 0x0010
+#define SP_FC 0x0002
+#define SP_LFE 0x0020
+#define SP_SL 0x0004
+#define SP_SR 0x0040
+
+#define SP_STEREO (SP_FL | SP_FR)
+#define SP_2DOT1 (SP_FL | SP_FR | SP_LFE)
+#define SP_QUAD (SP_FL | SP_FR | SP_SL | SP_SR)
+#define SP_5DOT1 (SP_FL | SP_FR | SP_FC | SP_LFE | SP_SL | SP_SR)
+
#define TAG_VALID 0x8000
#define TAG_CMD 0x6000
#define TAG_PCM_LEFT 0x1000
#define TAG_PCM_RIGHT 0x0800
-#define TAG_PCM (TAG_PCM_LEFT | TAG_PCM_RIGHT)
+#define TAG_PCM_MDM_L1 0x0400
+#define TAG_PCM_CENTER 0x0200
+#define TAG_PCM_SL 0x0100
+#define TAG_PCM_SR 0x0080
+#define TAG_PCM_LFE 0x0040
extern struct snd_soc_dai bfin_ac97_dai;
-void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \
- size_t count);
+void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \
+ size_t count, unsigned int chan_mask);
-void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \
+void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, \
size_t count);
#endif
#include "bf5xx-ac97-pcm.h"
#include "bf5xx-ac97.h"
-static struct snd_soc_machine bf5xx_board;
+static struct snd_soc_card bf5xx_board;
static int bf5xx_board_startup(struct snd_pcm_substream *substream)
{
.ops = &bf5xx_board_ops,
};
-static struct snd_soc_machine bf5xx_board = {
+static struct snd_soc_card bf5xx_board = {
.name = "bf5xx-board",
+ .platform = &bf5xx_ac97_soc_platform,
.dai_link = &bf5xx_board_dai,
.num_links = 1,
};
static struct snd_soc_device bf5xx_board_snd_devdata = {
- .machine = &bf5xx_board,
- .platform = &bf5xx_ac97_soc_platform,
+ .card = &bf5xx_board,
.codec_dev = &soc_codec_dev_ad1980,
};
#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
-static struct snd_soc_machine bf5xx_ad73311;
+static struct snd_soc_card bf5xx_ad73311;
static int snd_ad73311_startup(void)
{
params_format(params));
/* set cpu DAI configuration */
- ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
.ops = &bf5xx_ad73311_ops,
};
-static struct snd_soc_machine bf5xx_ad73311 = {
+static struct snd_soc_card bf5xx_ad73311 = {
.name = "bf5xx_ad73311",
+ .platform = &bf5xx_i2s_soc_platform,
.probe = bf5xx_probe,
.dai_link = &bf5xx_ad73311_dai,
.num_links = 1,
};
static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
- .machine = &bf5xx_ad73311,
- .platform = &bf5xx_i2s_soc_platform,
+ .card = &bf5xx_ad73311,
.codec_dev = &soc_codec_dev_ad73311,
};
};
EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform);
+static int __init bfin_i2s_init(void)
+{
+ return snd_soc_register_platform(&bf5xx_i2s_soc_platform);
+}
+module_init(bfin_i2s_init);
+
+static void __exit bfin_i2s_exit(void)
+{
+ snd_soc_unregister_platform(&bf5xx_i2s_soc_platform);
+}
+module_exit(bfin_i2s_exit);
+
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
MODULE_LICENSE("GPL");
return ret;
}
-static int bf5xx_i2s_startup(struct snd_pcm_substream *substream)
+static int bf5xx_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
pr_debug("%s enter\n", __func__);
}
static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
int ret = 0;
return 0;
}
-static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
+static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
pr_debug("%s enter\n", __func__);
bf5xx_i2s.counter--;
return 0;
}
-static void bf5xx_i2s_remove(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static void bf5xx_i2s_remove(struct snd_soc_dai *dai)
{
pr_debug("%s enter\n", __func__);
peripheral_free_list(&sport_req[sport_num][0]);
}
#ifdef CONFIG_PM
-static int bf5xx_i2s_suspend(struct platform_device *dev,
- struct snd_soc_dai *dai)
+static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
{
struct sport_device *sport =
(struct sport_device *)dai->private_data;
struct snd_soc_dai bf5xx_i2s_dai = {
.name = "bf5xx-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.probe = bf5xx_i2s_probe,
.remove = bf5xx_i2s_remove,
.suspend = bf5xx_i2s_suspend,
.ops = {
.startup = bf5xx_i2s_startup,
.shutdown = bf5xx_i2s_shutdown,
- .hw_params = bf5xx_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = bf5xx_i2s_hw_params,
.set_fmt = bf5xx_i2s_set_dai_fmt,
},
};
EXPORT_SYMBOL_GPL(bf5xx_i2s_dai);
+static int __init bfin_i2s_init(void)
+{
+ return snd_soc_register_dai(&bf5xx_i2s_dai);
+}
+module_init(bfin_i2s_init);
+
+static void __exit bfin_i2s_exit(void)
+{
+ snd_soc_unregister_dai(&bf5xx_i2s_dai);
+}
+module_exit(bfin_i2s_exit);
+
/* Module information */
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("I2S driver for ADI Blackfin");
void *err_data;
unsigned char *tx_dma_buf;
unsigned char *rx_dma_buf;
-#ifdef CONFIG_SND_MMAP_SUPPORT
+#ifdef CONFIG_SND_BF5XX_MMAP_SUPPORT
dma_addr_t tx_dma_phy;
dma_addr_t rx_dma_phy;
int tx_pos;/*pcm sample count*/
#include "bf5xx-i2s-pcm.h"
#include "bf5xx-i2s.h"
-static struct snd_soc_machine bf5xx_ssm2602;
+static struct snd_soc_card bf5xx_ssm2602;
static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream)
{
*/
/* set codec DAI configuration */
- ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
/* set cpu DAI configuration */
- ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
- ret = codec_dai->dai_ops.set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
+ ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
.i2c_address = 0x1b,
};
-static struct snd_soc_machine bf5xx_ssm2602 = {
+static struct snd_soc_card bf5xx_ssm2602 = {
.name = "bf5xx_ssm2602",
+ .platform = &bf5xx_i2s_soc_platform,
.dai_link = &bf5xx_ssm2602_dai,
.num_links = 1,
};
static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
- .machine = &bf5xx_ssm2602,
- .platform = &bf5xx_i2s_soc_platform,
+ .card = &bf5xx_ssm2602,
.codec_dev = &soc_codec_dev_ssm2602,
.codec_data = &bf5xx_ssm2602_setup,
};
config SND_SOC_ALL_CODECS
tristate "Build all ASoC CODEC drivers"
- depends on I2C
- select SPI
- select SPI_MASTER
- select SND_SOC_AD73311
- select SND_SOC_AK4535
- select SND_SOC_CS4270
- select SND_SOC_SSM2602
- select SND_SOC_TLV320AIC23
- select SND_SOC_TLV320AIC26
- select SND_SOC_TLV320AIC3X
- select SND_SOC_UDA1380
- select SND_SOC_WM8510
- select SND_SOC_WM8580
- select SND_SOC_WM8731
- select SND_SOC_WM8750
- select SND_SOC_WM8753
- select SND_SOC_WM8900
- select SND_SOC_WM8903
- select SND_SOC_WM8971
- select SND_SOC_WM8990
+ select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
+ select SND_SOC_AD1980 if SND_SOC_AC97_BUS
+ select SND_SOC_AD73311 if I2C
+ select SND_SOC_AK4535 if I2C
+ select SND_SOC_CS4270 if I2C
+ select SND_SOC_PCM3008
+ select SND_SOC_SSM2602 if I2C
+ select SND_SOC_TLV320AIC23 if I2C
+ select SND_SOC_TLV320AIC26 if SPI_MASTER
+ select SND_SOC_TLV320AIC3X if I2C
+ select SND_SOC_TWL4030 if TWL4030_CORE
+ select SND_SOC_UDA134X
+ select SND_SOC_UDA1380 if I2C
+ select SND_SOC_WM8350 if MFD_WM8350
+ select SND_SOC_WM8510 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8580 if I2C
+ select SND_SOC_WM8728 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8731 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8750 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8753 if (I2C || SPI_MASTER)
+ select SND_SOC_WM8900 if I2C
+ select SND_SOC_WM8903 if I2C
+ select SND_SOC_WM8971 if I2C
+ select SND_SOC_WM8990 if I2C
+ select SND_SOC_WM9712 if SND_SOC_AC97_BUS
+ select SND_SOC_WM9713 if SND_SOC_AC97_BUS
help
Normally ASoC codec drivers are only built if a machine driver which
uses them is also built since they are only usable with a machine
driver. Selecting this option will allow these drivers to be built
without an explicit machine driver for test and development purposes.
+ Support for the bus types used to access the codecs to be built must
+ be selected separately.
+
If unsure select "N".
bool
depends on SND_SOC_CS4270
+config SND_SOC_L3
+ tristate
+
+config SND_SOC_PCM3008
+ tristate
+
config SND_SOC_SSM2602
tristate
tristate
depends on I2C
+config SND_SOC_TWL4030
+ tristate
+ depends on TWL4030_CORE
+
+config SND_SOC_UDA134X
+ tristate
+ select SND_SOC_L3
+
config SND_SOC_UDA1380
tristate
+config SND_SOC_WM8350
+ tristate
+
config SND_SOC_WM8510
tristate
config SND_SOC_WM8580
tristate
+config SND_SOC_WM8728
+ tristate
+
config SND_SOC_WM8731
tristate
snd-soc-ad73311-objs := ad73311.o
snd-soc-ak4535-objs := ak4535.o
snd-soc-cs4270-objs := cs4270.o
+snd-soc-l3-objs := l3.o
+snd-soc-pcm3008-objs := pcm3008.o
snd-soc-ssm2602-objs := ssm2602.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
+snd-soc-twl4030-objs := twl4030.o
+snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
+snd-soc-wm8350-objs := wm8350.o
snd-soc-wm8510-objs := wm8510.o
snd-soc-wm8580-objs := wm8580.o
+snd-soc-wm8728-objs := wm8728.o
snd-soc-wm8731-objs := wm8731.o
snd-soc-wm8750-objs := wm8750.o
snd-soc-wm8753-objs := wm8753.o
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
+obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
+obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
+obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
+obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
+obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
+obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
#define AC97_VERSION "0.6"
-static int ac97_prepare(struct snd_pcm_substream *substream)
+static int ac97_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai ac97_dai = {
.name = "AC97 HiFi",
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.playback = {
.stream_name = "AC97 Playback",
.channels_min = 1,
if (ret < 0)
goto bus_err;
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0)
goto bus_err;
return 0;
SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
+SOC_DOUBLE("Center/LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 0, 31, 1),
+SOC_DOUBLE("Center/LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 7, 1, 1),
+
SOC_ENUM("Capture Source", ad1980_cap_src),
SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
struct snd_soc_dai ad1980_dai = {
.name = "AC97",
+ .ac97_control = 1,
.playback = {
.stream_name = "Playback",
.channels_min = 2,
- .channels_max = 2,
+ .channels_max = 6,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
.capture = {
struct snd_soc_codec *codec;
int ret = 0;
u16 vendor_id2;
+ u16 ext_status;
printk(KERN_INFO "AD1980 SoC Audio Codec\n");
ret = ad1980_reset(codec, 0);
if (ret < 0) {
- printk(KERN_ERR "AC97 link error\n");
+ printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n");
goto reset_err;
}
"supported\n");
}
- ac97_write(codec, AC97_MASTER, 0x0000); /* unmute line out volume */
- ac97_write(codec, AC97_PCM, 0x0000); /* unmute PCM out volume */
- ac97_write(codec, AC97_REC_GAIN, 0x0000);/* unmute record volume */
+ /* unmute captures and playbacks volume */
+ ac97_write(codec, AC97_MASTER, 0x0000);
+ ac97_write(codec, AC97_PCM, 0x0000);
+ ac97_write(codec, AC97_REC_GAIN, 0x0000);
+ ac97_write(codec, AC97_CENTER_LFE_MASTER, 0x0000);
+ ac97_write(codec, AC97_SURROUND_MASTER, 0x0000);
+
+ /*power on LFE/CENTER/Surround DACs*/
+ ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
+ ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
ad1980_add_controls(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "ad1980: failed to register card\n");
goto reset_err;
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
- *
- * Revision history
- * 25th Sep 2008 Initial version.
*/
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <sound/core.h>
goto pcm_err;
}
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "ad73311: failed to register card\n");
goto register_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
+static int __init ad73311_init(void)
+{
+ return snd_soc_register_dai(&ad73311_dai);
+}
+module_init(ad73311_init);
+
+static void __exit ad73311_exit(void)
+{
+ snd_soc_unregister_dai(&ad73311_dai);
+}
+module_exit(ad73311_exit);
+
MODULE_DESCRIPTION("ASoC ad73311 driver");
MODULE_AUTHOR("Cliff Cai ");
MODULE_LICENSE("GPL");
}
static int ak4535_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.hw_params = ak4535_hw_params,
- },
- .dai_ops = {
.set_fmt = ak4535_set_dai_fmt,
.digital_mute = ak4535_mute,
.set_sysclk = ak4535_set_dai_sysclk,
ak4535_add_controls(codec);
ak4535_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "ak4535: failed to register card\n");
goto card_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
+static int __init ak4535_modinit(void)
+{
+ return snd_soc_register_dai(&ak4535_dai);
+}
+module_init(ak4535_modinit);
+
+static void __exit ak4535_exit(void)
+{
+ snd_soc_unregister_dai(&ak4535_dai);
+}
+module_exit(ak4535_exit);
+
MODULE_DESCRIPTION("Soc AK4535 driver");
MODULE_AUTHOR("Richard Purdie");
MODULE_LICENSE("GPL");
/*
* Program the CS4270 with the given hardware parameters.
*
- * The .dai_ops functions are used to provide board-specific data, like
+ * The .ops functions are used to provide board-specific data, like
* input frequencies, to this driver. This function takes that information,
* combines it with the hardware parameters provided, and programs the
* hardware accordingly.
*/
static int cs4270_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
return ret;
}
+ /* Disable automatic volume control. It's enabled by default, and
+ * it causes volume change commands to be delayed, sometimes until
+ * after playback has started.
+ */
+
+ reg = cs4270_read_reg_cache(codec, CS4270_TRANS);
+ reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
+ ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
+ if (ret < 0) {
+ printk(KERN_ERR "I2C write failed\n");
+ return ret;
+ }
+
/* Thaw and power-up the codec */
ret = snd_soc_write(codec, CS4270_PWRCTL, 0);
if (codec->control_data) {
/* Initialize codec ops */
cs4270_dai.ops.hw_params = cs4270_hw_params;
- cs4270_dai.dai_ops.set_sysclk = cs4270_set_dai_sysclk;
- cs4270_dai.dai_ops.set_fmt = cs4270_set_dai_fmt;
+ cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk;
+ cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt;
#ifdef CONFIG_SND_SOC_CS4270_HWMUTE
- cs4270_dai.dai_ops.digital_mute = cs4270_mute;
+ cs4270_dai.ops.digital_mute = cs4270_mute;
#endif
} else
printk(KERN_INFO "cs4270: no I2C device found, "
printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n");
#endif
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "cs4270: failed to register card\n");
goto error_del_driver;
};
EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
+static int __init cs4270_init(void)
+{
+ return snd_soc_register_dai(&cs4270_dai);
+}
+module_init(cs4270_init);
+
+static void __exit cs4270_exit(void)
+{
+ snd_soc_unregister_dai(&cs4270_dai);
+}
+module_exit(cs4270_exit);
+
MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * L3 code
+ *
+ * Copyright (C) 2008, Christian Pellegrin <chripell@evolware.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * based on:
+ *
+ * L3 bus algorithm module.
+ *
+ * Copyright (C) 2001 Russell King, All Rights Reserved.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include <sound/l3.h>
+
+/*
+ * Send one byte of data to the chip. Data is latched into the chip on
+ * the rising edge of the clock.
+ */
+static void sendbyte(struct l3_pins *adap, unsigned int byte)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ adap->setclk(0);
+ udelay(adap->data_hold);
+ adap->setdat(byte & 1);
+ udelay(adap->data_setup);
+ adap->setclk(1);
+ udelay(adap->clock_high);
+ byte >>= 1;
+ }
+}
+
+/*
+ * Send a set of bytes to the chip. We need to pulse the MODE line
+ * between each byte, but never at the start nor at the end of the
+ * transfer.
+ */
+static void sendbytes(struct l3_pins *adap, const u8 *buf,
+ int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (i) {
+ udelay(adap->mode_hold);
+ adap->setmode(0);
+ udelay(adap->mode);
+ }
+ adap->setmode(1);
+ udelay(adap->mode_setup);
+ sendbyte(adap, buf[i]);
+ }
+}
+
+int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len)
+{
+ adap->setclk(1);
+ adap->setdat(1);
+ adap->setmode(1);
+ udelay(adap->mode);
+
+ adap->setmode(0);
+ udelay(adap->mode_setup);
+ sendbyte(adap, addr);
+ udelay(adap->mode_hold);
+
+ sendbytes(adap, data, len);
+
+ adap->setclk(1);
+ adap->setdat(1);
+ adap->setmode(0);
+
+ return len;
+}
+EXPORT_SYMBOL_GPL(l3_write);
+
+MODULE_DESCRIPTION("L3 bit-banging driver");
+MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * ALSA Soc PCM3008 codec support
+ *
+ * Author: Hugo Villeneuve
+ * Copyright (C) 2008 Lyrtech inc
+ *
+ * Based on AC97 Soc codec, original copyright follow:
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Generic PCM3008 support.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "pcm3008.h"
+
+#define PCM3008_VERSION "0.2"
+
+#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000)
+
+struct snd_soc_dai pcm3008_dai = {
+ .name = "PCM3008 HiFi",
+ .playback = {
+ .stream_name = "PCM3008 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PCM3008_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .stream_name = "PCM3008 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PCM3008_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+};
+EXPORT_SYMBOL_GPL(pcm3008_dai);
+
+static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
+{
+ gpio_free(setup->dem0_pin);
+ gpio_free(setup->dem1_pin);
+ gpio_free(setup->pdad_pin);
+ gpio_free(setup->pdda_pin);
+}
+
+static int pcm3008_soc_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ struct pcm3008_setup_data *setup = socdev->codec_data;
+ int ret = 0;
+
+ printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
+
+ socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (!socdev->codec)
+ return -ENOMEM;
+
+ codec = socdev->codec;
+ mutex_init(&codec->mutex);
+
+ codec->name = "PCM3008";
+ codec->owner = THIS_MODULE;
+ codec->dai = &pcm3008_dai;
+ codec->num_dai = 1;
+ codec->write = NULL;
+ codec->read = NULL;
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ /* Register PCMs. */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "pcm3008: failed to create pcms\n");
+ goto pcm_err;
+ }
+
+ /* Register Card. */
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "pcm3008: failed to register card\n");
+ goto card_err;
+ }
+
+ /* DEM1 DEM0 DE-EMPHASIS_MODE
+ * Low Low De-emphasis 44.1 kHz ON
+ * Low High De-emphasis OFF
+ * High Low De-emphasis 48 kHz ON
+ * High High De-emphasis 32 kHz ON
+ */
+
+ /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
+ ret = gpio_request(setup->dem0_pin, "codec_dem0");
+ if (ret == 0)
+ ret = gpio_direction_output(setup->dem0_pin, 1);
+ if (ret != 0)
+ goto gpio_err;
+
+ /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
+ ret = gpio_request(setup->dem1_pin, "codec_dem1");
+ if (ret == 0)
+ ret = gpio_direction_output(setup->dem1_pin, 0);
+ if (ret != 0)
+ goto gpio_err;
+
+ /* Configure PDAD GPIO. */
+ ret = gpio_request(setup->pdad_pin, "codec_pdad");
+ if (ret == 0)
+ ret = gpio_direction_output(setup->pdad_pin, 1);
+ if (ret != 0)
+ goto gpio_err;
+
+ /* Configure PDDA GPIO. */
+ ret = gpio_request(setup->pdda_pin, "codec_pdda");
+ if (ret == 0)
+ ret = gpio_direction_output(setup->pdda_pin, 1);
+ if (ret != 0)
+ goto gpio_err;
+
+ return ret;
+
+gpio_err:
+ pcm3008_gpio_free(setup);
+card_err:
+ snd_soc_free_pcms(socdev);
+pcm_err:
+ kfree(socdev->codec);
+
+ return ret;
+}
+
+static int pcm3008_soc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+ struct pcm3008_setup_data *setup = socdev->codec_data;
+
+ if (!codec)
+ return 0;
+
+ pcm3008_gpio_free(setup);
+ snd_soc_free_pcms(socdev);
+ kfree(socdev->codec);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct pcm3008_setup_data *setup = socdev->codec_data;
+
+ gpio_set_value(setup->pdad_pin, 0);
+ gpio_set_value(setup->pdda_pin, 0);
+
+ return 0;
+}
+
+static int pcm3008_soc_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct pcm3008_setup_data *setup = socdev->codec_data;
+
+ gpio_set_value(setup->pdad_pin, 1);
+ gpio_set_value(setup->pdda_pin, 1);
+
+ return 0;
+}
+#else
+#define pcm3008_soc_suspend NULL
+#define pcm3008_soc_resume NULL
+#endif
+
+struct snd_soc_codec_device soc_codec_dev_pcm3008 = {
+ .probe = pcm3008_soc_probe,
+ .remove = pcm3008_soc_remove,
+ .suspend = pcm3008_soc_suspend,
+ .resume = pcm3008_soc_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008);
+
+static int __init pcm3008_init(void)
+{
+ return snd_soc_register_dai(&pcm3008_dai);
+}
+module_init(pcm3008_init);
+
+static void __exit pcm3008_exit(void)
+{
+ snd_soc_unregister_dai(&pcm3008_dai);
+}
+module_exit(pcm3008_exit);
+
+MODULE_DESCRIPTION("Soc PCM3008 driver");
+MODULE_AUTHOR("Hugo Villeneuve");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * PCM3008 ALSA SoC Layer
+ *
+ * Author: Hugo Villeneuve
+ * Copyright (C) 2008 Lyrtech inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_SOC_PCM3008_H
+#define __LINUX_SND_SOC_PCM3008_H
+
+struct pcm3008_setup_data {
+ unsigned dem0_pin;
+ unsigned dem1_pin;
+ unsigned pdad_pin;
+ unsigned pdda_pin;
+};
+
+extern struct snd_soc_codec_device soc_codec_dev_pcm3008;
+extern struct snd_soc_dai pcm3008_dai;
+
+#endif
}
static int ssm2602_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
u16 srate;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
struct ssm2602_priv *ssm2602 = codec->private_data;
+ struct i2c_client *i2c = codec->control_data;
u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
int i = get_coeff(ssm2602->sysclk, params_rate(params));
+ if (substream == ssm2602->slave_substream) {
+ dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
+ return 0;
+ }
+
/*no match is found*/
if (i == ARRAY_SIZE(coeff_div))
return -EINVAL;
return 0;
}
-static int ssm2602_startup(struct snd_pcm_substream *substream)
+static int ssm2602_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
struct ssm2602_priv *ssm2602 = codec->private_data;
+ struct i2c_client *i2c = codec->control_data;
struct snd_pcm_runtime *master_runtime;
/* The DAI has shared clocks so if we already have a playback or
* capture going then constrain this substream to match it.
+ * TODO: the ssm2602 allows pairs of non-matching PB/REC rates
*/
if (ssm2602->master_substream) {
master_runtime = ssm2602->master_substream->runtime;
+ dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n",
+ master_runtime->sample_bits,
+ master_runtime->rate);
+
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
master_runtime->rate,
return 0;
}
-static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream)
+static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
return 0;
}
-static void ssm2602_shutdown(struct snd_pcm_substream *substream)
+static void ssm2602_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
+ struct ssm2602_priv *ssm2602 = codec->private_data;
/* deactivate */
if (!codec->active)
ssm2602_write(codec, SSM2602_ACTIVE, 0);
+
+ if (ssm2602->master_substream == substream)
+ ssm2602->master_substream = ssm2602->slave_substream;
+
+ ssm2602->slave_substream = NULL;
}
static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
SNDRV_PCM_RATE_96000)
+#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
struct snd_soc_dai ssm2602_dai = {
.name = "SSM2602",
.playback = {
.channels_min = 2,
.channels_max = 2,
.rates = SSM2602_RATES,
- .formats = SNDRV_PCM_FMTBIT_S32_LE,},
+ .formats = SSM2602_FORMATS,},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SSM2602_RATES,
- .formats = SNDRV_PCM_FMTBIT_S32_LE,},
+ .formats = SSM2602_FORMATS,},
.ops = {
.startup = ssm2602_startup,
.prepare = ssm2602_pcm_prepare,
.hw_params = ssm2602_hw_params,
.shutdown = ssm2602_shutdown,
- },
- .dai_ops = {
.digital_mute = ssm2602_mute,
.set_sysclk = ssm2602_set_dai_sysclk,
.set_fmt = ssm2602_set_dai_fmt,
ssm2602_add_controls(codec);
ssm2602_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
pr_err("ssm2602: failed to register card\n");
goto card_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602);
+static int __init ssm2602_modinit(void)
+{
+ return snd_soc_register_dai(&ssm2602_dai);
+}
+module_init(ssm2602_modinit);
+
+static void __exit ssm2602_exit(void)
+{
+ snd_soc_unregister_dai(&ssm2602_dai);
+}
+module_exit(ssm2602_exit);
+
MODULE_DESCRIPTION("ASoC ssm2602 driver");
MODULE_AUTHOR("Cliff Cai");
MODULE_LICENSE("GPL");
#define AIC23_VERSION "0.1"
-struct tlv320aic23_srate_reg_info {
- u32 sample_rate;
- u8 control; /* SR3, SR2, SR1, SR0 and BOSR */
- u8 divider; /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
-};
-
/*
* AIC23 register cache
*/
};
-/* tlv320aic23 related */
-static const struct tlv320aic23_srate_reg_info srate_reg_info[] = {
- {4000, 0x06, 1}, /* 4000 */
- {8000, 0x06, 0}, /* 8000 */
- {16000, 0x0C, 1}, /* 16000 */
- {22050, 0x11, 1}, /* 22050 */
- {24000, 0x00, 1}, /* 24000 */
- {32000, 0x0C, 0}, /* 32000 */
- {44100, 0x11, 0}, /* 44100 */
- {48000, 0x00, 0}, /* 48000 */
- {88200, 0x1F, 0}, /* 88200 */
- {96000, 0x0E, 0}, /* 96000 */
+/* AIC23 driver data */
+struct aic23 {
+ struct snd_soc_codec codec;
+ int mclk;
+ int requested_adc;
+ int requested_dac;
+};
+
+/*
+ * Common Crystals used
+ * 11.2896 Mhz /128 = *88.2k /192 = 58.8k
+ * 12.0000 Mhz /125 = *96k /136 = 88.235K
+ * 12.2880 Mhz /128 = *96k /192 = 64k
+ * 16.9344 Mhz /128 = 132.3k /192 = *88.2k
+ * 18.4320 Mhz /128 = 144k /192 = *96k
+ */
+
+/*
+ * Normal BOSR 0-256/2 = 128, 1-384/2 = 192
+ * USB BOSR 0-250/2 = 125, 1-272/2 = 136
+ */
+static const int bosr_usb_divisor_table[] = {
+ 128, 125, 192, 136
+};
+#define LOWER_GROUP ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<6) | (1<<7))
+#define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<15))
+static const unsigned short sr_valid_mask[] = {
+ LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 0*/
+ LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 1*/
+ LOWER_GROUP, /* Usb, bosr - 0*/
+ UPPER_GROUP, /* Usb, bosr - 1*/
+};
+/*
+ * Every divisor is a factor of 11*12
+ */
+#define SR_MULT (11*12)
+#define A(x) (x) ? (SR_MULT/x) : 0
+static const unsigned char sr_adc_mult_table[] = {
+ A(2), A(2), A(12), A(12), A(0), A(0), A(3), A(1),
+ A(2), A(2), A(11), A(11), A(0), A(0), A(0), A(1)
+};
+static const unsigned char sr_dac_mult_table[] = {
+ A(2), A(12), A(2), A(12), A(0), A(0), A(3), A(1),
+ A(2), A(11), A(2), A(11), A(0), A(0), A(0), A(1)
};
+static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
+ int dac, int dac_l, int dac_h, int need_dac)
+{
+ if ((adc >= adc_l) && (adc <= adc_h) &&
+ (dac >= dac_l) && (dac <= dac_h)) {
+ int diff_adc = need_adc - adc;
+ int diff_dac = need_dac - dac;
+ return abs(diff_adc) + abs(diff_dac);
+ }
+ return UINT_MAX;
+}
+
+static int find_rate(int mclk, u32 need_adc, u32 need_dac)
+{
+ int i, j;
+ int best_i = -1;
+ int best_j = -1;
+ int best_div = 0;
+ unsigned best_score = UINT_MAX;
+ int adc_l, adc_h, dac_l, dac_h;
+
+ need_adc *= SR_MULT;
+ need_dac *= SR_MULT;
+ /*
+ * rates given are +/- 1/32
+ */
+ adc_l = need_adc - (need_adc >> 5);
+ adc_h = need_adc + (need_adc >> 5);
+ dac_l = need_dac - (need_dac >> 5);
+ dac_h = need_dac + (need_dac >> 5);
+ for (i = 0; i < ARRAY_SIZE(bosr_usb_divisor_table); i++) {
+ int base = mclk / bosr_usb_divisor_table[i];
+ int mask = sr_valid_mask[i];
+ for (j = 0; j < ARRAY_SIZE(sr_adc_mult_table);
+ j++, mask >>= 1) {
+ int adc;
+ int dac;
+ int score;
+ if ((mask & 1) == 0)
+ continue;
+ adc = base * sr_adc_mult_table[j];
+ dac = base * sr_dac_mult_table[j];
+ score = get_score(adc, adc_l, adc_h, need_adc,
+ dac, dac_l, dac_h, need_dac);
+ if (best_score > score) {
+ best_score = score;
+ best_i = i;
+ best_j = j;
+ best_div = 0;
+ }
+ score = get_score((adc >> 1), adc_l, adc_h, need_adc,
+ (dac >> 1), dac_l, dac_h, need_dac);
+ /* prefer to have a /2 */
+ if ((score != UINT_MAX) && (best_score >= score)) {
+ best_score = score;
+ best_i = i;
+ best_j = j;
+ best_div = 1;
+ }
+ }
+ }
+ return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT);
+}
+
+#ifdef DEBUG
+static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
+ u32 *sample_rate_adc, u32 *sample_rate_dac)
+{
+ int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
+ int sr = (src >> 2) & 0x0f;
+ int val = (mclk / bosr_usb_divisor_table[src & 3]);
+ int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
+ int dac = (val * sr_dac_mult_table[sr]) / SR_MULT;
+ if (src & TLV320AIC23_CLKIN_HALF) {
+ adc >>= 1;
+ dac >>= 1;
+ }
+ *sample_rate_adc = adc;
+ *sample_rate_dac = dac;
+}
+#endif
+
+static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
+ u32 sample_rate_adc, u32 sample_rate_dac)
+{
+ /* Search for the right sample rate */
+ int data = find_rate(mclk, sample_rate_adc, sample_rate_dac);
+ if (data < 0) {
+ printk(KERN_ERR "%s:Invalid rate %u,%u requested\n",
+ __func__, sample_rate_adc, sample_rate_dac);
+ return -EINVAL;
+ }
+ tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
+#ifdef DEBUG
+ {
+ u32 adc, dac;
+ get_current_sample_rates(codec, mclk, &adc, &dac);
+ printk(KERN_DEBUG "actual samplerate = %u,%u reg=%x\n",
+ adc, dac, data);
+ }
+#endif
+ return 0;
+}
+
static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
{
snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
}
static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
- u16 iface_reg, data;
- u8 count = 0;
+ u16 iface_reg;
+ int ret;
+ struct aic23 *aic23 = container_of(codec, struct aic23, codec);
+ u32 sample_rate_adc = aic23->requested_adc;
+ u32 sample_rate_dac = aic23->requested_dac;
+ u32 sample_rate = params_rate(params);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ aic23->requested_dac = sample_rate_dac = sample_rate;
+ if (!sample_rate_adc)
+ sample_rate_adc = sample_rate;
+ } else {
+ aic23->requested_adc = sample_rate_adc = sample_rate;
+ if (!sample_rate_dac)
+ sample_rate_dac = sample_rate;
+ }
+ ret = set_sample_rate_control(codec, aic23->mclk, sample_rate_adc,
+ sample_rate_dac);
+ if (ret < 0)
+ return ret;
iface_reg =
tlv320aic23_read_reg_cache(codec,
TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
-
- /* Search for the right sample rate */
- /* Verify what happens if the rate is not supported
- * now it goes to 96Khz */
- while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
- (count < ARRAY_SIZE(srate_reg_info))) {
- count++;
- }
-
- data = (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
- (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
- TLV320AIC23_USB_CLK_ON;
-
- tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
-
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
break;
return 0;
}
-static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
+static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
return 0;
}
-static void tlv320aic23_shutdown(struct snd_pcm_substream *substream)
+static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
+ struct aic23 *aic23 = container_of(codec, struct aic23, codec);
/* deactivate */
if (!codec->active) {
udelay(50);
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
}
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ aic23->requested_dac = 0;
+ else
+ aic23->requested_adc = 0;
}
static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
-
- switch (freq) {
- case 12000000:
- return 0;
- }
- return -EINVAL;
+ struct aic23 *aic23 = container_of(codec, struct aic23, codec);
+ aic23->mclk = freq;
+ return 0;
}
static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
.prepare = tlv320aic23_pcm_prepare,
.hw_params = tlv320aic23_hw_params,
.shutdown = tlv320aic23_shutdown,
- },
- .dai_ops = {
- .digital_mute = tlv320aic23_mute,
- .set_fmt = tlv320aic23_set_dai_fmt,
- .set_sysclk = tlv320aic23_set_dai_sysclk,
- }
+ .digital_mute = tlv320aic23_mute,
+ .set_fmt = tlv320aic23_set_dai_fmt,
+ .set_sysclk = tlv320aic23_set_dai_sysclk,
+ }
};
EXPORT_SYMBOL_GPL(tlv320aic23_dai);
tlv320aic23_add_controls(codec);
tlv320aic23_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "tlv320aic23: failed to register card\n");
goto card_err;
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec;
+ struct aic23 *aic23;
int ret = 0;
printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
+ aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
+ if (aic23 == NULL)
return -ENOMEM;
-
+ codec = &aic23->codec;
socdev->codec = codec;
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->codec;
+ struct aic23 *aic23 = container_of(codec, struct aic23, codec);
if (codec->control_data)
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
i2c_del_driver(&tlv320aic23_i2c_driver);
#endif
kfree(codec->reg_cache);
- kfree(codec);
+ kfree(aic23);
return 0;
}
};
EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
+static int __init tlv320aic23_modinit(void)
+{
+ return snd_soc_register_dai(&tlv320aic23_dai);
+}
+module_init(tlv320aic23_modinit);
+
+static void __exit tlv320aic23_exit(void)
+{
+ snd_soc_unregister_dai(&tlv320aic23_dai);
+}
+module_exit(tlv320aic23_exit);
+
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
MODULE_LICENSE("GPL");
* Digital Audio Interface Operations
*/
static int aic26_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
},
.ops = {
.hw_params = aic26_hw_params,
- },
- .dai_ops = {
.digital_mute = aic26_mute,
.set_sysclk = aic26_set_sysclk,
.set_fmt = aic26_set_fmt,
/* CODEC is setup, we can register the card now */
dev_dbg(&pdev->dev, "Registering card\n");
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
dev_err(&pdev->dev, "aic26: failed to register card\n");
goto card_err;
static int aic26_spi_probe(struct spi_device *spi)
{
struct aic26 *aic26;
- int rc, i, reg;
+ int ret, i, reg;
dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
aic26->codec.reg_cache_size = AIC26_NUM_REGS;
aic26->codec.reg_cache = aic26->reg_cache;
+ aic26_dai.dev = &spi->dev;
+ ret = snd_soc_register_dai(&aic26_dai);
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to register DAI: %d\n", ret);
+ kfree(aic26);
+ return ret;
+ }
+
/* Reset the codec to power on defaults */
aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00);
/* Register the sysfs files for debugging */
/* Create SysFS files */
- rc = device_create_file(&spi->dev, &dev_attr_keyclick);
- if (rc)
+ ret = device_create_file(&spi->dev, &dev_attr_keyclick);
+ if (ret)
dev_info(&spi->dev, "error creating sysfs files\n");
#if defined(CONFIG_SND_SOC_OF_SIMPLE)
{
struct aic26 *aic26 = dev_get_drvdata(&spi->dev);
+ snd_soc_unregister_dai(&aic26_dai);
kfree(aic26);
return 0;
SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL,
DACR1_2_RLOPM_VOL, 0, 0x7f, 1),
- SOC_DOUBLE_R("Line DAC Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3,
- 0x01, 0),
- SOC_DOUBLE_R("Line PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL,
- PGAR_2_RLOPM_VOL, 0, 0x7f, 1),
- SOC_DOUBLE_R("Line Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL,
+ SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0),
+ SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0),
+ SOC_DOUBLE_R("LineL DAC Playback Volume", DACL1_2_LLOPM_VOL,
+ DACR1_2_LLOPM_VOL, 0, 0x7f, 1),
+ SOC_SINGLE("LineL Left PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL,
+ 0, 0x7f, 1),
+ SOC_SINGLE("LineR Right PGA Bypass Playback Volume", PGAR_2_RLOPM_VOL,
+ 0, 0x7f, 1),
+ SOC_DOUBLE_R("LineL Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL,
+ LINE2R_2_LLOPM_VOL, 0, 0x7f, 1),
+ SOC_DOUBLE_R("LineR Line2 Bypass Playback Volume", LINE2L_2_RLOPM_VOL,
LINE2R_2_RLOPM_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL,
DACR1_2_HPROUT_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
0x01, 0),
- SOC_DOUBLE_R("HP PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL,
+ SOC_DOUBLE_R("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL,
PGAR_2_HPROUT_VOL, 0, 0x7f, 1),
+ SOC_SINGLE("HPL PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL,
+ 0, 0x7f, 1),
+ SOC_SINGLE("HPR PGA Bypass Playback Volume", PGAL_2_HPROUT_VOL,
+ 0, 0x7f, 1),
SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL,
LINE2R_2_HPROUT_VOL, 0, 0x7f, 1),
DACR1_2_HPRCOM_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
0x01, 0),
- SOC_DOUBLE_R("HPCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL,
- PGAR_2_HPRCOM_VOL, 0, 0x7f, 1),
+ SOC_SINGLE("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL,
+ 0, 0x7f, 1),
+ SOC_SINGLE("HPRCOM PGA Bypass Playback Volume", PGAL_2_HPRCOM_VOL,
+ 0, 0x7f, 1),
SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL,
LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1),
/* Left DAC_L1 Mixer */
static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
/* Right DAC_R1 Mixer */
static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
/* Left PGA Mixer */
static const struct snd_kcontrol_new aic3x_left_pga_mixer_controls[] = {
SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1),
+ SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_LADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Line2L Switch", LINE2L_2_LADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1),
+ SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_LADC_CTRL, 0, 1, 1),
};
/* Right PGA Mixer */
static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = {
SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1),
+ SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_RADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Line2R Switch", LINE2R_2_RADC_CTRL, 3, 1, 1),
+ SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_RADC_CTRL, 4, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1),
};
/* Left PGA Bypass Mixer */
static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HP Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPL Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPR Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPLCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPRCOM Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
};
/* Right PGA Bypass Mixer */
static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HP Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPL Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPR Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPLCOM Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPRCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
};
/* Left Line2 Bypass Mixer */
static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPLCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
};
/* Right Line2 Bypass Mixer */
static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("Line Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineL Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("LineR Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPRCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
};
static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
/* Mono Output */
SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0),
- /* Left Inputs to Left ADC */
+ /* Inputs to Left ADC */
SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0),
SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_left_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_left_pga_mixer_controls)),
SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line1_mux_controls),
+ SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0,
+ &aic3x_left_line1_mux_controls),
SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line2_mux_controls),
- /* Right Inputs to Right ADC */
+ /* Inputs to Right ADC */
SND_SOC_DAPM_ADC("Right ADC", "Right Capture",
LINE1R_2_RADC_CTRL, 2, 0),
SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_right_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_right_pga_mixer_controls)),
+ SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0,
+ &aic3x_right_line1_mux_controls),
SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0,
&aic3x_right_line1_mux_controls),
SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0,
{"Left DAC Mux", "DAC_L2", "Left DAC"},
{"Left DAC Mux", "DAC_L3", "Left DAC"},
- {"Left DAC_L1 Mixer", "Line Switch", "Left DAC Mux"},
+ {"Left DAC_L1 Mixer", "LineL Switch", "Left DAC Mux"},
+ {"Left DAC_L1 Mixer", "LineR Switch", "Left DAC Mux"},
{"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"},
{"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"},
{"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"},
{"Right DAC Mux", "DAC_R2", "Right DAC"},
{"Right DAC Mux", "DAC_R3", "Right DAC"},
- {"Right DAC_R1 Mixer", "Line Switch", "Right DAC Mux"},
+ {"Right DAC_R1 Mixer", "LineL Switch", "Right DAC Mux"},
+ {"Right DAC_R1 Mixer", "LineR Switch", "Right DAC Mux"},
{"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"},
{"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"},
{"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"},
{"Left Line2L Mux", "differential", "LINE2L"},
{"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"},
+ {"Left PGA Mixer", "Line1R Switch", "Left Line1R Mux"},
{"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"},
{"Left PGA Mixer", "Mic3L Switch", "MIC3L"},
+ {"Left PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Left ADC", NULL, "Left PGA Mixer"},
{"Left ADC", NULL, "GPIO1 dmic modclk"},
{"Right Line2R Mux", "single-ended", "LINE2R"},
{"Right Line2R Mux", "differential", "LINE2R"},
+ {"Right PGA Mixer", "Line1L Switch", "Right Line1L Mux"},
{"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"},
{"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"},
+ {"Right PGA Mixer", "Mic3L Switch", "MIC3L"},
{"Right PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Right ADC", NULL, "Right PGA Mixer"},
{"Right ADC", NULL, "GPIO1 dmic modclk"},
/* Left PGA Bypass */
- {"Left PGA Bypass Mixer", "Line Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "LineL Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "LineR Switch", "Left PGA Mixer"},
{"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HP Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPCOM Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HPL Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HPR Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HPLCOM Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HPRCOM Switch", "Left PGA Mixer"},
{"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"},
{"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"},
{"Left HP Out", NULL, "Left PGA Bypass Mixer"},
/* Right PGA Bypass */
- {"Right PGA Bypass Mixer", "Line Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "LineL Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "LineR Switch", "Right PGA Mixer"},
{"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HP Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPCOM Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HPL Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HPR Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HPLCOM Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HPRCOM Switch", "Right PGA Mixer"},
{"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"},
{"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"},
{"Right HP Out", NULL, "Right PGA Bypass Mixer"},
/* Left Line2 Bypass */
- {"Left Line2 Bypass Mixer", "Line Switch", "Left Line2L Mux"},
+ {"Left Line2 Bypass Mixer", "LineL Switch", "Left Line2L Mux"},
+ {"Left Line2 Bypass Mixer", "LineR Switch", "Left Line2L Mux"},
{"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"},
{"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"},
- {"Left Line2 Bypass Mixer", "HPCOM Switch", "Left Line2L Mux"},
+ {"Left Line2 Bypass Mixer", "HPLCOM Switch", "Left Line2L Mux"},
{"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"},
{"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"},
{"Left HP Out", NULL, "Left Line2 Bypass Mixer"},
/* Right Line2 Bypass */
- {"Right Line2 Bypass Mixer", "Line Switch", "Right Line2R Mux"},
+ {"Right Line2 Bypass Mixer", "LineL Switch", "Right Line2R Mux"},
+ {"Right Line2 Bypass Mixer", "LineR Switch", "Right Line2R Mux"},
{"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"},
{"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"},
- {"Right Line2 Bypass Mixer", "HPCOM Switch", "Right Line2R Mux"},
+ {"Right Line2 Bypass Mixer", "HPRCOM Switch", "Right Line2R Mux"},
{"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"},
{"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"},
}
static int aic3x_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
}
EXPORT_SYMBOL_GPL(aic3x_get_gpio);
+void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
+ int headset_debounce, int button_debounce)
+{
+ u8 val;
+
+ val = ((detect & AIC3X_HEADSET_DETECT_MASK)
+ << AIC3X_HEADSET_DETECT_SHIFT) |
+ ((headset_debounce & AIC3X_HEADSET_DEBOUNCE_MASK)
+ << AIC3X_HEADSET_DEBOUNCE_SHIFT) |
+ ((button_debounce & AIC3X_BUTTON_DEBOUNCE_MASK)
+ << AIC3X_BUTTON_DEBOUNCE_SHIFT);
+
+ if (detect & AIC3X_HEADSET_DETECT_MASK)
+ val |= AIC3X_HEADSET_DETECT_ENABLED;
+
+ aic3x_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
+}
+EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
+
int aic3x_headset_detected(struct snd_soc_codec *codec)
{
u8 val;
- aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val);
- return (val >> 2) & 1;
+ aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
+ return (val >> 4) & 1;
}
EXPORT_SYMBOL_GPL(aic3x_headset_detected);
+int aic3x_button_pressed(struct snd_soc_codec *codec)
+{
+ u8 val;
+ aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
+ return (val >> 5) & 1;
+}
+EXPORT_SYMBOL_GPL(aic3x_button_pressed);
+
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
.formats = AIC3X_FORMATS,},
.ops = {
.hw_params = aic3x_hw_params,
- },
- .dai_ops = {
.digital_mute = aic3x_mute,
.set_sysclk = aic3x_set_dai_sysclk,
.set_fmt = aic3x_set_dai_fmt,
aic3x_add_controls(codec);
aic3x_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "aic3x: failed to register card\n");
goto card_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x);
+static int __init aic3x_modinit(void)
+{
+ return snd_soc_register_dai(&aic3x_dai);
+}
+module_init(aic3x_modinit);
+
+static void __exit aic3x_exit(void)
+{
+ snd_soc_unregister_dai(&aic3x_dai);
+}
+module_exit(aic3x_exit);
+
MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver");
MODULE_AUTHOR("Vladimir Barinov");
MODULE_LICENSE("GPL");
#define AIC3X_OVRF_STATUS_AND_PLLR_REG 11
/* Audio codec digital filter control register */
#define AIC3X_CODEC_DFILT_CTRL 12
-
+/* Headset/button press detection register */
+#define AIC3X_HEADSET_DETECT_CTRL_A 13
+#define AIC3X_HEADSET_DETECT_CTRL_B 14
/* ADC PGA Gain control registers */
#define LADC_VOL 15
#define RADC_VOL 16
#define MIC3LR_2_RADC_CTRL 18
/* Line1 Input control registers */
#define LINE1L_2_LADC_CTRL 19
+#define LINE1R_2_LADC_CTRL 21
#define LINE1R_2_RADC_CTRL 22
+#define LINE1L_2_RADC_CTRL 24
/* Line2 Input control registers */
#define LINE2L_2_LADC_CTRL 20
#define LINE2R_2_RADC_CTRL 23
#define LINE2L_2_HPLOUT_VOL 45
#define LINE2R_2_HPROUT_VOL 62
#define PGAL_2_HPLOUT_VOL 46
+#define PGAL_2_HPROUT_VOL 60
+#define PGAR_2_HPLOUT_VOL 49
#define PGAR_2_HPROUT_VOL 63
#define DACL1_2_HPLOUT_VOL 47
#define DACR1_2_HPROUT_VOL 64
#define LINE2L_2_HPLCOM_VOL 52
#define LINE2R_2_HPRCOM_VOL 69
#define PGAL_2_HPLCOM_VOL 53
+#define PGAR_2_HPLCOM_VOL 56
+#define PGAL_2_HPRCOM_VOL 67
#define PGAR_2_HPRCOM_VOL 70
#define DACL1_2_HPLCOM_VOL 54
#define DACR1_2_HPRCOM_VOL 71
#define MONOLOPM_CTRL 79
/* Line Output Plus/Minus control registers */
#define LINE2L_2_LLOPM_VOL 80
+#define LINE2L_2_RLOPM_VOL 87
+#define LINE2R_2_LLOPM_VOL 83
#define LINE2R_2_RLOPM_VOL 90
#define PGAL_2_LLOPM_VOL 81
+#define PGAL_2_RLOPM_VOL 88
+#define PGAR_2_LLOPM_VOL 84
#define PGAR_2_RLOPM_VOL 91
#define DACL1_2_LLOPM_VOL 82
+#define DACL1_2_RLOPM_VOL 89
#define DACR1_2_RLOPM_VOL 92
+#define DACR1_2_LLOPM_VOL 85
#define LLOPM_CTRL 86
#define RLOPM_CTRL 93
/* GPIO/IRQ registers */
void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
+
+/* headset detection / button API */
+
+/* The AIC3x supports detection of stereo headsets (GND + left + right signal)
+ * and cellular headsets (GND + speaker output + microphone input).
+ * It is recommended to enable MIC bias for this function to work properly.
+ * For more information, please refer to the datasheet. */
+enum {
+ AIC3X_HEADSET_DETECT_OFF = 0,
+ AIC3X_HEADSET_DETECT_STEREO = 1,
+ AIC3X_HEADSET_DETECT_CELLULAR = 2,
+ AIC3X_HEADSET_DETECT_BOTH = 3
+};
+
+enum {
+ AIC3X_HEADSET_DEBOUNCE_16MS = 0,
+ AIC3X_HEADSET_DEBOUNCE_32MS = 1,
+ AIC3X_HEADSET_DEBOUNCE_64MS = 2,
+ AIC3X_HEADSET_DEBOUNCE_128MS = 3,
+ AIC3X_HEADSET_DEBOUNCE_256MS = 4,
+ AIC3X_HEADSET_DEBOUNCE_512MS = 5
+};
+
+enum {
+ AIC3X_BUTTON_DEBOUNCE_0MS = 0,
+ AIC3X_BUTTON_DEBOUNCE_8MS = 1,
+ AIC3X_BUTTON_DEBOUNCE_16MS = 2,
+ AIC3X_BUTTON_DEBOUNCE_32MS = 3
+};
+
+#define AIC3X_HEADSET_DETECT_ENABLED 0x80
+#define AIC3X_HEADSET_DETECT_SHIFT 5
+#define AIC3X_HEADSET_DETECT_MASK 3
+#define AIC3X_HEADSET_DEBOUNCE_SHIFT 2
+#define AIC3X_HEADSET_DEBOUNCE_MASK 7
+#define AIC3X_BUTTON_DEBOUNCE_SHIFT 0
+#define AIC3X_BUTTON_DEBOUNCE_MASK 3
+
+/* see the enums above for valid parameters to this function */
+void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
+ int headset_debounce, int button_debounce);
int aic3x_headset_detected(struct snd_soc_codec *codec);
+int aic3x_button_pressed(struct snd_soc_codec *codec);
struct aic3x_setup_data {
int i2c_bus;
--- /dev/null
+/*
+ * ALSA SoC TWL4030 codec driver
+ *
+ * Author: Steve Sakoman, <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl4030.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "twl4030.h"
+
+/*
+ * twl4030 register cache & default register settings
+ */
+static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
+ 0x00, /* this register not used */
+ 0x93, /* REG_CODEC_MODE (0x1) */
+ 0xc3, /* REG_OPTION (0x2) */
+ 0x00, /* REG_UNKNOWN (0x3) */
+ 0x00, /* REG_MICBIAS_CTL (0x4) */
+ 0x20, /* REG_ANAMICL (0x5) */
+ 0x00, /* REG_ANAMICR (0x6) */
+ 0x00, /* REG_AVADC_CTL (0x7) */
+ 0x00, /* REG_ADCMICSEL (0x8) */
+ 0x00, /* REG_DIGMIXING (0x9) */
+ 0x0c, /* REG_ATXL1PGA (0xA) */
+ 0x0c, /* REG_ATXR1PGA (0xB) */
+ 0x00, /* REG_AVTXL2PGA (0xC) */
+ 0x00, /* REG_AVTXR2PGA (0xD) */
+ 0x01, /* REG_AUDIO_IF (0xE) */
+ 0x00, /* REG_VOICE_IF (0xF) */
+ 0x00, /* REG_ARXR1PGA (0x10) */
+ 0x00, /* REG_ARXL1PGA (0x11) */
+ 0x6c, /* REG_ARXR2PGA (0x12) */
+ 0x6c, /* REG_ARXL2PGA (0x13) */
+ 0x00, /* REG_VRXPGA (0x14) */
+ 0x00, /* REG_VSTPGA (0x15) */
+ 0x00, /* REG_VRX2ARXPGA (0x16) */
+ 0x0c, /* REG_AVDAC_CTL (0x17) */
+ 0x00, /* REG_ARX2VTXPGA (0x18) */
+ 0x00, /* REG_ARXL1_APGA_CTL (0x19) */
+ 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */
+ 0x4b, /* REG_ARXL2_APGA_CTL (0x1B) */
+ 0x4b, /* REG_ARXR2_APGA_CTL (0x1C) */
+ 0x00, /* REG_ATX2ARXPGA (0x1D) */
+ 0x00, /* REG_BT_IF (0x1E) */
+ 0x00, /* REG_BTPGA (0x1F) */
+ 0x00, /* REG_BTSTPGA (0x20) */
+ 0x00, /* REG_EAR_CTL (0x21) */
+ 0x24, /* REG_HS_SEL (0x22) */
+ 0x0a, /* REG_HS_GAIN_SET (0x23) */
+ 0x00, /* REG_HS_POPN_SET (0x24) */
+ 0x00, /* REG_PREDL_CTL (0x25) */
+ 0x00, /* REG_PREDR_CTL (0x26) */
+ 0x00, /* REG_PRECKL_CTL (0x27) */
+ 0x00, /* REG_PRECKR_CTL (0x28) */
+ 0x00, /* REG_HFL_CTL (0x29) */
+ 0x00, /* REG_HFR_CTL (0x2A) */
+ 0x00, /* REG_ALC_CTL (0x2B) */
+ 0x00, /* REG_ALC_SET1 (0x2C) */
+ 0x00, /* REG_ALC_SET2 (0x2D) */
+ 0x00, /* REG_BOOST_CTL (0x2E) */
+ 0x00, /* REG_SOFTVOL_CTL (0x2F) */
+ 0x00, /* REG_DTMF_FREQSEL (0x30) */
+ 0x00, /* REG_DTMF_TONEXT1H (0x31) */
+ 0x00, /* REG_DTMF_TONEXT1L (0x32) */
+ 0x00, /* REG_DTMF_TONEXT2H (0x33) */
+ 0x00, /* REG_DTMF_TONEXT2L (0x34) */
+ 0x00, /* REG_DTMF_TONOFF (0x35) */
+ 0x00, /* REG_DTMF_WANONOFF (0x36) */
+ 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */
+ 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */
+ 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */
+ 0x16, /* REG_APLL_CTL (0x3A) */
+ 0x00, /* REG_DTMF_CTL (0x3B) */
+ 0x00, /* REG_DTMF_PGA_CTL2 (0x3C) */
+ 0x00, /* REG_DTMF_PGA_CTL1 (0x3D) */
+ 0x00, /* REG_MISC_SET_1 (0x3E) */
+ 0x00, /* REG_PCMBTMUX (0x3F) */
+ 0x00, /* not used (0x40) */
+ 0x00, /* not used (0x41) */
+ 0x00, /* not used (0x42) */
+ 0x00, /* REG_RX_PATH_SEL (0x43) */
+ 0x00, /* REG_VDL_APGA_CTL (0x44) */
+ 0x00, /* REG_VIBRA_CTL (0x45) */
+ 0x00, /* REG_VIBRA_SET (0x46) */
+ 0x00, /* REG_VIBRA_PWM_SET (0x47) */
+ 0x00, /* REG_ANAMIC_GAIN (0x48) */
+ 0x00, /* REG_MISC_SET_2 (0x49) */
+};
+
+/*
+ * read twl4030 register cache
+ */
+static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u8 *cache = codec->reg_cache;
+
+ return cache[reg];
+}
+
+/*
+ * write twl4030 register cache
+ */
+static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec,
+ u8 reg, u8 value)
+{
+ u8 *cache = codec->reg_cache;
+
+ if (reg >= TWL4030_CACHEREGNUM)
+ return;
+ cache[reg] = value;
+}
+
+/*
+ * write to the twl4030 register space
+ */
+static int twl4030_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value)
+{
+ twl4030_write_reg_cache(codec, reg, value);
+ return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
+}
+
+static void twl4030_clear_codecpdz(struct snd_soc_codec *codec)
+{
+ u8 mode;
+
+ mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
+ twl4030_write(codec, TWL4030_REG_CODEC_MODE,
+ mode & ~TWL4030_CODECPDZ);
+
+ /* REVISIT: this delay is present in TI sample drivers */
+ /* but there seems to be no TRM requirement for it */
+ udelay(10);
+}
+
+static void twl4030_set_codecpdz(struct snd_soc_codec *codec)
+{
+ u8 mode;
+
+ mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
+ twl4030_write(codec, TWL4030_REG_CODEC_MODE,
+ mode | TWL4030_CODECPDZ);
+
+ /* REVISIT: this delay is present in TI sample drivers */
+ /* but there seems to be no TRM requirement for it */
+ udelay(10);
+}
+
+static void twl4030_init_chip(struct snd_soc_codec *codec)
+{
+ int i;
+
+ /* clear CODECPDZ prior to setting register defaults */
+ twl4030_clear_codecpdz(codec);
+
+ /* set all audio section registers to reasonable defaults */
+ for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
+ twl4030_write(codec, i, twl4030_reg[i]);
+
+}
+
+/* Earpiece */
+static const char *twl4030_earpiece_texts[] =
+ {"Off", "DACL1", "DACL2", "Invalid", "DACR1"};
+
+static const struct soc_enum twl4030_earpiece_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1,
+ ARRAY_SIZE(twl4030_earpiece_texts),
+ twl4030_earpiece_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_earpiece_control =
+SOC_DAPM_ENUM("Route", twl4030_earpiece_enum);
+
+/* PreDrive Left */
+static const char *twl4030_predrivel_texts[] =
+ {"Off", "DACL1", "DACL2", "Invalid", "DACR2"};
+
+static const struct soc_enum twl4030_predrivel_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1,
+ ARRAY_SIZE(twl4030_predrivel_texts),
+ twl4030_predrivel_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_predrivel_control =
+SOC_DAPM_ENUM("Route", twl4030_predrivel_enum);
+
+/* PreDrive Right */
+static const char *twl4030_predriver_texts[] =
+ {"Off", "DACR1", "DACR2", "Invalid", "DACL2"};
+
+static const struct soc_enum twl4030_predriver_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1,
+ ARRAY_SIZE(twl4030_predriver_texts),
+ twl4030_predriver_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_predriver_control =
+SOC_DAPM_ENUM("Route", twl4030_predriver_enum);
+
+/* Headset Left */
+static const char *twl4030_hsol_texts[] =
+ {"Off", "DACL1", "DACL2"};
+
+static const struct soc_enum twl4030_hsol_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 1,
+ ARRAY_SIZE(twl4030_hsol_texts),
+ twl4030_hsol_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_hsol_control =
+SOC_DAPM_ENUM("Route", twl4030_hsol_enum);
+
+/* Headset Right */
+static const char *twl4030_hsor_texts[] =
+ {"Off", "DACR1", "DACR2"};
+
+static const struct soc_enum twl4030_hsor_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 4,
+ ARRAY_SIZE(twl4030_hsor_texts),
+ twl4030_hsor_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_hsor_control =
+SOC_DAPM_ENUM("Route", twl4030_hsor_enum);
+
+/* Carkit Left */
+static const char *twl4030_carkitl_texts[] =
+ {"Off", "DACL1", "DACL2"};
+
+static const struct soc_enum twl4030_carkitl_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_PRECKL_CTL, 1,
+ ARRAY_SIZE(twl4030_carkitl_texts),
+ twl4030_carkitl_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_carkitl_control =
+SOC_DAPM_ENUM("Route", twl4030_carkitl_enum);
+
+/* Carkit Right */
+static const char *twl4030_carkitr_texts[] =
+ {"Off", "DACR1", "DACR2"};
+
+static const struct soc_enum twl4030_carkitr_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_PRECKR_CTL, 1,
+ ARRAY_SIZE(twl4030_carkitr_texts),
+ twl4030_carkitr_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_carkitr_control =
+SOC_DAPM_ENUM("Route", twl4030_carkitr_enum);
+
+/* Handsfree Left */
+static const char *twl4030_handsfreel_texts[] =
+ {"Voice", "DACL1", "DACL2", "DACR2"};
+
+static const struct soc_enum twl4030_handsfreel_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0,
+ ARRAY_SIZE(twl4030_handsfreel_texts),
+ twl4030_handsfreel_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control =
+SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
+
+/* Handsfree Right */
+static const char *twl4030_handsfreer_texts[] =
+ {"Voice", "DACR1", "DACR2", "DACL2"};
+
+static const struct soc_enum twl4030_handsfreer_enum =
+ SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0,
+ ARRAY_SIZE(twl4030_handsfreer_texts),
+ twl4030_handsfreer_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
+SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
+
+static int outmixer_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int ret = 0;
+ int val;
+
+ switch (e->reg) {
+ case TWL4030_REG_PREDL_CTL:
+ case TWL4030_REG_PREDR_CTL:
+ case TWL4030_REG_EAR_CTL:
+ val = w->value >> e->shift_l;
+ if (val == 3) {
+ printk(KERN_WARNING
+ "Invalid MUX setting for register 0x%02x (%d)\n",
+ e->reg, val);
+ ret = -1;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+static int handsfree_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value;
+ unsigned char hs_ctl;
+
+ hs_ctl = twl4030_read_reg_cache(w->codec, e->reg);
+
+ if (hs_ctl & TWL4030_HF_CTL_REF_EN) {
+ hs_ctl |= TWL4030_HF_CTL_RAMP_EN;
+ twl4030_write(w->codec, e->reg, hs_ctl);
+ hs_ctl |= TWL4030_HF_CTL_LOOP_EN;
+ twl4030_write(w->codec, e->reg, hs_ctl);
+ hs_ctl |= TWL4030_HF_CTL_HB_EN;
+ twl4030_write(w->codec, e->reg, hs_ctl);
+ } else {
+ hs_ctl &= ~(TWL4030_HF_CTL_RAMP_EN | TWL4030_HF_CTL_LOOP_EN
+ | TWL4030_HF_CTL_HB_EN);
+ twl4030_write(w->codec, e->reg, hs_ctl);
+ }
+
+ return 0;
+}
+
+/*
+ * Some of the gain controls in TWL (mostly those which are associated with
+ * the outputs) are implemented in an interesting way:
+ * 0x0 : Power down (mute)
+ * 0x1 : 6dB
+ * 0x2 : 0 dB
+ * 0x3 : -6 dB
+ * Inverting not going to help with these.
+ * Custom volsw and volsw_2r get/put functions to handle these gain bits.
+ */
+#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\
+ xinvert, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw, \
+ .get = snd_soc_get_volsw_twl4030, \
+ .put = snd_soc_put_volsw_twl4030, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
+ .max = xmax, .invert = xinvert} }
+#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\
+ xinvert, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw_2r, \
+ .get = snd_soc_get_volsw_r2_twl4030,\
+ .put = snd_soc_put_volsw_r2_twl4030, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+ .rshift = xshift, .max = xmax, .invert = xinvert} }
+#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \
+ SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \
+ xinvert, tlv_array)
+
+static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int shift = mc->shift;
+ unsigned int rshift = mc->rshift;
+ int max = mc->max;
+ int mask = (1 << fls(max)) - 1;
+
+ ucontrol->value.integer.value[0] =
+ (snd_soc_read(codec, reg) >> shift) & mask;
+ if (ucontrol->value.integer.value[0])
+ ucontrol->value.integer.value[0] =
+ max + 1 - ucontrol->value.integer.value[0];
+
+ if (shift != rshift) {
+ ucontrol->value.integer.value[1] =
+ (snd_soc_read(codec, reg) >> rshift) & mask;
+ if (ucontrol->value.integer.value[1])
+ ucontrol->value.integer.value[1] =
+ max + 1 - ucontrol->value.integer.value[1];
+ }
+
+ return 0;
+}
+
+static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int shift = mc->shift;
+ unsigned int rshift = mc->rshift;
+ int max = mc->max;
+ int mask = (1 << fls(max)) - 1;
+ unsigned short val, val2, val_mask;
+
+ val = (ucontrol->value.integer.value[0] & mask);
+
+ val_mask = mask << shift;
+ if (val)
+ val = max + 1 - val;
+ val = val << shift;
+ if (shift != rshift) {
+ val2 = (ucontrol->value.integer.value[1] & mask);
+ val_mask |= mask << rshift;
+ if (val2)
+ val2 = max + 1 - val2;
+ val |= val2 << rshift;
+ }
+ return snd_soc_update_bits(codec, reg, val_mask, val);
+}
+
+static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ int max = mc->max;
+ int mask = (1<<fls(max))-1;
+
+ ucontrol->value.integer.value[0] =
+ (snd_soc_read(codec, reg) >> shift) & mask;
+ ucontrol->value.integer.value[1] =
+ (snd_soc_read(codec, reg2) >> shift) & mask;
+
+ if (ucontrol->value.integer.value[0])
+ ucontrol->value.integer.value[0] =
+ max + 1 - ucontrol->value.integer.value[0];
+ if (ucontrol->value.integer.value[1])
+ ucontrol->value.integer.value[1] =
+ max + 1 - ucontrol->value.integer.value[1];
+
+ return 0;
+}
+
+static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ int max = mc->max;
+ int mask = (1 << fls(max)) - 1;
+ int err;
+ unsigned short val, val2, val_mask;
+
+ val_mask = mask << shift;
+ val = (ucontrol->value.integer.value[0] & mask);
+ val2 = (ucontrol->value.integer.value[1] & mask);
+
+ if (val)
+ val = max + 1 - val;
+ if (val2)
+ val2 = max + 1 - val2;
+
+ val = val << shift;
+ val2 = val2 << shift;
+
+ err = snd_soc_update_bits(codec, reg, val_mask, val);
+ if (err < 0)
+ return err;
+
+ err = snd_soc_update_bits(codec, reg2, val_mask, val2);
+ return err;
+}
+
+static int twl4030_get_left_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = kcontrol->private_data;
+ u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
+ int result = 0;
+
+ /* one bit must be set a time */
+ reg &= TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
+ | TWL4030_MAINMIC_EN;
+ if (reg != 0) {
+ result++;
+ while ((reg & 1) == 0) {
+ result++;
+ reg >>= 1;
+ }
+ }
+
+ ucontrol->value.integer.value[0] = result;
+ return 0;
+}
+
+static int twl4030_put_left_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = kcontrol->private_data;
+ int value = ucontrol->value.integer.value[0];
+ u8 anamicl, micbias, avadc_ctl;
+
+ anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
+ anamicl &= ~(TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
+ | TWL4030_MAINMIC_EN);
+ micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
+ micbias &= ~(TWL4030_HSMICBIAS_EN | TWL4030_MICBIAS1_EN);
+ avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
+
+ switch (value) {
+ case 1:
+ anamicl |= TWL4030_MAINMIC_EN;
+ micbias |= TWL4030_MICBIAS1_EN;
+ break;
+ case 2:
+ anamicl |= TWL4030_HSMIC_EN;
+ micbias |= TWL4030_HSMICBIAS_EN;
+ break;
+ case 3:
+ anamicl |= TWL4030_AUXL_EN;
+ break;
+ case 4:
+ anamicl |= TWL4030_CKMIC_EN;
+ break;
+ default:
+ break;
+ }
+
+ /* If some input is selected, enable amp and ADC */
+ if (value != 0) {
+ anamicl |= TWL4030_MICAMPL_EN;
+ avadc_ctl |= TWL4030_ADCL_EN;
+ } else {
+ anamicl &= ~TWL4030_MICAMPL_EN;
+ avadc_ctl &= ~TWL4030_ADCL_EN;
+ }
+
+ twl4030_write(codec, TWL4030_REG_ANAMICL, anamicl);
+ twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
+ twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
+
+ return 1;
+}
+
+static int twl4030_get_right_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = kcontrol->private_data;
+ u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
+ int value = 0;
+
+ reg &= TWL4030_SUBMIC_EN|TWL4030_AUXR_EN;
+ switch (reg) {
+ case TWL4030_SUBMIC_EN:
+ value = 1;
+ break;
+ case TWL4030_AUXR_EN:
+ value = 2;
+ break;
+ default:
+ break;
+ }
+
+ ucontrol->value.integer.value[0] = value;
+ return 0;
+}
+
+static int twl4030_put_right_input(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = kcontrol->private_data;
+ int value = ucontrol->value.integer.value[0];
+ u8 anamicr, micbias, avadc_ctl;
+
+ anamicr = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
+ anamicr &= ~(TWL4030_SUBMIC_EN|TWL4030_AUXR_EN);
+ micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
+ micbias &= ~TWL4030_MICBIAS2_EN;
+ avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
+
+ switch (value) {
+ case 1:
+ anamicr |= TWL4030_SUBMIC_EN;
+ micbias |= TWL4030_MICBIAS2_EN;
+ break;
+ case 2:
+ anamicr |= TWL4030_AUXR_EN;
+ break;
+ default:
+ break;
+ }
+
+ if (value != 0) {
+ anamicr |= TWL4030_MICAMPR_EN;
+ avadc_ctl |= TWL4030_ADCR_EN;
+ } else {
+ anamicr &= ~TWL4030_MICAMPR_EN;
+ avadc_ctl &= ~TWL4030_ADCR_EN;
+ }
+
+ twl4030_write(codec, TWL4030_REG_ANAMICR, anamicr);
+ twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
+ twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
+
+ return 1;
+}
+
+static const char *twl4030_left_in_sel[] = {
+ "None",
+ "Main Mic",
+ "Headset Mic",
+ "Line In",
+ "Carkit Mic",
+};
+
+static const char *twl4030_right_in_sel[] = {
+ "None",
+ "Sub Mic",
+ "Line In",
+};
+
+static const struct soc_enum twl4030_left_input_mux =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_left_in_sel),
+ twl4030_left_in_sel);
+
+static const struct soc_enum twl4030_right_input_mux =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_right_in_sel),
+ twl4030_right_in_sel);
+
+/*
+ * FGAIN volume control:
+ * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB)
+ */
+static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1);
+
+/*
+ * CGAIN volume control:
+ * 0 dB to 12 dB in 6 dB steps
+ * value 2 and 3 means 12 dB
+ */
+static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0);
+
+/*
+ * Analog playback gain
+ * -24 dB to 12 dB in 2 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(analog_tlv, -2400, 200, 0);
+
+/*
+ * Gain controls tied to outputs
+ * -6 dB to 6 dB in 6 dB steps (mute instead of -12)
+ */
+static DECLARE_TLV_DB_SCALE(output_tvl, -1200, 600, 1);
+
+/*
+ * Capture gain after the ADCs
+ * from 0 dB to 31 dB in 1 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
+
+/*
+ * Gain control for input amplifiers
+ * 0 dB to 30 dB in 6 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
+
+static const struct snd_kcontrol_new twl4030_snd_controls[] = {
+ /* Common playback gain controls */
+ SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume",
+ TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
+ 0, 0x3f, 0, digital_fine_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Digital Fine Playback Volume",
+ TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
+ 0, 0x3f, 0, digital_fine_tlv),
+
+ SOC_DOUBLE_R_TLV("DAC1 Digital Coarse Playback Volume",
+ TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
+ 6, 0x2, 0, digital_coarse_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Digital Coarse Playback Volume",
+ TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
+ 6, 0x2, 0, digital_coarse_tlv),
+
+ SOC_DOUBLE_R_TLV("DAC1 Analog Playback Volume",
+ TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL,
+ 3, 0x12, 1, analog_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Analog Playback Volume",
+ TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
+ 3, 0x12, 1, analog_tlv),
+ SOC_DOUBLE_R("DAC1 Analog Playback Switch",
+ TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL,
+ 1, 1, 0),
+ SOC_DOUBLE_R("DAC2 Analog Playback Switch",
+ TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
+ 1, 1, 0),
+
+ /* Separate output gain controls */
+ SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
+ TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
+ 4, 3, 0, output_tvl),
+
+ SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume",
+ TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl),
+
+ SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume",
+ TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL,
+ 4, 3, 0, output_tvl),
+
+ SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
+ TWL4030_REG_EAR_CTL, 4, 3, 0, output_tvl),
+
+ /* Common capture gain controls */
+ SOC_DOUBLE_R_TLV("Capture Volume",
+ TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA,
+ 0, 0x1f, 0, digital_capture_tlv),
+
+ SOC_DOUBLE_TLV("Input Boost Volume", TWL4030_REG_ANAMIC_GAIN,
+ 0, 3, 5, 0, input_gain_tlv),
+
+ /* Input source controls */
+ SOC_ENUM_EXT("Left Input Source", twl4030_left_input_mux,
+ twl4030_get_left_input, twl4030_put_left_input),
+ SOC_ENUM_EXT("Right Input Source", twl4030_right_input_mux,
+ twl4030_get_right_input, twl4030_put_right_input),
+};
+
+/* add non dapm controls */
+static int twl4030_add_controls(struct snd_soc_codec *codec)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&twl4030_snd_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("INL"),
+ SND_SOC_DAPM_INPUT("INR"),
+
+ SND_SOC_DAPM_OUTPUT("OUTL"),
+ SND_SOC_DAPM_OUTPUT("OUTR"),
+ SND_SOC_DAPM_OUTPUT("EARPIECE"),
+ SND_SOC_DAPM_OUTPUT("PREDRIVEL"),
+ SND_SOC_DAPM_OUTPUT("PREDRIVER"),
+ SND_SOC_DAPM_OUTPUT("HSOL"),
+ SND_SOC_DAPM_OUTPUT("HSOR"),
+ SND_SOC_DAPM_OUTPUT("CARKITL"),
+ SND_SOC_DAPM_OUTPUT("CARKITR"),
+ SND_SOC_DAPM_OUTPUT("HFL"),
+ SND_SOC_DAPM_OUTPUT("HFR"),
+
+ /* DACs */
+ SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback",
+ TWL4030_REG_AVDAC_CTL, 0, 0),
+ SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback",
+ TWL4030_REG_AVDAC_CTL, 1, 0),
+ SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback",
+ TWL4030_REG_AVDAC_CTL, 2, 0),
+ SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback",
+ TWL4030_REG_AVDAC_CTL, 3, 0),
+
+ /* Analog PGAs */
+ SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("ARXL1_APGA", TWL4030_REG_ARXL1_APGA_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("ARXR2_APGA", TWL4030_REG_ARXR2_APGA_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL,
+ 0, 0, NULL, 0),
+
+ /* Output MUX controls */
+ /* Earpiece */
+ SND_SOC_DAPM_MUX_E("Earpiece Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_earpiece_control, outmixer_event,
+ SND_SOC_DAPM_PRE_REG),
+ /* PreDrivL/R */
+ SND_SOC_DAPM_MUX_E("PredriveL Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_predrivel_control, outmixer_event,
+ SND_SOC_DAPM_PRE_REG),
+ SND_SOC_DAPM_MUX_E("PredriveR Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_predriver_control, outmixer_event,
+ SND_SOC_DAPM_PRE_REG),
+ /* HeadsetL/R */
+ SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_hsol_control),
+ SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_hsor_control),
+ /* CarkitL/R */
+ SND_SOC_DAPM_MUX("CarkitL Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_carkitl_control),
+ SND_SOC_DAPM_MUX("CarkitR Mux", SND_SOC_NOPM, 0, 0,
+ &twl4030_dapm_carkitr_control),
+ /* HandsfreeL/R */
+ SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0,
+ &twl4030_dapm_handsfreel_control, handsfree_event,
+ SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0,
+ &twl4030_dapm_handsfreer_control, handsfree_event,
+ SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+ {"ARXL1_APGA", NULL, "DAC Left1"},
+ {"ARXR1_APGA", NULL, "DAC Right1"},
+ {"ARXL2_APGA", NULL, "DAC Left2"},
+ {"ARXR2_APGA", NULL, "DAC Right2"},
+
+ /* Internal playback routings */
+ /* Earpiece */
+ {"Earpiece Mux", "DACL1", "ARXL1_APGA"},
+ {"Earpiece Mux", "DACL2", "ARXL2_APGA"},
+ {"Earpiece Mux", "DACR1", "ARXR1_APGA"},
+ /* PreDrivL */
+ {"PredriveL Mux", "DACL1", "ARXL1_APGA"},
+ {"PredriveL Mux", "DACL2", "ARXL2_APGA"},
+ {"PredriveL Mux", "DACR2", "ARXR2_APGA"},
+ /* PreDrivR */
+ {"PredriveR Mux", "DACR1", "ARXR1_APGA"},
+ {"PredriveR Mux", "DACR2", "ARXR2_APGA"},
+ {"PredriveR Mux", "DACL2", "ARXL2_APGA"},
+ /* HeadsetL */
+ {"HeadsetL Mux", "DACL1", "ARXL1_APGA"},
+ {"HeadsetL Mux", "DACL2", "ARXL2_APGA"},
+ /* HeadsetR */
+ {"HeadsetR Mux", "DACR1", "ARXR1_APGA"},
+ {"HeadsetR Mux", "DACR2", "ARXR2_APGA"},
+ /* CarkitL */
+ {"CarkitL Mux", "DACL1", "ARXL1_APGA"},
+ {"CarkitL Mux", "DACL2", "ARXL2_APGA"},
+ /* CarkitR */
+ {"CarkitR Mux", "DACR1", "ARXR1_APGA"},
+ {"CarkitR Mux", "DACR2", "ARXR2_APGA"},
+ /* HandsfreeL */
+ {"HandsfreeL Mux", "DACL1", "ARXL1_APGA"},
+ {"HandsfreeL Mux", "DACL2", "ARXL2_APGA"},
+ {"HandsfreeL Mux", "DACR2", "ARXR2_APGA"},
+ /* HandsfreeR */
+ {"HandsfreeR Mux", "DACR1", "ARXR1_APGA"},
+ {"HandsfreeR Mux", "DACR2", "ARXR2_APGA"},
+ {"HandsfreeR Mux", "DACL2", "ARXL2_APGA"},
+
+ /* outputs */
+ {"OUTL", NULL, "ARXL2_APGA"},
+ {"OUTR", NULL, "ARXR2_APGA"},
+ {"EARPIECE", NULL, "Earpiece Mux"},
+ {"PREDRIVEL", NULL, "PredriveL Mux"},
+ {"PREDRIVER", NULL, "PredriveR Mux"},
+ {"HSOL", NULL, "HeadsetL Mux"},
+ {"HSOR", NULL, "HeadsetR Mux"},
+ {"CARKITL", NULL, "CarkitL Mux"},
+ {"CARKITR", NULL, "CarkitR Mux"},
+ {"HFL", NULL, "HandsfreeL Mux"},
+ {"HFR", NULL, "HandsfreeR Mux"},
+
+ /* inputs */
+ {"ADCL", NULL, "INL"},
+ {"ADCR", NULL, "INR"},
+};
+
+static int twl4030_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, twl4030_dapm_widgets,
+ ARRAY_SIZE(twl4030_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+ snd_soc_dapm_new_widgets(codec);
+ return 0;
+}
+
+static void twl4030_power_up(struct snd_soc_codec *codec)
+{
+ u8 anamicl, regmisc1, byte, popn;
+ int i = 0;
+
+ /* set CODECPDZ to turn on codec */
+ twl4030_set_codecpdz(codec);
+
+ /* initiate offset cancellation */
+ anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
+ twl4030_write(codec, TWL4030_REG_ANAMICL,
+ anamicl | TWL4030_CNCL_OFFSET_START);
+
+ /* wait for offset cancellation to complete */
+ do {
+ /* this takes a little while, so don't slam i2c */
+ udelay(2000);
+ twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
+ TWL4030_REG_ANAMICL);
+ } while ((i++ < 100) &&
+ ((byte & TWL4030_CNCL_OFFSET_START) ==
+ TWL4030_CNCL_OFFSET_START));
+
+ /* anti-pop when changing analog gain */
+ regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
+ twl4030_write(codec, TWL4030_REG_MISC_SET_1,
+ regmisc1 | TWL4030_SMOOTH_ANAVOL_EN);
+
+ /* toggle CODECPDZ as per TRM */
+ twl4030_clear_codecpdz(codec);
+ twl4030_set_codecpdz(codec);
+
+ /* program anti-pop with bias ramp delay */
+ popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
+ popn &= TWL4030_RAMP_DELAY;
+ popn |= TWL4030_RAMP_DELAY_645MS;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+ popn |= TWL4030_VMID_EN;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+
+ /* enable anti-pop ramp */
+ popn |= TWL4030_RAMP_EN;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+}
+
+static void twl4030_power_down(struct snd_soc_codec *codec)
+{
+ u8 popn;
+
+ /* disable anti-pop ramp */
+ popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
+ popn &= ~TWL4030_RAMP_EN;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+
+ /* disable bias out */
+ popn &= ~TWL4030_VMID_EN;
+ twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
+
+ /* power down */
+ twl4030_clear_codecpdz(codec);
+}
+
+static int twl4030_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ twl4030_power_up(codec);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ /* TODO: develop a twl4030_prepare function */
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ /* TODO: develop a twl4030_standby function */
+ twl4030_power_down(codec);
+ break;
+ case SND_SOC_BIAS_OFF:
+ twl4030_power_down(codec);
+ break;
+ }
+ codec->bias_level = level;
+
+ return 0;
+}
+
+static int twl4030_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ u8 mode, old_mode, format, old_format;
+
+
+ /* bit rate */
+ old_mode = twl4030_read_reg_cache(codec,
+ TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
+ mode = old_mode & ~TWL4030_APLL_RATE;
+
+ switch (params_rate(params)) {
+ case 8000:
+ mode |= TWL4030_APLL_RATE_8000;
+ break;
+ case 11025:
+ mode |= TWL4030_APLL_RATE_11025;
+ break;
+ case 12000:
+ mode |= TWL4030_APLL_RATE_12000;
+ break;
+ case 16000:
+ mode |= TWL4030_APLL_RATE_16000;
+ break;
+ case 22050:
+ mode |= TWL4030_APLL_RATE_22050;
+ break;
+ case 24000:
+ mode |= TWL4030_APLL_RATE_24000;
+ break;
+ case 32000:
+ mode |= TWL4030_APLL_RATE_32000;
+ break;
+ case 44100:
+ mode |= TWL4030_APLL_RATE_44100;
+ break;
+ case 48000:
+ mode |= TWL4030_APLL_RATE_48000;
+ break;
+ default:
+ printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ if (mode != old_mode) {
+ /* change rate and set CODECPDZ */
+ twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
+ twl4030_set_codecpdz(codec);
+ }
+
+ /* sample size */
+ old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
+ format = old_format;
+ format &= ~TWL4030_DATA_WIDTH;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ format |= TWL4030_DATA_WIDTH_16S_16W;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ format |= TWL4030_DATA_WIDTH_32S_24W;
+ break;
+ default:
+ printk(KERN_ERR "TWL4030 hw params: unknown format %d\n",
+ params_format(params));
+ return -EINVAL;
+ }
+
+ if (format != old_format) {
+
+ /* clear CODECPDZ before changing format (codec requirement) */
+ twl4030_clear_codecpdz(codec);
+
+ /* change format */
+ twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
+
+ /* set CODECPDZ afterwards */
+ twl4030_set_codecpdz(codec);
+ }
+ return 0;
+}
+
+static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u8 infreq;
+
+ switch (freq) {
+ case 19200000:
+ infreq = TWL4030_APLL_INFREQ_19200KHZ;
+ break;
+ case 26000000:
+ infreq = TWL4030_APLL_INFREQ_26000KHZ;
+ break;
+ case 38400000:
+ infreq = TWL4030_APLL_INFREQ_38400KHZ;
+ break;
+ default:
+ printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n",
+ freq);
+ return -EINVAL;
+ }
+
+ infreq |= TWL4030_APLL_EN;
+ twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
+
+ return 0;
+}
+
+static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u8 old_format, format;
+
+ /* get format */
+ old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
+ format = old_format;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ format &= ~(TWL4030_AIF_SLAVE_EN);
+ format &= ~(TWL4030_CLK256FS_EN);
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ format |= TWL4030_AIF_SLAVE_EN;
+ format |= TWL4030_CLK256FS_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ format &= ~TWL4030_AIF_FORMAT;
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ format |= TWL4030_AIF_FORMAT_CODEC;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (format != old_format) {
+
+ /* clear CODECPDZ before changing format (codec requirement) */
+ twl4030_clear_codecpdz(codec);
+
+ /* change format */
+ twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
+
+ /* set CODECPDZ afterwards */
+ twl4030_set_codecpdz(codec);
+ }
+
+ return 0;
+}
+
+#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
+#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
+
+struct snd_soc_dai twl4030_dai = {
+ .name = "twl4030",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = TWL4030_RATES,
+ .formats = TWL4030_FORMATS,},
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = TWL4030_RATES,
+ .formats = TWL4030_FORMATS,},
+ .ops = {
+ .hw_params = twl4030_hw_params,
+ .set_sysclk = twl4030_set_dai_sysclk,
+ .set_fmt = twl4030_set_dai_fmt,
+ }
+};
+EXPORT_SYMBOL_GPL(twl4030_dai);
+
+static int twl4030_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int twl4030_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ twl4030_set_bias_level(codec, codec->suspend_bias_level);
+ return 0;
+}
+
+/*
+ * initialize the driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+
+static int twl4030_init(struct snd_soc_device *socdev)
+{
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret = 0;
+
+ printk(KERN_INFO "TWL4030 Audio Codec init \n");
+
+ codec->name = "twl4030";
+ codec->owner = THIS_MODULE;
+ codec->read = twl4030_read_reg_cache;
+ codec->write = twl4030_write;
+ codec->set_bias_level = twl4030_set_bias_level;
+ codec->dai = &twl4030_dai;
+ codec->num_dai = 1;
+ codec->reg_cache_size = sizeof(twl4030_reg);
+ codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
+ GFP_KERNEL);
+ if (codec->reg_cache == NULL)
+ return -ENOMEM;
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "twl4030: failed to create pcms\n");
+ goto pcm_err;
+ }
+
+ twl4030_init_chip(codec);
+
+ /* power on device */
+ twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ twl4030_add_controls(codec);
+ twl4030_add_widgets(codec);
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "twl4030: failed to register card\n");
+ goto card_err;
+ }
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ kfree(codec->reg_cache);
+ return ret;
+}
+
+static struct snd_soc_device *twl4030_socdev;
+
+static int twl4030_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+
+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (codec == NULL)
+ return -ENOMEM;
+
+ socdev->codec = codec;
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ twl4030_socdev = socdev;
+ twl4030_init(socdev);
+
+ return 0;
+}
+
+static int twl4030_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ printk(KERN_INFO "TWL4030 Audio Codec remove\n");
+ kfree(codec);
+
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_twl4030 = {
+ .probe = twl4030_probe,
+ .remove = twl4030_remove,
+ .suspend = twl4030_suspend,
+ .resume = twl4030_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
+
+static int __init twl4030_modinit(void)
+{
+ return snd_soc_register_dai(&twl4030_dai);
+}
+module_init(twl4030_modinit);
+
+static void __exit twl4030_exit(void)
+{
+ snd_soc_unregister_dai(&twl4030_dai);
+}
+module_exit(twl4030_exit);
+
+MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
+MODULE_AUTHOR("Steve Sakoman");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * ALSA SoC TWL4030 codec driver
+ *
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TWL4030_AUDIO_H__
+#define __TWL4030_AUDIO_H__
+
+#define TWL4030_REG_CODEC_MODE 0x1
+#define TWL4030_REG_OPTION 0x2
+#define TWL4030_REG_UNKNOWN 0x3
+#define TWL4030_REG_MICBIAS_CTL 0x4
+#define TWL4030_REG_ANAMICL 0x5
+#define TWL4030_REG_ANAMICR 0x6
+#define TWL4030_REG_AVADC_CTL 0x7
+#define TWL4030_REG_ADCMICSEL 0x8
+#define TWL4030_REG_DIGMIXING 0x9
+#define TWL4030_REG_ATXL1PGA 0xA
+#define TWL4030_REG_ATXR1PGA 0xB
+#define TWL4030_REG_AVTXL2PGA 0xC
+#define TWL4030_REG_AVTXR2PGA 0xD
+#define TWL4030_REG_AUDIO_IF 0xE
+#define TWL4030_REG_VOICE_IF 0xF
+#define TWL4030_REG_ARXR1PGA 0x10
+#define TWL4030_REG_ARXL1PGA 0x11
+#define TWL4030_REG_ARXR2PGA 0x12
+#define TWL4030_REG_ARXL2PGA 0x13
+#define TWL4030_REG_VRXPGA 0x14
+#define TWL4030_REG_VSTPGA 0x15
+#define TWL4030_REG_VRX2ARXPGA 0x16
+#define TWL4030_REG_AVDAC_CTL 0x17
+#define TWL4030_REG_ARX2VTXPGA 0x18
+#define TWL4030_REG_ARXL1_APGA_CTL 0x19
+#define TWL4030_REG_ARXR1_APGA_CTL 0x1A
+#define TWL4030_REG_ARXL2_APGA_CTL 0x1B
+#define TWL4030_REG_ARXR2_APGA_CTL 0x1C
+#define TWL4030_REG_ATX2ARXPGA 0x1D
+#define TWL4030_REG_BT_IF 0x1E
+#define TWL4030_REG_BTPGA 0x1F
+#define TWL4030_REG_BTSTPGA 0x20
+#define TWL4030_REG_EAR_CTL 0x21
+#define TWL4030_REG_HS_SEL 0x22
+#define TWL4030_REG_HS_GAIN_SET 0x23
+#define TWL4030_REG_HS_POPN_SET 0x24
+#define TWL4030_REG_PREDL_CTL 0x25
+#define TWL4030_REG_PREDR_CTL 0x26
+#define TWL4030_REG_PRECKL_CTL 0x27
+#define TWL4030_REG_PRECKR_CTL 0x28
+#define TWL4030_REG_HFL_CTL 0x29
+#define TWL4030_REG_HFR_CTL 0x2A
+#define TWL4030_REG_ALC_CTL 0x2B
+#define TWL4030_REG_ALC_SET1 0x2C
+#define TWL4030_REG_ALC_SET2 0x2D
+#define TWL4030_REG_BOOST_CTL 0x2E
+#define TWL4030_REG_SOFTVOL_CTL 0x2F
+#define TWL4030_REG_DTMF_FREQSEL 0x30
+#define TWL4030_REG_DTMF_TONEXT1H 0x31
+#define TWL4030_REG_DTMF_TONEXT1L 0x32
+#define TWL4030_REG_DTMF_TONEXT2H 0x33
+#define TWL4030_REG_DTMF_TONEXT2L 0x34
+#define TWL4030_REG_DTMF_TONOFF 0x35
+#define TWL4030_REG_DTMF_WANONOFF 0x36
+#define TWL4030_REG_I2S_RX_SCRAMBLE_H 0x37
+#define TWL4030_REG_I2S_RX_SCRAMBLE_M 0x38
+#define TWL4030_REG_I2S_RX_SCRAMBLE_L 0x39
+#define TWL4030_REG_APLL_CTL 0x3A
+#define TWL4030_REG_DTMF_CTL 0x3B
+#define TWL4030_REG_DTMF_PGA_CTL2 0x3C
+#define TWL4030_REG_DTMF_PGA_CTL1 0x3D
+#define TWL4030_REG_MISC_SET_1 0x3E
+#define TWL4030_REG_PCMBTMUX 0x3F
+#define TWL4030_REG_RX_PATH_SEL 0x43
+#define TWL4030_REG_VDL_APGA_CTL 0x44
+#define TWL4030_REG_VIBRA_CTL 0x45
+#define TWL4030_REG_VIBRA_SET 0x46
+#define TWL4030_REG_VIBRA_PWM_SET 0x47
+#define TWL4030_REG_ANAMIC_GAIN 0x48
+#define TWL4030_REG_MISC_SET_2 0x49
+
+#define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1)
+
+/* Bitfield Definitions */
+
+/* TWL4030_CODEC_MODE (0x01) Fields */
+
+#define TWL4030_APLL_RATE 0xF0
+#define TWL4030_APLL_RATE_8000 0x00
+#define TWL4030_APLL_RATE_11025 0x10
+#define TWL4030_APLL_RATE_12000 0x20
+#define TWL4030_APLL_RATE_16000 0x40
+#define TWL4030_APLL_RATE_22050 0x50
+#define TWL4030_APLL_RATE_24000 0x60
+#define TWL4030_APLL_RATE_32000 0x80
+#define TWL4030_APLL_RATE_44100 0x90
+#define TWL4030_APLL_RATE_48000 0xA0
+#define TWL4030_SEL_16K 0x04
+#define TWL4030_CODECPDZ 0x02
+#define TWL4030_OPT_MODE 0x01
+
+/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
+
+#define TWL4030_MICBIAS2_CTL 0x40
+#define TWL4030_MICBIAS1_CTL 0x20
+#define TWL4030_HSMICBIAS_EN 0x04
+#define TWL4030_MICBIAS2_EN 0x02
+#define TWL4030_MICBIAS1_EN 0x01
+
+/* ANAMICL (0x05) Fields */
+
+#define TWL4030_CNCL_OFFSET_START 0x80
+#define TWL4030_OFFSET_CNCL_SEL 0x60
+#define TWL4030_OFFSET_CNCL_SEL_ARX1 0x00
+#define TWL4030_OFFSET_CNCL_SEL_ARX2 0x20
+#define TWL4030_OFFSET_CNCL_SEL_VRX 0x40
+#define TWL4030_OFFSET_CNCL_SEL_ALL 0x60
+#define TWL4030_MICAMPL_EN 0x10
+#define TWL4030_CKMIC_EN 0x08
+#define TWL4030_AUXL_EN 0x04
+#define TWL4030_HSMIC_EN 0x02
+#define TWL4030_MAINMIC_EN 0x01
+
+/* ANAMICR (0x06) Fields */
+
+#define TWL4030_MICAMPR_EN 0x10
+#define TWL4030_AUXR_EN 0x04
+#define TWL4030_SUBMIC_EN 0x01
+
+/* AVADC_CTL (0x07) Fields */
+
+#define TWL4030_ADCL_EN 0x08
+#define TWL4030_AVADC_CLK_PRIORITY 0x04
+#define TWL4030_ADCR_EN 0x02
+
+/* AUDIO_IF (0x0E) Fields */
+
+#define TWL4030_AIF_SLAVE_EN 0x80
+#define TWL4030_DATA_WIDTH 0x60
+#define TWL4030_DATA_WIDTH_16S_16W 0x00
+#define TWL4030_DATA_WIDTH_32S_16W 0x40
+#define TWL4030_DATA_WIDTH_32S_24W 0x60
+#define TWL4030_AIF_FORMAT 0x18
+#define TWL4030_AIF_FORMAT_CODEC 0x00
+#define TWL4030_AIF_FORMAT_LEFT 0x08
+#define TWL4030_AIF_FORMAT_RIGHT 0x10
+#define TWL4030_AIF_FORMAT_TDM 0x18
+#define TWL4030_AIF_TRI_EN 0x04
+#define TWL4030_CLK256FS_EN 0x02
+#define TWL4030_AIF_EN 0x01
+
+/* HS_GAIN_SET (0x23) Fields */
+
+#define TWL4030_HSR_GAIN 0x0C
+#define TWL4030_HSR_GAIN_PWR_DOWN 0x00
+#define TWL4030_HSR_GAIN_PLUS_6DB 0x04
+#define TWL4030_HSR_GAIN_0DB 0x08
+#define TWL4030_HSR_GAIN_MINUS_6DB 0x0C
+#define TWL4030_HSL_GAIN 0x03
+#define TWL4030_HSL_GAIN_PWR_DOWN 0x00
+#define TWL4030_HSL_GAIN_PLUS_6DB 0x01
+#define TWL4030_HSL_GAIN_0DB 0x02
+#define TWL4030_HSL_GAIN_MINUS_6DB 0x03
+
+/* HS_POPN_SET (0x24) Fields */
+
+#define TWL4030_VMID_EN 0x40
+#define TWL4030_EXTMUTE 0x20
+#define TWL4030_RAMP_DELAY 0x1C
+#define TWL4030_RAMP_DELAY_20MS 0x00
+#define TWL4030_RAMP_DELAY_40MS 0x04
+#define TWL4030_RAMP_DELAY_81MS 0x08
+#define TWL4030_RAMP_DELAY_161MS 0x0C
+#define TWL4030_RAMP_DELAY_323MS 0x10
+#define TWL4030_RAMP_DELAY_645MS 0x14
+#define TWL4030_RAMP_DELAY_1291MS 0x18
+#define TWL4030_RAMP_DELAY_2581MS 0x1C
+#define TWL4030_RAMP_EN 0x02
+
+/* HFL_CTL (0x29, 0x2A) Fields */
+#define TWL4030_HF_CTL_HB_EN 0x04
+#define TWL4030_HF_CTL_LOOP_EN 0x08
+#define TWL4030_HF_CTL_RAMP_EN 0x10
+#define TWL4030_HF_CTL_REF_EN 0x20
+
+/* APLL_CTL (0x3A) Fields */
+
+#define TWL4030_APLL_EN 0x10
+#define TWL4030_APLL_INFREQ 0x0F
+#define TWL4030_APLL_INFREQ_19200KHZ 0x05
+#define TWL4030_APLL_INFREQ_26000KHZ 0x06
+#define TWL4030_APLL_INFREQ_38400KHZ 0x0F
+
+/* REG_MISC_SET_1 (0x3E) Fields */
+
+#define TWL4030_CLK64_EN 0x80
+#define TWL4030_SCRAMBLE_EN 0x40
+#define TWL4030_FMLOOP_EN 0x20
+#define TWL4030_SMOOTH_ANAVOL_EN 0x02
+#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
+
+extern struct snd_soc_dai twl4030_dai;
+extern struct snd_soc_codec_device soc_codec_dev_twl4030;
+
+#endif /* End of __TWL4030_AUDIO_H__ */
--- /dev/null
+/*
+ * uda134x.c -- UDA134X ALSA SoC Codec driver
+ *
+ * Modifications by Christian Pellegrin <chripell@evolware.org>
+ *
+ * Copyright 2007 Dension Audio Systems Ltd.
+ * Author: Zoltan Devai
+ *
+ * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include <sound/uda134x.h>
+#include <sound/l3.h>
+
+#include "uda134x.h"
+
+
+#define POWER_OFF_ON_STANDBY 1
+/*
+ ALSA SOC usually puts the device in standby mode when it's not used
+ for sometime. If you define POWER_OFF_ON_STANDBY the driver will
+ turn off the ADC/DAC when this callback is invoked and turn it back
+ on when needed. Unfortunately this will result in a very light bump
+ (it can be audible only with good earphones). If this bothers you
+ just comment this line, you will have slightly higher power
+ consumption . Please note that sending the L3 command for ADC is
+ enough to make the bump, so it doesn't make difference if you
+ completely take off power from the codec.
+ */
+
+#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000
+#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
+
+struct uda134x_priv {
+ int sysclk;
+ int dai_fmt;
+
+ struct snd_pcm_substream *master_substream;
+ struct snd_pcm_substream *slave_substream;
+};
+
+/* In-data addresses are hard-coded into the reg-cache values */
+static const char uda134x_reg[UDA134X_REGS_NUM] = {
+ /* Extended address registers */
+ 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* Status, data regs */
+ 0x00, 0x83, 0x00, 0x40, 0x80, 0x00,
+};
+
+/*
+ * The codec has no support for reading its registers except for peak level...
+ */
+static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u8 *cache = codec->reg_cache;
+
+ if (reg >= UDA134X_REGS_NUM)
+ return -1;
+ return cache[reg];
+}
+
+/*
+ * Write the register cache
+ */
+static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec,
+ u8 reg, unsigned int value)
+{
+ u8 *cache = codec->reg_cache;
+
+ if (reg >= UDA134X_REGS_NUM)
+ return;
+ cache[reg] = value;
+}
+
+/*
+ * Write to the uda134x registers
+ *
+ */
+static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ int ret;
+ u8 addr;
+ u8 data = value;
+ struct uda134x_platform_data *pd = codec->control_data;
+
+ pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value);
+
+ if (reg >= UDA134X_REGS_NUM) {
+ printk(KERN_ERR "%s unkown register: reg: %d",
+ __func__, reg);
+ return -EINVAL;
+ }
+
+ uda134x_write_reg_cache(codec, reg, value);
+
+ switch (reg) {
+ case UDA134X_STATUS0:
+ case UDA134X_STATUS1:
+ addr = UDA134X_STATUS_ADDR;
+ break;
+ case UDA134X_DATA000:
+ case UDA134X_DATA001:
+ case UDA134X_DATA010:
+ addr = UDA134X_DATA0_ADDR;
+ break;
+ case UDA134X_DATA1:
+ addr = UDA134X_DATA1_ADDR;
+ break;
+ default:
+ /* It's an extended address register */
+ addr = (reg | UDA134X_EXTADDR_PREFIX);
+
+ ret = l3_write(&pd->l3,
+ UDA134X_DATA0_ADDR, &addr, 1);
+ if (ret != 1)
+ return -EIO;
+
+ addr = UDA134X_DATA0_ADDR;
+ data = (value | UDA134X_EXTDATA_PREFIX);
+ break;
+ }
+
+ ret = l3_write(&pd->l3,
+ addr, &data, 1);
+ if (ret != 1)
+ return -EIO;
+
+ return 0;
+}
+
+static inline void uda134x_reset(struct snd_soc_codec *codec)
+{
+ u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
+ uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6));
+ msleep(1);
+ uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6));
+}
+
+static int uda134x_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010);
+
+ pr_debug("%s mute: %d\n", __func__, mute);
+
+ if (mute)
+ mute_reg |= (1<<2);
+ else
+ mute_reg &= ~(1<<2);
+
+ uda134x_write(codec, UDA134X_DATA010, mute_reg & ~(1<<2));
+
+ return 0;
+}
+
+static int uda134x_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+ struct snd_pcm_runtime *master_runtime;
+
+ if (uda134x->master_substream) {
+ master_runtime = uda134x->master_substream->runtime;
+
+ pr_debug("%s constraining to %d bits at %d\n", __func__,
+ master_runtime->sample_bits,
+ master_runtime->rate);
+
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ master_runtime->rate,
+ master_runtime->rate);
+
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ master_runtime->sample_bits,
+ master_runtime->sample_bits);
+
+ uda134x->slave_substream = substream;
+ } else
+ uda134x->master_substream = substream;
+
+ return 0;
+}
+
+static void uda134x_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+
+ if (uda134x->master_substream == substream)
+ uda134x->master_substream = uda134x->slave_substream;
+
+ uda134x->slave_substream = NULL;
+}
+
+static int uda134x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+ u8 hw_params;
+
+ if (substream == uda134x->slave_substream) {
+ pr_debug("%s ignoring hw_params for slave substream\n",
+ __func__);
+ return 0;
+ }
+
+ hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
+ hw_params &= STATUS0_SYSCLK_MASK;
+ hw_params &= STATUS0_DAIFMT_MASK;
+
+ pr_debug("%s sysclk: %d, rate:%d\n", __func__,
+ uda134x->sysclk, params_rate(params));
+
+ /* set SYSCLK / fs ratio */
+ switch (uda134x->sysclk / params_rate(params)) {
+ case 512:
+ break;
+ case 384:
+ hw_params |= (1<<4);
+ break;
+ case 256:
+ hw_params |= (1<<5);
+ break;
+ default:
+ printk(KERN_ERR "%s unsupported fs\n", __func__);
+ return -EINVAL;
+ }
+
+ pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__,
+ uda134x->dai_fmt, params_format(params));
+
+ /* set DAI format and word length */
+ switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ hw_params |= (1<<1);
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ hw_params |= (1<<2);
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ hw_params |= ((1<<2) | (1<<1));
+ break;
+ default:
+ printk(KERN_ERR "%s unsupported format (right)\n",
+ __func__);
+ return -EINVAL;
+ }
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ hw_params |= (1<<3);
+ break;
+ default:
+ printk(KERN_ERR "%s unsupported format\n", __func__);
+ return -EINVAL;
+ }
+
+ uda134x_write(codec, UDA134X_STATUS0, hw_params);
+
+ return 0;
+}
+
+static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+
+ pr_debug("%s clk_id: %d, freq: %d, dir: %d\n", __func__,
+ clk_id, freq, dir);
+
+ /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
+ because the codec is slave. Of course limitations of the clock
+ master (the IIS controller) apply.
+ We'll error out on set_hw_params if it's not OK */
+ if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
+ uda134x->sysclk = freq;
+ return 0;
+ }
+
+ printk(KERN_ERR "%s unsupported sysclk\n", __func__);
+ return -EINVAL;
+}
+
+static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct uda134x_priv *uda134x = codec->private_data;
+
+ pr_debug("%s fmt: %08X\n", __func__, fmt);
+
+ /* codec supports only full slave mode */
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
+ printk(KERN_ERR "%s unsupported slave mode\n", __func__);
+ return -EINVAL;
+ }
+
+ /* no support for clock inversion */
+ if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
+ printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
+ return -EINVAL;
+ }
+
+ /* We can't setup DAI format here as it depends on the word bit num */
+ /* so let's just store the value for later */
+ uda134x->dai_fmt = fmt;
+
+ return 0;
+}
+
+static int uda134x_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ u8 reg;
+ struct uda134x_platform_data *pd = codec->control_data;
+ int i;
+ u8 *cache = codec->reg_cache;
+
+ pr_debug("%s bias level %d\n", __func__, level);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ /* ADC, DAC on */
+ reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
+ uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ /* power on */
+ if (pd->power) {
+ pd->power(1);
+ /* Sync reg_cache with the hardware */
+ for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
+ codec->write(codec, i, *cache++);
+ }
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ /* ADC, DAC power off */
+ reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
+ uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
+ break;
+ case SND_SOC_BIAS_OFF:
+ /* power off */
+ if (pd->power)
+ pd->power(0);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1",
+ "Minimum2", "Maximum"};
+static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+static const char *uda134x_mixmode[] = {"Differential", "Analog1",
+ "Analog2", "Both"};
+
+static const struct soc_enum uda134x_mixer_enum[] = {
+SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting),
+SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph),
+SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode),
+};
+
+static const struct snd_kcontrol_new uda1341_snd_controls[] = {
+SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
+SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0),
+SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1),
+SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1),
+
+SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0),
+SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0),
+
+SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
+SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
+
+SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
+SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
+SOC_ENUM("Input Mux", uda134x_mixer_enum[2]),
+
+SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0),
+SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1),
+SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0),
+
+SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0),
+SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0),
+SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0),
+SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0),
+SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0),
+SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new uda1340_snd_controls[] = {
+SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
+
+SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
+SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
+
+SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
+SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
+
+SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
+};
+
+static int uda134x_add_controls(struct snd_soc_codec *codec)
+{
+ int err, i, n;
+ const struct snd_kcontrol_new *ctrls;
+ struct uda134x_platform_data *pd = codec->control_data;
+
+ switch (pd->model) {
+ case UDA134X_UDA1340:
+ case UDA134X_UDA1344:
+ n = ARRAY_SIZE(uda1340_snd_controls);
+ ctrls = uda1340_snd_controls;
+ break;
+ case UDA134X_UDA1341:
+ n = ARRAY_SIZE(uda1341_snd_controls);
+ ctrls = uda1341_snd_controls;
+ break;
+ default:
+ printk(KERN_ERR "%s unkown codec type: %d",
+ __func__, pd->model);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < n; i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&ctrls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+struct snd_soc_dai uda134x_dai = {
+ .name = "UDA134X",
+ /* playback capabilities */
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = UDA134X_RATES,
+ .formats = UDA134X_FORMATS,
+ },
+ /* capture capabilities */
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = UDA134X_RATES,
+ .formats = UDA134X_FORMATS,
+ },
+ /* pcm operations */
+ .ops = {
+ .startup = uda134x_startup,
+ .shutdown = uda134x_shutdown,
+ .hw_params = uda134x_hw_params,
+ .digital_mute = uda134x_mute,
+ .set_sysclk = uda134x_set_dai_sysclk,
+ .set_fmt = uda134x_set_dai_fmt,
+ }
+};
+EXPORT_SYMBOL(uda134x_dai);
+
+
+static int uda134x_soc_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ struct uda134x_priv *uda134x;
+ void *codec_setup_data = socdev->codec_data;
+ int ret = -ENOMEM;
+ struct uda134x_platform_data *pd;
+
+ printk(KERN_INFO "UDA134X SoC Audio Codec\n");
+
+ if (!codec_setup_data) {
+ printk(KERN_ERR "UDA134X SoC codec: "
+ "missing L3 bitbang function\n");
+ return -ENODEV;
+ }
+
+ pd = codec_setup_data;
+ switch (pd->model) {
+ case UDA134X_UDA1340:
+ case UDA134X_UDA1341:
+ case UDA134X_UDA1344:
+ break;
+ default:
+ printk(KERN_ERR "UDA134X SoC codec: "
+ "unsupported model %d\n",
+ pd->model);
+ return -EINVAL;
+ }
+
+ socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (socdev->codec == NULL)
+ return ret;
+
+ codec = socdev->codec;
+
+ uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
+ if (uda134x == NULL)
+ goto priv_err;
+ codec->private_data = uda134x;
+
+ codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg),
+ GFP_KERNEL);
+ if (codec->reg_cache == NULL)
+ goto reg_err;
+
+ mutex_init(&codec->mutex);
+
+ codec->reg_cache_size = sizeof(uda134x_reg);
+ codec->reg_cache_step = 1;
+
+ codec->name = "UDA134X";
+ codec->owner = THIS_MODULE;
+ codec->dai = &uda134x_dai;
+ codec->num_dai = 1;
+ codec->read = uda134x_read_reg_cache;
+ codec->write = uda134x_write;
+#ifdef POWER_OFF_ON_STANDBY
+ codec->set_bias_level = uda134x_set_bias_level;
+#endif
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ codec->control_data = codec_setup_data;
+
+ if (pd->power)
+ pd->power(1);
+
+ uda134x_reset(codec);
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "UDA134X: failed to register pcms\n");
+ goto pcm_err;
+ }
+
+ ret = uda134x_add_controls(codec);
+ if (ret < 0) {
+ printk(KERN_ERR "UDA134X: failed to register controls\n");
+ goto pcm_err;
+ }
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "UDA134X: failed to register card\n");
+ goto card_err;
+ }
+
+ return 0;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ kfree(codec->reg_cache);
+reg_err:
+ kfree(codec->private_data);
+priv_err:
+ kfree(codec);
+ return ret;
+}
+
+/* power down chip */
+static int uda134x_soc_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+
+ kfree(codec->private_data);
+ kfree(codec->reg_cache);
+ kfree(codec);
+
+ return 0;
+}
+
+#if defined(CONFIG_PM)
+static int uda134x_soc_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int uda134x_soc_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+ uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
+ return 0;
+}
+#else
+#define uda134x_soc_suspend NULL
+#define uda134x_soc_resume NULL
+#endif /* CONFIG_PM */
+
+struct snd_soc_codec_device soc_codec_dev_uda134x = {
+ .probe = uda134x_soc_probe,
+ .remove = uda134x_soc_remove,
+ .suspend = uda134x_soc_suspend,
+ .resume = uda134x_soc_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);
+
+static int __init uda134x_init(void)
+{
+ return snd_soc_register_dai(&uda134x_dai);
+}
+module_init(uda134x_init);
+
+static void __exit uda134x_exit(void)
+{
+ snd_soc_unregister_dai(&uda134x_dai);
+}
+module_exit(uda134x_exit);
+
+MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
+MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
+MODULE_LICENSE("GPL");
--- /dev/null
+#ifndef _UDA134X_CODEC_H
+#define _UDA134X_CODEC_H
+
+#define UDA134X_L3ADDR 5
+#define UDA134X_DATA0_ADDR ((UDA134X_L3ADDR << 2) | 0)
+#define UDA134X_DATA1_ADDR ((UDA134X_L3ADDR << 2) | 1)
+#define UDA134X_STATUS_ADDR ((UDA134X_L3ADDR << 2) | 2)
+
+#define UDA134X_EXTADDR_PREFIX 0xC0
+#define UDA134X_EXTDATA_PREFIX 0xE0
+
+/* UDA134X registers */
+#define UDA134X_EA000 0
+#define UDA134X_EA001 1
+#define UDA134X_EA010 2
+#define UDA134X_EA011 3
+#define UDA134X_EA100 4
+#define UDA134X_EA101 5
+#define UDA134X_EA110 6
+#define UDA134X_EA111 7
+#define UDA134X_STATUS0 8
+#define UDA134X_STATUS1 9
+#define UDA134X_DATA000 10
+#define UDA134X_DATA001 11
+#define UDA134X_DATA010 12
+#define UDA134X_DATA1 13
+
+#define UDA134X_REGS_NUM 14
+
+#define STATUS0_DAIFMT_MASK (~(7<<1))
+#define STATUS0_SYSCLK_MASK (~(3<<4))
+
+extern struct snd_soc_dai uda134x_dai;
+extern struct snd_soc_codec_device soc_codec_dev_uda134x;
+
+#endif
* when the DAI is being clocked by the CPU DAI. It's up to the
* machine and cpu DAI driver to do this before we are called.
*/
-static int uda1380_pcm_prepare(struct snd_pcm_substream *substream)
+static int uda1380_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
}
static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
return 0;
}
-static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream)
+static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.prepare = uda1380_pcm_prepare,
- },
- .dai_ops = {
.digital_mute = uda1380_mute,
.set_fmt = uda1380_set_dai_fmt,
},
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.prepare = uda1380_pcm_prepare,
- },
- .dai_ops = {
.digital_mute = uda1380_mute,
.set_fmt = uda1380_set_dai_fmt,
},
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.prepare = uda1380_pcm_prepare,
- },
- .dai_ops = {
.set_fmt = uda1380_set_dai_fmt,
},
},
/* uda1380 init */
uda1380_add_controls(codec);
uda1380_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
pr_err("uda1380: failed to register card\n");
goto card_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
+static int __init uda1380_modinit(void)
+{
+ return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
+}
+module_init(uda1380_modinit);
+
+static void __exit uda1380_exit(void)
+{
+ snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
+}
+module_exit(uda1380_exit);
+
MODULE_AUTHOR("Giorgio Padrin");
MODULE_DESCRIPTION("Audio support for codec Philips UDA1380");
MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * wm8350.c -- WM8350 ALSA SoC audio driver
+ *
+ * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood <lg@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/regulator/consumer.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8350.h"
+
+#define WM8350_OUTn_0dB 0x39
+
+#define WM8350_RAMP_NONE 0
+#define WM8350_RAMP_UP 1
+#define WM8350_RAMP_DOWN 2
+
+/* We only include the analogue supplies here; the digital supplies
+ * need to be available well before this driver can be probed.
+ */
+static const char *supply_names[] = {
+ "AVDD",
+ "HPVDD",
+};
+
+struct wm8350_output {
+ u16 active;
+ u16 left_vol;
+ u16 right_vol;
+ u16 ramp;
+ u16 mute;
+};
+
+struct wm8350_data {
+ struct snd_soc_codec codec;
+ struct wm8350_output out1;
+ struct wm8350_output out2;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
+};
+
+static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ struct wm8350 *wm8350 = codec->control_data;
+ return wm8350->reg_cache[reg];
+}
+
+static unsigned int wm8350_codec_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ struct wm8350 *wm8350 = codec->control_data;
+ return wm8350_reg_read(wm8350, reg);
+}
+
+static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ struct wm8350 *wm8350 = codec->control_data;
+ return wm8350_reg_write(wm8350, reg, value);
+}
+
+/*
+ * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown.
+ */
+static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec)
+{
+ struct wm8350_data *wm8350_data = codec->private_data;
+ struct wm8350_output *out1 = &wm8350_data->out1;
+ struct wm8350 *wm8350 = codec->control_data;
+ int left_complete = 0, right_complete = 0;
+ u16 reg, val;
+
+ /* left channel */
+ reg = wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME);
+ val = (reg & WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
+
+ if (out1->ramp == WM8350_RAMP_UP) {
+ /* ramp step up */
+ if (val < out1->left_vol) {
+ val++;
+ reg &= ~WM8350_OUT1L_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME,
+ reg | (val << WM8350_OUT1L_VOL_SHIFT));
+ } else
+ left_complete = 1;
+ } else if (out1->ramp == WM8350_RAMP_DOWN) {
+ /* ramp step down */
+ if (val > 0) {
+ val--;
+ reg &= ~WM8350_OUT1L_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME,
+ reg | (val << WM8350_OUT1L_VOL_SHIFT));
+ } else
+ left_complete = 1;
+ } else
+ return 1;
+
+ /* right channel */
+ reg = wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME);
+ val = (reg & WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
+ if (out1->ramp == WM8350_RAMP_UP) {
+ /* ramp step up */
+ if (val < out1->right_vol) {
+ val++;
+ reg &= ~WM8350_OUT1R_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME,
+ reg | (val << WM8350_OUT1R_VOL_SHIFT));
+ } else
+ right_complete = 1;
+ } else if (out1->ramp == WM8350_RAMP_DOWN) {
+ /* ramp step down */
+ if (val > 0) {
+ val--;
+ reg &= ~WM8350_OUT1R_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME,
+ reg | (val << WM8350_OUT1R_VOL_SHIFT));
+ } else
+ right_complete = 1;
+ }
+
+ /* only hit the update bit if either volume has changed this step */
+ if (!left_complete || !right_complete)
+ wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME, WM8350_OUT1_VU);
+
+ return left_complete & right_complete;
+}
+
+/*
+ * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown.
+ */
+static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec)
+{
+ struct wm8350_data *wm8350_data = codec->private_data;
+ struct wm8350_output *out2 = &wm8350_data->out2;
+ struct wm8350 *wm8350 = codec->control_data;
+ int left_complete = 0, right_complete = 0;
+ u16 reg, val;
+
+ /* left channel */
+ reg = wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME);
+ val = (reg & WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
+ if (out2->ramp == WM8350_RAMP_UP) {
+ /* ramp step up */
+ if (val < out2->left_vol) {
+ val++;
+ reg &= ~WM8350_OUT2L_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME,
+ reg | (val << WM8350_OUT1L_VOL_SHIFT));
+ } else
+ left_complete = 1;
+ } else if (out2->ramp == WM8350_RAMP_DOWN) {
+ /* ramp step down */
+ if (val > 0) {
+ val--;
+ reg &= ~WM8350_OUT2L_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME,
+ reg | (val << WM8350_OUT1L_VOL_SHIFT));
+ } else
+ left_complete = 1;
+ } else
+ return 1;
+
+ /* right channel */
+ reg = wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME);
+ val = (reg & WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
+ if (out2->ramp == WM8350_RAMP_UP) {
+ /* ramp step up */
+ if (val < out2->right_vol) {
+ val++;
+ reg &= ~WM8350_OUT2R_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME,
+ reg | (val << WM8350_OUT1R_VOL_SHIFT));
+ } else
+ right_complete = 1;
+ } else if (out2->ramp == WM8350_RAMP_DOWN) {
+ /* ramp step down */
+ if (val > 0) {
+ val--;
+ reg &= ~WM8350_OUT2R_VOL_MASK;
+ wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME,
+ reg | (val << WM8350_OUT1R_VOL_SHIFT));
+ } else
+ right_complete = 1;
+ }
+
+ /* only hit the update bit if either volume has changed this step */
+ if (!left_complete || !right_complete)
+ wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME, WM8350_OUT2_VU);
+
+ return left_complete & right_complete;
+}
+
+/*
+ * This work ramps both output PGAs at stream start/stop time to
+ * minimise pop associated with DAPM power switching.
+ * It's best to enable Zero Cross when ramping occurs to minimise any
+ * zipper noises.
+ */
+static void wm8350_pga_work(struct work_struct *work)
+{
+ struct snd_soc_codec *codec =
+ container_of(work, struct snd_soc_codec, delayed_work.work);
+ struct wm8350_data *wm8350_data = codec->private_data;
+ struct wm8350_output *out1 = &wm8350_data->out1,
+ *out2 = &wm8350_data->out2;
+ int i, out1_complete, out2_complete;
+
+ /* do we need to ramp at all ? */
+ if (out1->ramp == WM8350_RAMP_NONE && out2->ramp == WM8350_RAMP_NONE)
+ return;
+
+ /* PGA volumes have 6 bits of resolution to ramp */
+ for (i = 0; i <= 63; i++) {
+ out1_complete = 1, out2_complete = 1;
+ if (out1->ramp != WM8350_RAMP_NONE)
+ out1_complete = wm8350_out1_ramp_step(codec);
+ if (out2->ramp != WM8350_RAMP_NONE)
+ out2_complete = wm8350_out2_ramp_step(codec);
+
+ /* ramp finished ? */
+ if (out1_complete && out2_complete)
+ break;
+
+ /* we need to delay longer on the up ramp */
+ if (out1->ramp == WM8350_RAMP_UP ||
+ out2->ramp == WM8350_RAMP_UP) {
+ /* delay is longer over 0dB as increases are larger */
+ if (i >= WM8350_OUTn_0dB)
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (2));
+ else
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (1));
+ } else
+ udelay(50); /* doesn't matter if we delay longer */
+ }
+
+ out1->ramp = WM8350_RAMP_NONE;
+ out2->ramp = WM8350_RAMP_NONE;
+}
+
+/*
+ * WM8350 Controls
+ */
+
+static int pga_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm8350_data *wm8350_data = codec->private_data;
+ struct wm8350_output *out;
+
+ switch (w->shift) {
+ case 0:
+ case 1:
+ out = &wm8350_data->out1;
+ break;
+ case 2:
+ case 3:
+ out = &wm8350_data->out2;
+ break;
+
+ default:
+ BUG();
+ return -1;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ out->ramp = WM8350_RAMP_UP;
+ out->active = 1;
+
+ if (!delayed_work_pending(&codec->delayed_work))
+ schedule_delayed_work(&codec->delayed_work,
+ msecs_to_jiffies(1));
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ out->ramp = WM8350_RAMP_DOWN;
+ out->active = 0;
+
+ if (!delayed_work_pending(&codec->delayed_work))
+ schedule_delayed_work(&codec->delayed_work,
+ msecs_to_jiffies(1));
+ break;
+ }
+
+ return 0;
+}
+
+static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8350_data *wm8350_priv = codec->private_data;
+ struct wm8350_output *out = NULL;
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int ret;
+ unsigned int reg = mc->reg;
+ u16 val;
+
+ /* For OUT1 and OUT2 we shadow the values and only actually write
+ * them out when active in order to ensure the amplifier comes on
+ * as quietly as possible. */
+ switch (reg) {
+ case WM8350_LOUT1_VOLUME:
+ out = &wm8350_priv->out1;
+ break;
+ case WM8350_LOUT2_VOLUME:
+ out = &wm8350_priv->out2;
+ break;
+ default:
+ break;
+ }
+
+ if (out) {
+ out->left_vol = ucontrol->value.integer.value[0];
+ out->right_vol = ucontrol->value.integer.value[1];
+ if (!out->active)
+ return 1;
+ }
+
+ ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+ if (ret < 0)
+ return ret;
+
+ /* now hit the volume update bits (always bit 8) */
+ val = wm8350_codec_read(codec, reg);
+ wm8350_codec_write(codec, reg, val | WM8350_OUT1_VU);
+ return 1;
+}
+
+static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8350_data *wm8350_priv = codec->private_data;
+ struct wm8350_output *out1 = &wm8350_priv->out1;
+ struct wm8350_output *out2 = &wm8350_priv->out2;
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned int reg = mc->reg;
+
+ /* If these are cached registers use the cache */
+ switch (reg) {
+ case WM8350_LOUT1_VOLUME:
+ ucontrol->value.integer.value[0] = out1->left_vol;
+ ucontrol->value.integer.value[1] = out1->right_vol;
+ return 0;
+
+ case WM8350_LOUT2_VOLUME:
+ ucontrol->value.integer.value[0] = out2->left_vol;
+ ucontrol->value.integer.value[1] = out2->right_vol;
+ return 0;
+
+ default:
+ break;
+ }
+
+ return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+}
+
+/* double control with volume update */
+#define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
+ xinvert, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+ SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw_2r, \
+ .get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+ .rshift = xshift, .max = xmax, .invert = xinvert}, }
+
+static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
+static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
+static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
+static const char *wm8350_dacmutes[] = { "Fast", "Slow" };
+static const char *wm8350_dacfilter[] = { "Normal", "Sloping" };
+static const char *wm8350_adcfilter[] = { "None", "High Pass" };
+static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" };
+static const char *wm8350_lr[] = { "Left", "Right" };
+
+static const struct soc_enum wm8350_enum[] = {
+ SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 4, 4, wm8350_deemp),
+ SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol),
+ SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem),
+ SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes),
+ SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter),
+ SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter),
+ SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp),
+ SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol),
+ SOC_ENUM_SINGLE(WM8350_INPUT_MIXER_VOLUME, 15, 2, wm8350_lr),
+};
+
+static DECLARE_TLV_DB_LINEAR(pre_amp_tlv, -1200, 3525);
+static DECLARE_TLV_DB_LINEAR(out_pga_tlv, -5700, 600);
+static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1);
+static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1);
+static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1);
+
+static const unsigned int capture_sd_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 12, TLV_DB_SCALE_ITEM(-3600, 300, 1),
+ 13, 15, TLV_DB_SCALE_ITEM(0, 0, 0),
+};
+
+static const struct snd_kcontrol_new wm8350_snd_controls[] = {
+ SOC_ENUM("Playback Deemphasis", wm8350_enum[0]),
+ SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]),
+ SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume",
+ WM8350_DAC_DIGITAL_VOLUME_L,
+ WM8350_DAC_DIGITAL_VOLUME_R,
+ 0, 255, 0, dac_pcm_tlv),
+ SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
+ SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
+ SOC_ENUM("Playback PCM Filter", wm8350_enum[4]),
+ SOC_ENUM("Capture PCM Filter", wm8350_enum[5]),
+ SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]),
+ SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]),
+ SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
+ WM8350_ADC_DIGITAL_VOLUME_L,
+ WM8350_ADC_DIGITAL_VOLUME_R,
+ 0, 255, 0, adc_pcm_tlv),
+ SOC_DOUBLE_TLV("Capture Sidetone Volume",
+ WM8350_ADC_DIVIDER,
+ 8, 4, 15, 1, capture_sd_tlv),
+ SOC_WM8350_DOUBLE_R_TLV("Capture Volume",
+ WM8350_LEFT_INPUT_VOLUME,
+ WM8350_RIGHT_INPUT_VOLUME,
+ 2, 63, 0, pre_amp_tlv),
+ SOC_DOUBLE_R("Capture ZC Switch",
+ WM8350_LEFT_INPUT_VOLUME,
+ WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0),
+ SOC_SINGLE_TLV("Left Input Left Sidetone Volume",
+ WM8350_OUTPUT_LEFT_MIXER_VOLUME, 1, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Left Input Right Sidetone Volume",
+ WM8350_OUTPUT_LEFT_MIXER_VOLUME,
+ 5, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Left Input Bypass Volume",
+ WM8350_OUTPUT_LEFT_MIXER_VOLUME,
+ 9, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Right Input Left Sidetone Volume",
+ WM8350_OUTPUT_RIGHT_MIXER_VOLUME,
+ 1, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Right Input Right Sidetone Volume",
+ WM8350_OUTPUT_RIGHT_MIXER_VOLUME,
+ 5, 7, 0, out_mix_tlv),
+ SOC_SINGLE_TLV("Right Input Bypass Volume",
+ WM8350_OUTPUT_RIGHT_MIXER_VOLUME,
+ 13, 7, 0, out_mix_tlv),
+ SOC_SINGLE("Left Input Mixer +20dB Switch",
+ WM8350_INPUT_MIXER_VOLUME_L, 0, 1, 0),
+ SOC_SINGLE("Right Input Mixer +20dB Switch",
+ WM8350_INPUT_MIXER_VOLUME_R, 0, 1, 0),
+ SOC_SINGLE_TLV("Out4 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME,
+ 1, 7, 0, out_mix_tlv),
+ SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume",
+ WM8350_LOUT1_VOLUME,
+ WM8350_ROUT1_VOLUME,
+ 2, 63, 0, out_pga_tlv),
+ SOC_DOUBLE_R("Out1 Playback ZC Switch",
+ WM8350_LOUT1_VOLUME,
+ WM8350_ROUT1_VOLUME, 13, 1, 0),
+ SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume",
+ WM8350_LOUT2_VOLUME,
+ WM8350_ROUT2_VOLUME,
+ 2, 63, 0, out_pga_tlv),
+ SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME,
+ WM8350_ROUT2_VOLUME, 13, 1, 0),
+ SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0),
+ SOC_SINGLE_TLV("Out2 Beep Volume", WM8350_BEEP_VOLUME,
+ 5, 7, 0, out_mix_tlv),
+
+ SOC_DOUBLE_R("Out1 Playback Switch",
+ WM8350_LOUT1_VOLUME,
+ WM8350_ROUT1_VOLUME,
+ 14, 1, 1),
+ SOC_DOUBLE_R("Out2 Playback Switch",
+ WM8350_LOUT2_VOLUME,
+ WM8350_ROUT2_VOLUME,
+ 14, 1, 1),
+};
+
+/*
+ * DAPM Controls
+ */
+
+/* Left Playback Mixer */
+static const struct snd_kcontrol_new wm8350_left_play_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Playback Switch",
+ WM8350_LEFT_MIXER_CONTROL, 11, 1, 0),
+ SOC_DAPM_SINGLE("Left Bypass Switch",
+ WM8350_LEFT_MIXER_CONTROL, 2, 1, 0),
+ SOC_DAPM_SINGLE("Right Playback Switch",
+ WM8350_LEFT_MIXER_CONTROL, 12, 1, 0),
+ SOC_DAPM_SINGLE("Left Sidetone Switch",
+ WM8350_LEFT_MIXER_CONTROL, 0, 1, 0),
+ SOC_DAPM_SINGLE("Right Sidetone Switch",
+ WM8350_LEFT_MIXER_CONTROL, 1, 1, 0),
+};
+
+/* Right Playback Mixer */
+static const struct snd_kcontrol_new wm8350_right_play_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Playback Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 12, 1, 0),
+ SOC_DAPM_SINGLE("Right Bypass Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 3, 1, 0),
+ SOC_DAPM_SINGLE("Left Playback Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 11, 1, 0),
+ SOC_DAPM_SINGLE("Left Sidetone Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 0, 1, 0),
+ SOC_DAPM_SINGLE("Right Sidetone Switch",
+ WM8350_RIGHT_MIXER_CONTROL, 1, 1, 0),
+};
+
+/* Out4 Mixer */
+static const struct snd_kcontrol_new wm8350_out4_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Right Playback Switch",
+ WM8350_OUT4_MIXER_CONTROL, 12, 1, 0),
+ SOC_DAPM_SINGLE("Left Playback Switch",
+ WM8350_OUT4_MIXER_CONTROL, 11, 1, 0),
+ SOC_DAPM_SINGLE("Right Capture Switch",
+ WM8350_OUT4_MIXER_CONTROL, 9, 1, 0),
+ SOC_DAPM_SINGLE("Out3 Playback Switch",
+ WM8350_OUT4_MIXER_CONTROL, 2, 1, 0),
+ SOC_DAPM_SINGLE("Right Mixer Switch",
+ WM8350_OUT4_MIXER_CONTROL, 1, 1, 0),
+ SOC_DAPM_SINGLE("Left Mixer Switch",
+ WM8350_OUT4_MIXER_CONTROL, 0, 1, 0),
+};
+
+/* Out3 Mixer */
+static const struct snd_kcontrol_new wm8350_out3_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left Playback Switch",
+ WM8350_OUT3_MIXER_CONTROL, 11, 1, 0),
+ SOC_DAPM_SINGLE("Left Capture Switch",
+ WM8350_OUT3_MIXER_CONTROL, 8, 1, 0),
+ SOC_DAPM_SINGLE("Out4 Playback Switch",
+ WM8350_OUT3_MIXER_CONTROL, 3, 1, 0),
+ SOC_DAPM_SINGLE("Left Mixer Switch",
+ WM8350_OUT3_MIXER_CONTROL, 0, 1, 0),
+};
+
+/* Left Input Mixer */
+static const struct snd_kcontrol_new wm8350_left_capt_mixer_controls[] = {
+ SOC_DAPM_SINGLE_TLV("L2 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME_L, 1, 7, 0, out_mix_tlv),
+ SOC_DAPM_SINGLE_TLV("L3 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME_L, 9, 7, 0, out_mix_tlv),
+ SOC_DAPM_SINGLE("PGA Capture Switch",
+ WM8350_LEFT_INPUT_VOLUME, 14, 1, 0),
+};
+
+/* Right Input Mixer */
+static const struct snd_kcontrol_new wm8350_right_capt_mixer_controls[] = {
+ SOC_DAPM_SINGLE_TLV("L2 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME_R, 5, 7, 0, out_mix_tlv),
+ SOC_DAPM_SINGLE_TLV("L3 Capture Volume",
+ WM8350_INPUT_MIXER_VOLUME_R, 13, 7, 0, out_mix_tlv),
+ SOC_DAPM_SINGLE("PGA Capture Switch",
+ WM8350_RIGHT_INPUT_VOLUME, 14, 1, 0),
+};
+
+/* Left Mic Mixer */
+static const struct snd_kcontrol_new wm8350_left_mic_mixer_controls[] = {
+ SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 1, 1, 0),
+ SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 0, 1, 0),
+ SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 2, 1, 0),
+};
+
+/* Right Mic Mixer */
+static const struct snd_kcontrol_new wm8350_right_mic_mixer_controls[] = {
+ SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 9, 1, 0),
+ SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 8, 1, 0),
+ SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 10, 1, 0),
+};
+
+/* Beep Switch */
+static const struct snd_kcontrol_new wm8350_beep_switch_controls =
+SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1);
+
+/* Out4 Capture Mux */
+static const struct snd_kcontrol_new wm8350_out4_capture_controls =
+SOC_DAPM_ENUM("Route", wm8350_enum[8]);
+
+static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = {
+
+ SND_SOC_DAPM_PGA("IN3R PGA", WM8350_POWER_MGMT_2, 11, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IN3L PGA", WM8350_POWER_MGMT_2, 10, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_E("Right Out2 PGA", WM8350_POWER_MGMT_3, 3, 0, NULL,
+ 0, pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_PGA_E("Left Out2 PGA", WM8350_POWER_MGMT_3, 2, 0, NULL, 0,
+ pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_PGA_E("Right Out1 PGA", WM8350_POWER_MGMT_3, 1, 0, NULL,
+ 0, pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_PGA_E("Left Out1 PGA", WM8350_POWER_MGMT_3, 0, 0, NULL, 0,
+ pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_MIXER("Right Capture Mixer", WM8350_POWER_MGMT_2,
+ 7, 0, &wm8350_right_capt_mixer_controls[0],
+ ARRAY_SIZE(wm8350_right_capt_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Left Capture Mixer", WM8350_POWER_MGMT_2,
+ 6, 0, &wm8350_left_capt_mixer_controls[0],
+ ARRAY_SIZE(wm8350_left_capt_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Out4 Mixer", WM8350_POWER_MGMT_2, 5, 0,
+ &wm8350_out4_mixer_controls[0],
+ ARRAY_SIZE(wm8350_out4_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Out3 Mixer", WM8350_POWER_MGMT_2, 4, 0,
+ &wm8350_out3_mixer_controls[0],
+ ARRAY_SIZE(wm8350_out3_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Right Playback Mixer", WM8350_POWER_MGMT_2, 1, 0,
+ &wm8350_right_play_mixer_controls[0],
+ ARRAY_SIZE(wm8350_right_play_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Left Playback Mixer", WM8350_POWER_MGMT_2, 0, 0,
+ &wm8350_left_play_mixer_controls[0],
+ ARRAY_SIZE(wm8350_left_play_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Left Mic Mixer", WM8350_POWER_MGMT_2, 8, 0,
+ &wm8350_left_mic_mixer_controls[0],
+ ARRAY_SIZE(wm8350_left_mic_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Right Mic Mixer", WM8350_POWER_MGMT_2, 9, 0,
+ &wm8350_right_mic_mixer_controls[0],
+ ARRAY_SIZE(wm8350_right_mic_mixer_controls)),
+
+ /* virtual mixer for Beep and Out2R */
+ SND_SOC_DAPM_MIXER("Out2 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SWITCH("Beep", WM8350_POWER_MGMT_3, 7, 0,
+ &wm8350_beep_switch_controls),
+
+ SND_SOC_DAPM_ADC("Right ADC", "Right Capture",
+ WM8350_POWER_MGMT_4, 3, 0),
+ SND_SOC_DAPM_ADC("Left ADC", "Left Capture",
+ WM8350_POWER_MGMT_4, 2, 0),
+ SND_SOC_DAPM_DAC("Right DAC", "Right Playback",
+ WM8350_POWER_MGMT_4, 5, 0),
+ SND_SOC_DAPM_DAC("Left DAC", "Left Playback",
+ WM8350_POWER_MGMT_4, 4, 0),
+
+ SND_SOC_DAPM_MICBIAS("Mic Bias", WM8350_POWER_MGMT_1, 4, 0),
+
+ SND_SOC_DAPM_MUX("Out4 Capture Channel", SND_SOC_NOPM, 0, 0,
+ &wm8350_out4_capture_controls),
+
+ SND_SOC_DAPM_OUTPUT("OUT1R"),
+ SND_SOC_DAPM_OUTPUT("OUT1L"),
+ SND_SOC_DAPM_OUTPUT("OUT2R"),
+ SND_SOC_DAPM_OUTPUT("OUT2L"),
+ SND_SOC_DAPM_OUTPUT("OUT3"),
+ SND_SOC_DAPM_OUTPUT("OUT4"),
+
+ SND_SOC_DAPM_INPUT("IN1RN"),
+ SND_SOC_DAPM_INPUT("IN1RP"),
+ SND_SOC_DAPM_INPUT("IN2R"),
+ SND_SOC_DAPM_INPUT("IN1LP"),
+ SND_SOC_DAPM_INPUT("IN1LN"),
+ SND_SOC_DAPM_INPUT("IN2L"),
+ SND_SOC_DAPM_INPUT("IN3R"),
+ SND_SOC_DAPM_INPUT("IN3L"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+
+ /* left playback mixer */
+ {"Left Playback Mixer", "Playback Switch", "Left DAC"},
+ {"Left Playback Mixer", "Left Bypass Switch", "IN3L PGA"},
+ {"Left Playback Mixer", "Right Playback Switch", "Right DAC"},
+ {"Left Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"},
+ {"Left Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"},
+
+ /* right playback mixer */
+ {"Right Playback Mixer", "Playback Switch", "Right DAC"},
+ {"Right Playback Mixer", "Right Bypass Switch", "IN3R PGA"},
+ {"Right Playback Mixer", "Left Playback Switch", "Left DAC"},
+ {"Right Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"},
+ {"Right Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"},
+
+ /* out4 playback mixer */
+ {"Out4 Mixer", "Right Playback Switch", "Right DAC"},
+ {"Out4 Mixer", "Left Playback Switch", "Left DAC"},
+ {"Out4 Mixer", "Right Capture Switch", "Right Capture Mixer"},
+ {"Out4 Mixer", "Out3 Playback Switch", "Out3 Mixer"},
+ {"Out4 Mixer", "Right Mixer Switch", "Right Playback Mixer"},
+ {"Out4 Mixer", "Left Mixer Switch", "Left Playback Mixer"},
+ {"OUT4", NULL, "Out4 Mixer"},
+
+ /* out3 playback mixer */
+ {"Out3 Mixer", "Left Playback Switch", "Left DAC"},
+ {"Out3 Mixer", "Left Capture Switch", "Left Capture Mixer"},
+ {"Out3 Mixer", "Left Mixer Switch", "Left Playback Mixer"},
+ {"Out3 Mixer", "Out4 Playback Switch", "Out4 Mixer"},
+ {"OUT3", NULL, "Out3 Mixer"},
+
+ /* out2 */
+ {"Right Out2 PGA", NULL, "Right Playback Mixer"},
+ {"Left Out2 PGA", NULL, "Left Playback Mixer"},
+ {"OUT2L", NULL, "Left Out2 PGA"},
+ {"OUT2R", NULL, "Right Out2 PGA"},
+
+ /* out1 */
+ {"Right Out1 PGA", NULL, "Right Playback Mixer"},
+ {"Left Out1 PGA", NULL, "Left Playback Mixer"},
+ {"OUT1L", NULL, "Left Out1 PGA"},
+ {"OUT1R", NULL, "Right Out1 PGA"},
+
+ /* ADCs */
+ {"Left ADC", NULL, "Left Capture Mixer"},
+ {"Right ADC", NULL, "Right Capture Mixer"},
+
+ /* Left capture mixer */
+ {"Left Capture Mixer", "L2 Capture Volume", "IN2L"},
+ {"Left Capture Mixer", "L3 Capture Volume", "IN3L PGA"},
+ {"Left Capture Mixer", "PGA Capture Switch", "Left Mic Mixer"},
+ {"Left Capture Mixer", NULL, "Out4 Capture Channel"},
+
+ /* Right capture mixer */
+ {"Right Capture Mixer", "L2 Capture Volume", "IN2R"},
+ {"Right Capture Mixer", "L3 Capture Volume", "IN3R PGA"},
+ {"Right Capture Mixer", "PGA Capture Switch", "Right Mic Mixer"},
+ {"Right Capture Mixer", NULL, "Out4 Capture Channel"},
+
+ /* L3 Inputs */
+ {"IN3L PGA", NULL, "IN3L"},
+ {"IN3R PGA", NULL, "IN3R"},
+
+ /* Left Mic mixer */
+ {"Left Mic Mixer", "INN Capture Switch", "IN1LN"},
+ {"Left Mic Mixer", "INP Capture Switch", "IN1LP"},
+ {"Left Mic Mixer", "IN2 Capture Switch", "IN2L"},
+
+ /* Right Mic mixer */
+ {"Right Mic Mixer", "INN Capture Switch", "IN1RN"},
+ {"Right Mic Mixer", "INP Capture Switch", "IN1RP"},
+ {"Right Mic Mixer", "IN2 Capture Switch", "IN2R"},
+
+ /* out 4 capture */
+ {"Out4 Capture Channel", NULL, "Out4 Mixer"},
+
+ /* Beep */
+ {"Beep", NULL, "IN3R PGA"},
+};
+
+static int wm8350_add_controls(struct snd_soc_codec *codec)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&wm8350_snd_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int wm8350_add_widgets(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(codec,
+ wm8350_dapm_widgets,
+ ARRAY_SIZE(wm8350_dapm_widgets));
+ if (ret != 0) {
+ dev_err(codec->dev, "dapm control register failed\n");
+ return ret;
+ }
+
+ /* set up audio paths */
+ ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+ if (ret != 0) {
+ dev_err(codec->dev, "DAPM route register failed\n");
+ return ret;
+ }
+
+ return snd_soc_dapm_new_widgets(codec);
+}
+
+static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8350 *wm8350 = codec->control_data;
+ u16 fll_4;
+
+ switch (clk_id) {
+ case WM8350_MCLK_SEL_MCLK:
+ wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_1,
+ WM8350_MCLK_SEL);
+ break;
+ case WM8350_MCLK_SEL_PLL_MCLK:
+ case WM8350_MCLK_SEL_PLL_DAC:
+ case WM8350_MCLK_SEL_PLL_ADC:
+ case WM8350_MCLK_SEL_PLL_32K:
+ wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_1,
+ WM8350_MCLK_SEL);
+ fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) &
+ ~WM8350_FLL_CLK_SRC_MASK;
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, fll_4 | clk_id);
+ break;
+ }
+
+ /* MCLK direction */
+ if (dir == WM8350_MCLK_DIR_OUT)
+ wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2,
+ WM8350_MCLK_DIR);
+ else
+ wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_2,
+ WM8350_MCLK_DIR);
+
+ return 0;
+}
+
+static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 val;
+
+ switch (div_id) {
+ case WM8350_ADC_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_ADC_DIVIDER) &
+ ~WM8350_ADC_CLKDIV_MASK;
+ wm8350_codec_write(codec, WM8350_ADC_DIVIDER, val | div);
+ break;
+ case WM8350_DAC_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_DAC_CLOCK_CONTROL) &
+ ~WM8350_DAC_CLKDIV_MASK;
+ wm8350_codec_write(codec, WM8350_DAC_CLOCK_CONTROL, val | div);
+ break;
+ case WM8350_BCLK_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
+ ~WM8350_BCLK_DIV_MASK;
+ wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
+ break;
+ case WM8350_OPCLK_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
+ ~WM8350_OPCLK_DIV_MASK;
+ wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
+ break;
+ case WM8350_SYS_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
+ ~WM8350_MCLK_DIV_MASK;
+ wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
+ break;
+ case WM8350_DACLR_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) &
+ ~WM8350_DACLRC_RATE_MASK;
+ wm8350_codec_write(codec, WM8350_DAC_LR_RATE, val | div);
+ break;
+ case WM8350_ADCLR_CLKDIV:
+ val = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) &
+ ~WM8350_ADCLRC_RATE_MASK;
+ wm8350_codec_write(codec, WM8350_ADC_LR_RATE, val | div);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
+ ~(WM8350_AIF_BCLK_INV | WM8350_AIF_LRCLK_INV | WM8350_AIF_FMT_MASK);
+ u16 master = wm8350_codec_read(codec, WM8350_AI_DAC_CONTROL) &
+ ~WM8350_BCLK_MSTR;
+ u16 dac_lrc = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) &
+ ~WM8350_DACLRC_ENA;
+ u16 adc_lrc = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) &
+ ~WM8350_ADCLRC_ENA;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ master |= WM8350_BCLK_MSTR;
+ dac_lrc |= WM8350_DACLRC_ENA;
+ adc_lrc |= WM8350_ADCLRC_ENA;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface |= 0x2 << 8;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= 0x1 << 8;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= 0x3 << 8;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ iface |= 0x3 << 8; /* lg not sure which mode */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= WM8350_AIF_LRCLK_INV | WM8350_AIF_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= WM8350_AIF_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ iface |= WM8350_AIF_LRCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
+ wm8350_codec_write(codec, WM8350_AI_DAC_CONTROL, master);
+ wm8350_codec_write(codec, WM8350_DAC_LR_RATE, dac_lrc);
+ wm8350_codec_write(codec, WM8350_ADC_LR_RATE, adc_lrc);
+ return 0;
+}
+
+static int wm8350_pcm_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int master = wm8350_codec_cache_read(codec, WM8350_AI_DAC_CONTROL) &
+ WM8350_BCLK_MSTR;
+ int enabled = 0;
+
+ /* Check that the DACs or ADCs are enabled since they are
+ * required for LRC in master mode. The DACs or ADCs need a
+ * valid audio path i.e. pin -> ADC or DAC -> pin before
+ * the LRC will be enabled in master mode. */
+ if (!master && cmd != SNDRV_PCM_TRIGGER_START)
+ return 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) &
+ (WM8350_ADCR_ENA | WM8350_ADCL_ENA);
+ } else {
+ enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) &
+ (WM8350_DACR_ENA | WM8350_DACL_ENA);
+ }
+
+ if (!enabled) {
+ dev_err(codec->dev,
+ "%s: invalid audio path - no clocks available\n",
+ __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
+ ~WM8350_AIF_WL_MASK;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface |= 0x1 << 10;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface |= 0x2 << 10;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ iface |= 0x3 << 10;
+ break;
+ }
+
+ wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
+ return 0;
+}
+
+static int wm8350_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8350 *wm8350 = codec->control_data;
+
+ if (mute)
+ wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
+ else
+ wm8350_clear_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
+ return 0;
+}
+
+/* FLL divisors */
+struct _fll_div {
+ int div; /* FLL_OUTDIV */
+ int n;
+ int k;
+ int ratio; /* FLL_FRATIO */
+};
+
+/* The size in bits of the fll divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_FLL_SIZE ((1 << 16) * 10)
+
+static inline int fll_factors(struct _fll_div *fll_div, unsigned int input,
+ unsigned int output)
+{
+ u64 Kpart;
+ unsigned int t1, t2, K, Nmod;
+
+ if (output >= 2815250 && output <= 3125000)
+ fll_div->div = 0x4;
+ else if (output >= 5625000 && output <= 6250000)
+ fll_div->div = 0x3;
+ else if (output >= 11250000 && output <= 12500000)
+ fll_div->div = 0x2;
+ else if (output >= 22500000 && output <= 25000000)
+ fll_div->div = 0x1;
+ else {
+ printk(KERN_ERR "wm8350: fll freq %d out of range\n", output);
+ return -EINVAL;
+ }
+
+ if (input > 48000)
+ fll_div->ratio = 1;
+ else
+ fll_div->ratio = 8;
+
+ t1 = output * (1 << (fll_div->div + 1));
+ t2 = input * fll_div->ratio;
+
+ fll_div->n = t1 / t2;
+ Nmod = t1 % t2;
+
+ if (Nmod) {
+ Kpart = FIXED_FLL_SIZE * (long long)Nmod;
+ do_div(Kpart, t2);
+ K = Kpart & 0xFFFFFFFF;
+
+ /* Check if we need to round */
+ if ((K % 10) >= 5)
+ K += 5;
+
+ /* Move down to proper range now rounding is done */
+ K /= 10;
+ fll_div->k = K;
+ } else
+ fll_div->k = 0;
+
+ return 0;
+}
+
+static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
+ int pll_id, unsigned int freq_in,
+ unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8350 *wm8350 = codec->control_data;
+ struct _fll_div fll_div;
+ int ret = 0;
+ u16 fll_1, fll_4;
+
+ /* power down FLL - we need to do this for reconfiguration */
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4,
+ WM8350_FLL_ENA | WM8350_FLL_OSC_ENA);
+
+ if (freq_out == 0 || freq_in == 0)
+ return ret;
+
+ ret = fll_factors(&fll_div, freq_in, freq_out);
+ if (ret < 0)
+ return ret;
+ dev_dbg(wm8350->dev,
+ "FLL in %d FLL out %d N 0x%x K 0x%x div %d ratio %d",
+ freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div,
+ fll_div.ratio);
+
+ /* set up N.K & dividers */
+ fll_1 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_1) &
+ ~(WM8350_FLL_OUTDIV_MASK | WM8350_FLL_RSP_RATE_MASK | 0xc000);
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_1,
+ fll_1 | (fll_div.div << 8) | 0x50);
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_2,
+ (fll_div.ratio << 11) | (fll_div.
+ n & WM8350_FLL_N_MASK));
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_3, fll_div.k);
+ fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) &
+ ~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF);
+ wm8350_codec_write(codec, WM8350_FLL_CONTROL_4,
+ fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) |
+ (fll_div.ratio == 8 ? WM8350_FLL_SLOW_LOCK_REF : 0));
+
+ /* power FLL on */
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA);
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA);
+
+ return 0;
+}
+
+static int wm8350_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct wm8350 *wm8350 = codec->control_data;
+ struct wm8350_data *priv = codec->private_data;
+ struct wm8350_audio_platform_data *platform =
+ wm8350->codec.platform_data;
+ u16 pm1;
+ int ret;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1 | WM8350_VMID_50K |
+ platform->codec_current_on << 14);
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1);
+ pm1 &= ~WM8350_VMID_MASK;
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1 | WM8350_VMID_50K);
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies),
+ priv->supplies);
+ if (ret != 0)
+ return ret;
+
+ /* Enable the system clock */
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4,
+ WM8350_SYSCLK_ENA);
+
+ /* mute DAC & outputs */
+ wm8350_set_bits(wm8350, WM8350_DAC_MUTE,
+ WM8350_DAC_MUTE_ENA);
+
+ /* discharge cap memory */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
+ platform->dis_out1 |
+ (platform->dis_out2 << 2) |
+ (platform->dis_out3 << 4) |
+ (platform->dis_out4 << 6));
+
+ /* wait for discharge */
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (platform->
+ cap_discharge_msecs));
+
+ /* enable antipop */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
+ (platform->vmid_s_curve << 8));
+
+ /* ramp up vmid */
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ (platform->
+ codec_current_charge << 14) |
+ WM8350_VMID_5K | WM8350_VMIDEN |
+ WM8350_VBUFEN);
+
+ /* wait for vmid */
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (platform->
+ vmid_charge_msecs));
+
+ /* turn on vmid 300k */
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK);
+ pm1 |= WM8350_VMID_300K |
+ (platform->codec_current_standby << 14);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1);
+
+
+ /* enable analogue bias */
+ pm1 |= WM8350_BIASEN;
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1);
+
+ /* disable antipop */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0);
+
+ } else {
+ /* turn on vmid 300k and reduce current */
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1 | WM8350_VMID_300K |
+ (platform->
+ codec_current_standby << 14));
+
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+
+ /* mute DAC & enable outputs */
+ wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
+
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_3,
+ WM8350_OUT1L_ENA | WM8350_OUT1R_ENA |
+ WM8350_OUT2L_ENA | WM8350_OUT2R_ENA);
+
+ /* enable anti pop S curve */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
+ (platform->vmid_s_curve << 8));
+
+ /* turn off vmid */
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~WM8350_VMIDEN;
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1);
+
+ /* wait */
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (platform->
+ vmid_discharge_msecs));
+
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
+ (platform->vmid_s_curve << 8) |
+ platform->dis_out1 |
+ (platform->dis_out2 << 2) |
+ (platform->dis_out3 << 4) |
+ (platform->dis_out4 << 6));
+
+ /* turn off VBuf and drain */
+ pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
+ ~(WM8350_VBUFEN | WM8350_VMID_MASK);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
+ pm1 | WM8350_OUTPUT_DRAIN_EN);
+
+ /* wait */
+ schedule_timeout_interruptible(msecs_to_jiffies
+ (platform->drain_msecs));
+
+ pm1 &= ~WM8350_BIASEN;
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1);
+
+ /* disable anti-pop */
+ wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0);
+
+ wm8350_clear_bits(wm8350, WM8350_LOUT1_VOLUME,
+ WM8350_OUT1L_ENA);
+ wm8350_clear_bits(wm8350, WM8350_ROUT1_VOLUME,
+ WM8350_OUT1R_ENA);
+ wm8350_clear_bits(wm8350, WM8350_LOUT2_VOLUME,
+ WM8350_OUT2L_ENA);
+ wm8350_clear_bits(wm8350, WM8350_ROUT2_VOLUME,
+ WM8350_OUT2R_ENA);
+
+ /* disable clock gen */
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4,
+ WM8350_SYSCLK_ENA);
+
+ regulator_bulk_disable(ARRAY_SIZE(priv->supplies),
+ priv->supplies);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+static int wm8350_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int wm8350_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_ON);
+
+ return 0;
+}
+
+static struct snd_soc_codec *wm8350_codec;
+
+static int wm8350_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ struct wm8350 *wm8350;
+ struct wm8350_data *priv;
+ int ret;
+ struct wm8350_output *out1;
+ struct wm8350_output *out2;
+
+ BUG_ON(!wm8350_codec);
+
+ socdev->codec = wm8350_codec;
+ codec = socdev->codec;
+ wm8350 = codec->control_data;
+ priv = codec->private_data;
+
+ /* Enable the codec */
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
+
+ /* Enable robust clocking mode in ADC */
+ wm8350_codec_write(codec, WM8350_SECURITY, 0xa7);
+ wm8350_codec_write(codec, 0xde, 0x13);
+ wm8350_codec_write(codec, WM8350_SECURITY, 0);
+
+ /* read OUT1 & OUT2 volumes */
+ out1 = &priv->out1;
+ out2 = &priv->out2;
+ out1->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME) &
+ WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
+ out1->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME) &
+ WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
+ out2->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME) &
+ WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
+ out2->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME) &
+ WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
+ wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, 0);
+ wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, 0);
+ wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, 0);
+ wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, 0);
+
+ /* Latch VU bits & mute */
+ wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME,
+ WM8350_OUT1_VU | WM8350_OUT1L_MUTE);
+ wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME,
+ WM8350_OUT2_VU | WM8350_OUT2L_MUTE);
+ wm8350_set_bits(wm8350, WM8350_ROUT1_VOLUME,
+ WM8350_OUT1_VU | WM8350_OUT1R_MUTE);
+ wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME,
+ WM8350_OUT2_VU | WM8350_OUT2R_MUTE);
+
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to create pcms\n");
+ return ret;
+ }
+
+ wm8350_add_controls(codec);
+ wm8350_add_widgets(codec);
+
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to register card\n");
+ goto card_err;
+ }
+
+ return 0;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+ return ret;
+}
+
+static int wm8350_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+ struct wm8350 *wm8350 = codec->control_data;
+ int ret;
+
+ /* cancel any work waiting to be queued. */
+ ret = cancel_delayed_work(&codec->delayed_work);
+
+ /* if there was any work waiting then we run it now and
+ * wait for its completion */
+ if (ret) {
+ schedule_delayed_work(&codec->delayed_work, 0);
+ flush_scheduled_work();
+ }
+
+ wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
+
+ return 0;
+}
+
+#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000)
+
+#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+struct snd_soc_dai wm8350_dai = {
+ .name = "WM8350",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8350_RATES,
+ .formats = WM8350_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8350_RATES,
+ .formats = WM8350_FORMATS,
+ },
+ .ops = {
+ .hw_params = wm8350_pcm_hw_params,
+ .digital_mute = wm8350_mute,
+ .trigger = wm8350_pcm_trigger,
+ .set_fmt = wm8350_set_dai_fmt,
+ .set_sysclk = wm8350_set_dai_sysclk,
+ .set_pll = wm8350_set_fll,
+ .set_clkdiv = wm8350_set_clkdiv,
+ },
+};
+EXPORT_SYMBOL_GPL(wm8350_dai);
+
+struct snd_soc_codec_device soc_codec_dev_wm8350 = {
+ .probe = wm8350_probe,
+ .remove = wm8350_remove,
+ .suspend = wm8350_suspend,
+ .resume = wm8350_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350);
+
+static int wm8350_codec_probe(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct wm8350_data *priv;
+ struct snd_soc_codec *codec;
+ int ret, i;
+
+ if (wm8350->codec.platform_data == NULL) {
+ dev_err(&pdev->dev, "No audio platform data supplied\n");
+ return -EINVAL;
+ }
+
+ priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+ priv->supplies[i].supply = supply_names[i];
+
+ ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
+ priv->supplies);
+ if (ret != 0)
+ goto err_priv;
+
+ codec = &priv->codec;
+ wm8350->codec.codec = codec;
+
+ wm8350_dai.dev = &pdev->dev;
+
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+ codec->dev = &pdev->dev;
+ codec->name = "WM8350";
+ codec->owner = THIS_MODULE;
+ codec->read = wm8350_codec_read;
+ codec->write = wm8350_codec_write;
+ codec->bias_level = SND_SOC_BIAS_OFF;
+ codec->set_bias_level = wm8350_set_bias_level;
+ codec->dai = &wm8350_dai;
+ codec->num_dai = 1;
+ codec->reg_cache_size = WM8350_MAX_REGISTER;
+ codec->private_data = priv;
+ codec->control_data = wm8350;
+
+ /* Put the codec into reset if it wasn't already */
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
+
+ INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
+ ret = snd_soc_register_codec(codec);
+ if (ret != 0)
+ goto err_supply;
+
+ wm8350_codec = codec;
+
+ ret = snd_soc_register_dai(&wm8350_dai);
+ if (ret != 0)
+ goto err_codec;
+ return 0;
+
+err_codec:
+ snd_soc_unregister_codec(codec);
+err_supply:
+ regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
+err_priv:
+ kfree(priv);
+ wm8350_codec = NULL;
+ return ret;
+}
+
+static int wm8350_codec_remove(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = wm8350->codec.codec;
+ struct wm8350_data *priv = codec->private_data;
+
+ snd_soc_unregister_dai(&wm8350_dai);
+ snd_soc_unregister_codec(codec);
+ regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
+ kfree(priv);
+ wm8350_codec = NULL;
+ return 0;
+}
+
+static struct platform_driver wm8350_codec_driver = {
+ .driver = {
+ .name = "wm8350-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8350_codec_probe,
+ .remove = __devexit_p(wm8350_codec_remove),
+};
+
+static __init int wm8350_init(void)
+{
+ return platform_driver_register(&wm8350_codec_driver);
+}
+module_init(wm8350_init);
+
+static __exit void wm8350_exit(void)
+{
+ platform_driver_unregister(&wm8350_codec_driver);
+}
+module_exit(wm8350_exit);
+
+MODULE_DESCRIPTION("ASoC WM8350 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-codec");
--- /dev/null
+/*
+ * wm8350.h - WM8903 audio codec interface
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _WM8350_H
+#define _WM8350_H
+
+#include <sound/soc.h>
+
+extern struct snd_soc_dai wm8350_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8350;
+
+#endif
}
static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
.formats = WM8510_FORMATS,},
.ops = {
.hw_params = wm8510_pcm_hw_params,
- },
- .dai_ops = {
.digital_mute = wm8510_mute,
.set_fmt = wm8510_set_dai_fmt,
.set_clkdiv = wm8510_set_dai_clkdiv,
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm8510_add_controls(codec);
wm8510_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8510: failed to register card\n");
goto card_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
+static int __init wm8510_modinit(void)
+{
+ return snd_soc_register_dai(&wm8510_dai);
+}
+module_init(wm8510_modinit);
+
+static void __exit wm8510_exit(void)
+{
+ snd_soc_unregister_dai(&wm8510_dai);
+}
+module_exit(wm8510_exit);
+
MODULE_DESCRIPTION("ASoC WM8510 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
* Set PCM DAI bit size and sample rate.
*/
static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai_link *dai = rtd->dai;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
- u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->codec_dai->id);
+ u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id);
paifb &= ~WM8580_AIF_LENGTH_MASK;
/* bit size */
return -EINVAL;
}
- wm8580_write(codec, WM8580_PAIF3 + dai->codec_dai->id, paifb);
+ wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb);
return 0;
}
},
.ops = {
.hw_params = wm8580_paif_hw_params,
- },
- .dai_ops = {
.set_fmt = wm8580_set_paif_dai_fmt,
.set_clkdiv = wm8580_set_dai_clkdiv,
.set_pll = wm8580_set_dai_pll,
},
.ops = {
.hw_params = wm8580_paif_hw_params,
- },
- .dai_ops = {
.set_fmt = wm8580_set_paif_dai_fmt,
.set_clkdiv = wm8580_set_dai_clkdiv,
.set_pll = wm8580_set_dai_pll,
wm8580_add_controls(codec);
wm8580_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8580: failed to register card\n");
goto card_err;
* low = 0x1a
* high = 0x1b
*/
-static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
-
-/* Magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
-static struct i2c_driver wm8580_i2c_driver;
-static struct i2c_client client_template;
-
-static int wm8580_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+static int wm8580_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct snd_soc_device *socdev = wm8580_socdev;
- struct wm8580_setup_data *setup = socdev->codec_data;
struct snd_soc_codec *codec = socdev->codec;
- struct i2c_client *i2c;
int ret;
- if (addr != setup->i2c_address)
- return -ENODEV;
-
- client_template.adapter = adap;
- client_template.addr = addr;
-
- i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
- return -ENOMEM;
- }
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
- ret = i2c_attach_client(i2c);
- if (ret < 0) {
- dev_err(&i2c->dev, "failed to attach codec at addr %x\n", addr);
- goto err;
- }
-
ret = wm8580_init(socdev);
- if (ret < 0) {
+ if (ret < 0)
dev_err(&i2c->dev, "failed to initialise WM8580\n");
- goto err;
- }
-
- return ret;
-
-err:
- kfree(codec);
- kfree(i2c);
return ret;
}
-static int wm8580_i2c_detach(struct i2c_client *client)
+static int wm8580_i2c_remove(struct i2c_client *client)
{
struct snd_soc_codec *codec = i2c_get_clientdata(client);
- i2c_detach_client(client);
kfree(codec->reg_cache);
- kfree(client);
return 0;
}
-static int wm8580_i2c_attach(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, wm8580_codec_probe);
-}
+static const struct i2c_device_id wm8580_i2c_id[] = {
+ { "wm8580", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
-/* corgi i2c codec control layer */
static struct i2c_driver wm8580_i2c_driver = {
.driver = {
.name = "WM8580 I2C Codec",
.owner = THIS_MODULE,
},
- .attach_adapter = wm8580_i2c_attach,
- .detach_client = wm8580_i2c_detach,
- .command = NULL,
+ .probe = wm8580_i2c_probe,
+ .remove = wm8580_i2c_remove,
+ .id_table = wm8580_i2c_id,
};
-static struct i2c_client client_template = {
- .name = "WM8580",
- .driver = &wm8580_i2c_driver,
-};
+static int wm8580_add_i2c_device(struct platform_device *pdev,
+ const struct wm8580_setup_data *setup)
+{
+ struct i2c_board_info info;
+ struct i2c_adapter *adapter;
+ struct i2c_client *client;
+ int ret;
+
+ ret = i2c_add_driver(&wm8580_i2c_driver);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "can't add i2c driver\n");
+ return ret;
+ }
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = setup->i2c_address;
+ strlcpy(info.type, "wm8580", I2C_NAME_SIZE);
+
+ adapter = i2c_get_adapter(setup->i2c_bus);
+ if (!adapter) {
+ dev_err(&pdev->dev, "can't get i2c adapter %d\n",
+ setup->i2c_bus);
+ goto err_driver;
+ }
+
+ client = i2c_new_device(adapter, &info);
+ i2c_put_adapter(adapter);
+ if (!client) {
+ dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
+ (unsigned int)info.addr);
+ goto err_driver;
+ }
+
+ return 0;
+
+err_driver:
+ i2c_del_driver(&wm8580_i2c_driver);
+ return -ENODEV;
+}
#endif
static int wm8580_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if (setup->i2c_address) {
- normal_i2c[0] = setup->i2c_address;
codec->hw_write = (hw_write_t)i2c_master_send;
- ret = i2c_add_driver(&wm8580_i2c_driver);
- if (ret != 0)
- printk(KERN_ERR "can't add i2c driver");
+ ret = wm8580_add_i2c_device(pdev, setup);
}
#else
/* Add other interfaces here */
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_unregister_device(codec->control_data);
i2c_del_driver(&wm8580_i2c_driver);
#endif
kfree(codec->private_data);
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
+static int __init wm8580_modinit(void)
+{
+ return snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
+}
+module_init(wm8580_modinit);
+
+static void __exit wm8580_exit(void)
+{
+ snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
+}
+module_exit(wm8580_exit);
+
MODULE_DESCRIPTION("ASoC WM8580 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
#define WM8580_CLKSRC_NONE 5
struct wm8580_setup_data {
+ int i2c_bus;
unsigned short i2c_address;
};
--- /dev/null
+/*
+ * wm8728.c -- WM8728 ALSA SoC Audio driver
+ *
+ * Copyright 2008 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8728.h"
+
+struct snd_soc_codec_device soc_codec_dev_wm8728;
+
+/*
+ * We can't read the WM8728 register space so we cache them instead.
+ * Note that the defaults here aren't the physical defaults, we latch
+ * the volume update bits, mute the output and enable infinite zero
+ * detect.
+ */
+static const u16 wm8728_reg_defaults[] = {
+ 0x1ff,
+ 0x1ff,
+ 0x001,
+ 0x100,
+};
+
+static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u16 *cache = codec->reg_cache;
+ BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
+ return cache[reg];
+}
+
+static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
+ u16 reg, unsigned int value)
+{
+ u16 *cache = codec->reg_cache;
+ BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
+ cache[reg] = value;
+}
+
+/*
+ * write to the WM8728 register space
+ */
+static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ u8 data[2];
+
+ /* data is
+ * D15..D9 WM8728 register offset
+ * D8...D0 register data
+ */
+ data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+ data[1] = value & 0x00ff;
+
+ wm8728_write_reg_cache(codec, reg, value);
+
+ if (codec->hw_write(codec->control_data, data, 2) == 2)
+ return 0;
+ else
+ return -EIO;
+}
+
+static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
+
+static const struct snd_kcontrol_new wm8728_snd_controls[] = {
+
+SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL,
+ 0, 255, 0, wm8728_tlv),
+
+SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0),
+};
+
+static int wm8728_add_controls(struct snd_soc_codec *codec)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&wm8728_snd_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+/*
+ * DAPM controls.
+ */
+static const struct snd_soc_dapm_widget wm8728_dapm_widgets[] = {
+SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_OUTPUT("VOUTL"),
+SND_SOC_DAPM_OUTPUT("VOUTR"),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+ {"VOUTL", NULL, "DAC"},
+ {"VOUTR", NULL, "DAC"},
+};
+
+static int wm8728_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, wm8728_dapm_widgets,
+ ARRAY_SIZE(wm8728_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+ snd_soc_dapm_new_widgets(codec);
+
+ return 0;
+}
+
+static int wm8728_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+
+ if (mute)
+ wm8728_write(codec, WM8728_DACCTL, mute_reg | 1);
+ else
+ wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1);
+
+ return 0;
+}
+
+static int wm8728_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+
+ dac &= ~0x18;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ dac |= 0x10;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ dac |= 0x08;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ wm8728_write(codec, WM8728_DACCTL, dac);
+
+ return 0;
+}
+
+static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL);
+
+ /* Currently only I2S is supported by the driver, though the
+ * hardware is more flexible.
+ */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface |= 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* The hardware only support full slave mode */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ iface &= ~0x22;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= 0x20;
+ iface &= ~0x02;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ iface |= 0x02;
+ iface &= ~0x20;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= 0x22;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ wm8728_write(codec, WM8728_IFCTL, iface);
+ return 0;
+}
+
+static int wm8728_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ u16 reg;
+ int i;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ /* Power everything up... */
+ reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+ wm8728_write(codec, WM8728_DACCTL, reg & ~0x4);
+
+ /* ..then sync in the register cache. */
+ for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++)
+ wm8728_write(codec, i,
+ wm8728_read_reg_cache(codec, i));
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+ wm8728_write(codec, WM8728_DACCTL, reg | 0x4);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+#define WM8728_RATES (SNDRV_PCM_RATE_8000_192000)
+
+#define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+struct snd_soc_dai wm8728_dai = {
+ .name = "WM8728",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM8728_RATES,
+ .formats = WM8728_FORMATS,
+ },
+ .ops = {
+ .hw_params = wm8728_hw_params,
+ .digital_mute = wm8728_mute,
+ .set_fmt = wm8728_set_dai_fmt,
+ }
+};
+EXPORT_SYMBOL_GPL(wm8728_dai);
+
+static int wm8728_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int wm8728_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ wm8728_set_bias_level(codec, codec->suspend_bias_level);
+
+ return 0;
+}
+
+/*
+ * initialise the WM8728 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int wm8728_init(struct snd_soc_device *socdev)
+{
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret = 0;
+
+ codec->name = "WM8728";
+ codec->owner = THIS_MODULE;
+ codec->read = wm8728_read_reg_cache;
+ codec->write = wm8728_write;
+ codec->set_bias_level = wm8728_set_bias_level;
+ codec->dai = &wm8728_dai;
+ codec->num_dai = 1;
+ codec->bias_level = SND_SOC_BIAS_OFF;
+ codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults);
+ codec->reg_cache = kmemdup(wm8728_reg_defaults,
+ sizeof(wm8728_reg_defaults),
+ GFP_KERNEL);
+ if (codec->reg_cache == NULL)
+ return -ENOMEM;
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ printk(KERN_ERR "wm8728: failed to create pcms\n");
+ goto pcm_err;
+ }
+
+ /* power on device */
+ wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ wm8728_add_controls(codec);
+ wm8728_add_widgets(codec);
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ printk(KERN_ERR "wm8728: failed to register card\n");
+ goto card_err;
+ }
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
+ kfree(codec->reg_cache);
+ return ret;
+}
+
+static struct snd_soc_device *wm8728_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+/*
+ * WM8728 2 wire address is determined by GPIO5
+ * state during powerup.
+ * low = 0x1a
+ * high = 0x1b
+ */
+
+static int wm8728_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct snd_soc_device *socdev = wm8728_socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret;
+
+ i2c_set_clientdata(i2c, codec);
+ codec->control_data = i2c;
+
+ ret = wm8728_init(socdev);
+ if (ret < 0)
+ pr_err("failed to initialise WM8728\n");
+
+ return ret;
+}
+
+static int wm8728_i2c_remove(struct i2c_client *client)
+{
+ struct snd_soc_codec *codec = i2c_get_clientdata(client);
+ kfree(codec->reg_cache);
+ return 0;
+}
+
+static const struct i2c_device_id wm8728_i2c_id[] = {
+ { "wm8728", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
+
+static struct i2c_driver wm8728_i2c_driver = {
+ .driver = {
+ .name = "WM8728 I2C Codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8728_i2c_probe,
+ .remove = wm8728_i2c_remove,
+ .id_table = wm8728_i2c_id,
+};
+
+static int wm8728_add_i2c_device(struct platform_device *pdev,
+ const struct wm8728_setup_data *setup)
+{
+ struct i2c_board_info info;
+ struct i2c_adapter *adapter;
+ struct i2c_client *client;
+ int ret;
+
+ ret = i2c_add_driver(&wm8728_i2c_driver);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "can't add i2c driver\n");
+ return ret;
+ }
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = setup->i2c_address;
+ strlcpy(info.type, "wm8728", I2C_NAME_SIZE);
+
+ adapter = i2c_get_adapter(setup->i2c_bus);
+ if (!adapter) {
+ dev_err(&pdev->dev, "can't get i2c adapter %d\n",
+ setup->i2c_bus);
+ goto err_driver;
+ }
+
+ client = i2c_new_device(adapter, &info);
+ i2c_put_adapter(adapter);
+ if (!client) {
+ dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
+ (unsigned int)info.addr);
+ goto err_driver;
+ }
+
+ return 0;
+
+err_driver:
+ i2c_del_driver(&wm8728_i2c_driver);
+ return -ENODEV;
+}
+#endif
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8728_spi_probe(struct spi_device *spi)
+{
+ struct snd_soc_device *socdev = wm8728_socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ int ret;
+
+ codec->control_data = spi;
+
+ ret = wm8728_init(socdev);
+ if (ret < 0)
+ dev_err(&spi->dev, "failed to initialise WM8728\n");
+
+ return ret;
+}
+
+static int __devexit wm8728_spi_remove(struct spi_device *spi)
+{
+ return 0;
+}
+
+static struct spi_driver wm8728_spi_driver = {
+ .driver = {
+ .name = "wm8728",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8728_spi_probe,
+ .remove = __devexit_p(wm8728_spi_remove),
+};
+
+static int wm8728_spi_write(struct spi_device *spi, const char *data, int len)
+{
+ struct spi_transfer t;
+ struct spi_message m;
+ u8 msg[2];
+
+ if (len <= 0)
+ return 0;
+
+ msg[0] = data[0];
+ msg[1] = data[1];
+
+ spi_message_init(&m);
+ memset(&t, 0, (sizeof t));
+
+ t.tx_buf = &msg[0];
+ t.len = len;
+
+ spi_message_add_tail(&t, &m);
+ spi_sync(spi, &m);
+
+ return len;
+}
+#endif /* CONFIG_SPI_MASTER */
+
+static int wm8728_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct wm8728_setup_data *setup;
+ struct snd_soc_codec *codec;
+ int ret = 0;
+
+ setup = socdev->codec_data;
+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (codec == NULL)
+ return -ENOMEM;
+
+ socdev->codec = codec;
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ wm8728_socdev = socdev;
+ ret = -ENODEV;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ if (setup->i2c_address) {
+ codec->hw_write = (hw_write_t)i2c_master_send;
+ ret = wm8728_add_i2c_device(pdev, setup);
+ }
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ if (setup->spi) {
+ codec->hw_write = (hw_write_t)wm8728_spi_write;
+ ret = spi_register_driver(&wm8728_spi_driver);
+ if (ret != 0)
+ printk(KERN_ERR "can't add spi driver");
+ }
+#endif
+
+ if (ret != 0)
+ kfree(codec);
+
+ return ret;
+}
+
+/* power down chip */
+static int wm8728_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+ if (codec->control_data)
+ wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_unregister_device(codec->control_data);
+ i2c_del_driver(&wm8728_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&wm8728_spi_driver);
+#endif
+ kfree(codec);
+
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8728 = {
+ .probe = wm8728_probe,
+ .remove = wm8728_remove,
+ .suspend = wm8728_suspend,
+ .resume = wm8728_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728);
+
+static int __init wm8728_modinit(void)
+{
+ return snd_soc_register_dai(&wm8728_dai);
+}
+module_init(wm8728_modinit);
+
+static void __exit wm8728_exit(void)
+{
+ snd_soc_unregister_dai(&wm8728_dai);
+}
+module_exit(wm8728_exit);
+
+MODULE_DESCRIPTION("ASoC WM8728 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * wm8728.h -- WM8728 ASoC codec driver
+ *
+ * Copyright 2008 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8728_H
+#define _WM8728_H
+
+#define WM8728_DACLVOL 0x00
+#define WM8728_DACRVOL 0x01
+#define WM8728_DACCTL 0x02
+#define WM8728_IFCTL 0x03
+
+struct wm8728_setup_data {
+ int spi;
+ int i2c_bus;
+ unsigned short i2c_address;
+};
+
+extern struct snd_soc_dai wm8728_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8728;
+
+#endif
}
static int wm8731_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
return 0;
}
-static int wm8731_pcm_prepare(struct snd_pcm_substream *substream)
+static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
return 0;
}
-static void wm8731_shutdown(struct snd_pcm_substream *substream)
+static void wm8731_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
.prepare = wm8731_pcm_prepare,
.hw_params = wm8731_hw_params,
.shutdown = wm8731_shutdown,
- },
- .dai_ops = {
.digital_mute = wm8731_mute,
.set_sysclk = wm8731_set_dai_sysclk,
.set_fmt = wm8731_set_dai_fmt,
wm8731_add_controls(codec);
wm8731_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8731: failed to register card\n");
goto card_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
+static int __init wm8731_modinit(void)
+{
+ return snd_soc_register_dai(&wm8731_dai);
+}
+module_init(wm8731_modinit);
+
+static void __exit wm8731_exit(void)
+{
+ snd_soc_unregister_dai(&wm8731_dai);
+}
+module_exit(wm8731_exit);
+
MODULE_DESCRIPTION("ASoC WM8731 driver");
MODULE_AUTHOR("Richard Purdie");
MODULE_LICENSE("GPL");
}
static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
.formats = WM8750_FORMATS,},
.ops = {
.hw_params = wm8750_pcm_hw_params,
- },
- .dai_ops = {
.digital_mute = wm8750_mute,
.set_fmt = wm8750_set_dai_fmt,
.set_sysclk = wm8750_set_dai_sysclk,
wm8750_add_controls(codec);
wm8750_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to register card\n");
goto card_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
+static int __init wm8750_modinit(void)
+{
+ return snd_soc_register_dai(&wm8750_dai);
+}
+module_init(wm8750_modinit);
+
+static void __exit wm8750_exit(void)
+{
+ snd_soc_unregister_dai(&wm8750_dai);
+}
+module_exit(wm8750_exit);
+
MODULE_DESCRIPTION("ASoC WM8750 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
* Set PCM DAI bit size and sample rate.
*/
static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
* Set PCM DAI bit size and sample rate.
*/
static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
.channels_min = 1,
.channels_max = 2,
.rates = WM8753_RATES,
- .formats = WM8753_FORMATS,},
+ .formats = WM8753_FORMATS},
.capture = { /* dummy for fast DAI switching */
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = WM8753_RATES,
- .formats = WM8753_FORMATS,},
+ .formats = WM8753_FORMATS},
.ops = {
- .hw_params = wm8753_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode1h_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_pcm_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_pcm_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode1v_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_pcm_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_pcm_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode2_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode3_4_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode3_4_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
wm8753_add_controls(codec);
wm8753_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8753: failed to register card\n");
goto card_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
+static int __init wm8753_modinit(void)
+{
+ return snd_soc_register_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
+}
+module_init(wm8753_modinit);
+
+static void __exit wm8753_exit(void)
+{
+ snd_soc_unregister_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
+}
+module_exit(wm8753_exit);
+
MODULE_DESCRIPTION("ASoC WM8753 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
struct snd_soc_codec_device soc_codec_dev_wm8900;
struct wm8900_priv {
+ struct snd_soc_codec codec;
+
+ u16 reg_cache[WM8900_MAXREG];
+
u32 fll_in; /* FLL input frequency */
u32 fll_out; /* FLL output frequency */
};
}
static int wm8900_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
},
.ops = {
.hw_params = wm8900_hw_params,
- },
- .dai_ops = {
.set_clkdiv = wm8900_set_dai_clkdiv,
.set_pll = wm8900_set_dai_pll,
.set_fmt = wm8900_set_dai_fmt,
return 0;
}
-/*
- * initialise the WM8900 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8900_init(struct snd_soc_device *socdev)
+static struct snd_soc_codec *wm8900_codec;
+
+static int wm8900_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct snd_soc_codec *codec = socdev->codec;
- int ret = 0;
+ struct wm8900_priv *wm8900;
+ struct snd_soc_codec *codec;
unsigned int reg;
- struct i2c_client *i2c_client = socdev->codec->control_data;
+ int ret;
+
+ wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
+ if (wm8900 == NULL)
+ return -ENOMEM;
+
+ codec = &wm8900->codec;
+ codec->private_data = wm8900;
+ codec->reg_cache = &wm8900->reg_cache[0];
+ codec->reg_cache_size = WM8900_MAXREG;
+
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
codec->name = "WM8900";
codec->owner = THIS_MODULE;
codec->write = wm8900_write;
codec->dai = &wm8900_dai;
codec->num_dai = 1;
- codec->reg_cache_size = WM8900_MAXREG;
- codec->reg_cache = kmemdup(wm8900_reg_defaults,
- sizeof(wm8900_reg_defaults), GFP_KERNEL);
-
- if (codec->reg_cache == NULL)
- return -ENOMEM;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+ codec->control_data = i2c;
+ codec->set_bias_level = wm8900_set_bias_level;
+ codec->dev = &i2c->dev;
reg = wm8900_read(codec, WM8900_REG_ID);
if (reg != 0x8900) {
- dev_err(&i2c_client->dev, "Device is not a WM8900 - ID %x\n",
- reg);
- return -ENODEV;
- }
-
- codec->private_data = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
- if (codec->private_data == NULL) {
- ret = -ENOMEM;
- goto priv_err;
+ dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg);
+ ret = -ENODEV;
+ goto err;
}
/* Read back from the chip */
reg = wm8900_chip_read(codec, WM8900_REG_POWER1);
reg = (reg >> 12) & 0xf;
- dev_info(&i2c_client->dev, "WM8900 revision %d\n", reg);
+ dev_info(&i2c->dev, "WM8900 revision %d\n", reg);
wm8900_reset(codec);
+ /* Turn the chip on */
+ wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
/* Latch the volume update bits */
wm8900_write(codec, WM8900_REG_LINVOL,
wm8900_read(codec, WM8900_REG_LINVOL) | 0x100);
/* Set the DAC and mixer output bias */
wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
- /* Register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "Failed to register new PCMs\n");
- goto pcm_err;
- }
-
- /* Turn the chip on */
- codec->bias_level = SND_SOC_BIAS_OFF;
- wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- wm8900_add_controls(codec);
- wm8900_add_widgets(codec);
-
- ret = snd_soc_register_card(socdev);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "Failed to register card\n");
- goto card_err;
- }
- return ret;
-
-card_err:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-pcm_err:
- kfree(codec->reg_cache);
-priv_err:
- kfree(codec->private_data);
- return ret;
-}
+ wm8900_dai.dev = &i2c->dev;
-static struct snd_soc_device *wm8900_socdev;
+ wm8900_codec = codec;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
-
-/* Magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
-
-static struct i2c_driver wm8900_i2c_driver;
-static struct i2c_client client_template;
-
-/* If the i2c layer weren't so broken, we could pass this kind of data
- around */
-static int wm8900_codec_probe(struct i2c_adapter *adap, int addr, int kind)
-{
- struct snd_soc_device *socdev = wm8900_socdev;
- struct wm8900_setup_data *setup = socdev->codec_data;
- struct snd_soc_codec *codec = socdev->codec;
- struct i2c_client *i2c;
- int ret;
-
- if (addr != setup->i2c_address)
- return -ENODEV;
-
- dev_err(&adap->dev, "Probe on %x\n", addr);
-
- client_template.adapter = adap;
- client_template.addr = addr;
-
- i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
- return -ENOMEM;
- }
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
-
- ret = i2c_attach_client(i2c);
- if (ret < 0) {
- dev_err(&adap->dev,
- "failed to attach codec at addr %x\n", addr);
+ ret = snd_soc_register_codec(codec);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
goto err;
}
- ret = wm8900_init(socdev);
- if (ret < 0) {
- dev_err(&adap->dev, "failed to initialise WM8900\n");
- goto err;
+ ret = snd_soc_register_dai(&wm8900_dai);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
+ goto err_codec;
}
+
return ret;
+err_codec:
+ snd_soc_unregister_codec(codec);
err:
- kfree(codec);
- kfree(i2c);
+ kfree(wm8900);
+ wm8900_codec = NULL;
return ret;
}
-static int wm8900_i2c_detach(struct i2c_client *client)
+static int wm8900_i2c_remove(struct i2c_client *client)
{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- i2c_detach_client(client);
- kfree(codec->reg_cache);
- kfree(client);
+ snd_soc_unregister_dai(&wm8900_dai);
+ snd_soc_unregister_codec(wm8900_codec);
+
+ wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF);
+
+ wm8900_dai.dev = NULL;
+ kfree(wm8900_codec->private_data);
+ wm8900_codec = NULL;
+
return 0;
}
-static int wm8900_i2c_attach(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, wm8900_codec_probe);
-}
+static const struct i2c_device_id wm8900_i2c_id[] = {
+ { "wm8900", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
-/* corgi i2c codec control layer */
static struct i2c_driver wm8900_i2c_driver = {
.driver = {
- .name = "WM8900 I2C codec",
+ .name = "WM8900",
.owner = THIS_MODULE,
},
- .attach_adapter = wm8900_i2c_attach,
- .detach_client = wm8900_i2c_detach,
- .command = NULL,
-};
-
-static struct i2c_client client_template = {
- .name = "WM8900",
- .driver = &wm8900_i2c_driver,
+ .probe = wm8900_i2c_probe,
+ .remove = wm8900_i2c_remove,
+ .id_table = wm8900_i2c_id,
};
-#endif
static int wm8900_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8900_setup_data *setup;
struct snd_soc_codec *codec;
int ret = 0;
- dev_info(&pdev->dev, "WM8900 Audio Codec\n");
-
- setup = socdev->codec_data;
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
+ if (!wm8900_codec) {
+ dev_err(&pdev->dev, "I2C client not yet instantiated\n");
+ return -ENODEV;
+ }
+ codec = wm8900_codec;
socdev->codec = codec;
- codec->set_bias_level = wm8900_set_bias_level;
+ /* Register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register new PCMs\n");
+ goto pcm_err;
+ }
- wm8900_socdev = socdev;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (setup->i2c_address) {
- normal_i2c[0] = setup->i2c_address;
- codec->hw_write = (hw_write_t)i2c_master_send;
- ret = i2c_add_driver(&wm8900_i2c_driver);
- if (ret != 0)
- printk(KERN_ERR "can't add i2c driver");
+ wm8900_add_controls(codec);
+ wm8900_add_widgets(codec);
+
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register card\n");
+ goto card_err;
}
-#else
-#error Non-I2C interfaces not yet supported
-#endif
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+pcm_err:
return ret;
}
static int wm8900_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- if (codec->control_data)
- wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&wm8900_i2c_driver);
-#endif
- kfree(codec);
return 0;
}
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900);
+static int __init wm8900_modinit(void)
+{
+ return i2c_add_driver(&wm8900_i2c_driver);
+}
+module_init(wm8900_modinit);
+
+static void __exit wm8900_exit(void)
+{
+ i2c_del_driver(&wm8900_i2c_driver);
+}
+module_exit(wm8900_exit);
+
MODULE_DESCRIPTION("ASoC WM8900 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>");
MODULE_LICENSE("GPL");
#define WM8900_DAC_CLKDIV_5_5 0x14
#define WM8900_DAC_CLKDIV_6 0x18
-#define WM8900_
-
-struct wm8900_setup_data {
- unsigned short i2c_address;
-};
-
extern struct snd_soc_dai wm8900_dai;
extern struct snd_soc_codec_device soc_codec_dev_wm8900;
#include "wm8903.h"
-struct wm8903_priv {
- int sysclk;
-
- /* Reference counts */
- int charge_pump_users;
- int class_w_users;
- int playback_active;
- int capture_active;
-
- struct snd_pcm_substream *master_substream;
- struct snd_pcm_substream *slave_substream;
-};
-
/* Register defaults at reset */
static u16 wm8903_reg_defaults[] = {
0x8903, /* R0 - SW Reset and ID */
0x0000, /* R172 - Analogue Output Bias 0 */
};
+struct wm8903_priv {
+ struct snd_soc_codec codec;
+ u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)];
+
+ int sysclk;
+
+ /* Reference counts */
+ int charge_pump_users;
+ int class_w_users;
+ int playback_active;
+ int capture_active;
+
+ struct snd_pcm_substream *master_substream;
+ struct snd_pcm_substream *slave_substream;
+};
+
+
static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
static void wm8903_reset(struct snd_soc_codec *codec)
{
wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0);
+ memcpy(codec->reg_cache, wm8903_reg_defaults,
+ sizeof(wm8903_reg_defaults));
}
#define WM8903_OUTPUT_SHORT 0x8
break;
default:
BUG();
+ return -EINVAL; /* Spurious warning from some compilers */
}
switch (w->shift) {
break;
default:
BUG();
+ return -EINVAL; /* Spurious warning from some compilers */
}
if (event & SND_SOC_DAPM_PRE_PMU) {
SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0),
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0),
-SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0),
+SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 0, 1, 0),
};
static const struct snd_kcontrol_new right_output_mixer[] = {
SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0),
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0),
SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0),
-SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0),
+SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 0, 1, 0),
};
static const struct snd_kcontrol_new left_speaker_mixer[] = {
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0),
SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0),
SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0,
- 1, 1, 0),
+ 0, 1, 0),
};
static const struct snd_kcontrol_new right_speaker_mixer[] = {
SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
1, 1, 0),
SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
- 1, 1, 0),
+ 0, 1, 0),
};
static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = {
case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ wm8903_write(codec, WM8903_CLOCK_RATES_2,
+ WM8903_CLK_SYS_ENA);
+
wm8903_run_sequence(codec, 0);
wm8903_sync_reg_cache(codec, codec->reg_cache);
case SND_SOC_BIAS_OFF:
wm8903_run_sequence(codec, 32);
+ reg = wm8903_read(codec, WM8903_CLOCK_RATES_2);
+ reg &= ~WM8903_CLK_SYS_ENA;
+ wm8903_write(codec, WM8903_CLOCK_RATES_2, reg);
break;
}
{ 0, 0 },
};
-static int wm8903_startup(struct snd_pcm_substream *substream)
+static int wm8903_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
return 0;
}
-static void wm8903_shutdown(struct snd_pcm_substream *substream)
+static void wm8903_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
}
static int wm8903_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
.startup = wm8903_startup,
.shutdown = wm8903_shutdown,
.hw_params = wm8903_hw_params,
- },
- .dai_ops = {
.digital_mute = wm8903_digital_mute,
.set_fmt = wm8903_set_dai_fmt,
.set_sysclk = wm8903_set_dai_sysclk
return 0;
}
-/*
- * initialise the WM8903 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8903_init(struct snd_soc_device *socdev)
+static struct snd_soc_codec *wm8903_codec;
+
+static int wm8903_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct snd_soc_codec *codec = socdev->codec;
- struct i2c_client *i2c = codec->control_data;
- int ret = 0;
+ struct wm8903_priv *wm8903;
+ struct snd_soc_codec *codec;
+ int ret;
u16 val;
- val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID);
- if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
- dev_err(&i2c->dev,
- "Device with ID register %x is not a WM8903\n", val);
- return -ENODEV;
- }
+ wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
+ if (wm8903 == NULL)
+ return -ENOMEM;
+
+ codec = &wm8903->codec;
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ codec->dev = &i2c->dev;
codec->name = "WM8903";
codec->owner = THIS_MODULE;
codec->read = wm8903_read;
codec->write = wm8903_write;
+ codec->hw_write = (hw_write_t)i2c_master_send;
codec->bias_level = SND_SOC_BIAS_OFF;
codec->set_bias_level = wm8903_set_bias_level;
codec->dai = &wm8903_dai;
codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults);
- codec->reg_cache = kmemdup(wm8903_reg_defaults,
- sizeof(wm8903_reg_defaults),
- GFP_KERNEL);
- if (codec->reg_cache == NULL) {
- dev_err(&i2c->dev, "Failed to allocate register cache\n");
- return -ENOMEM;
+ codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
+ codec->reg_cache = &wm8903->reg_cache[0];
+ codec->private_data = wm8903;
+
+ i2c_set_clientdata(i2c, codec);
+ codec->control_data = i2c;
+
+ val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID);
+ if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
+ dev_err(&i2c->dev,
+ "Device with ID register %x is not a WM8903\n", val);
+ return -ENODEV;
}
val = wm8903_read(codec, WM8903_REVISION_NUMBER);
wm8903_reset(codec);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&i2c->dev, "failed to create pcms\n");
- goto pcm_err;
- }
-
- /* SYSCLK is required for pretty much anything */
- wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA);
-
/* power on device */
wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
val |= WM8903_DAC_MUTEMODE;
wm8903_write(codec, WM8903_DAC_DIGITAL_1, val);
- wm8903_add_controls(codec);
- wm8903_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
- if (ret < 0) {
- dev_err(&i2c->dev, "wm8903: failed to register card\n");
- goto card_err;
+ wm8903_dai.dev = &i2c->dev;
+ wm8903_codec = codec;
+
+ ret = snd_soc_register_codec(codec);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+ goto err;
+ }
+
+ ret = snd_soc_register_dai(&wm8903_dai);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
+ goto err_codec;
}
return ret;
-card_err:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-pcm_err:
- kfree(codec->reg_cache);
+err_codec:
+ snd_soc_unregister_codec(codec);
+err:
+ wm8903_codec = NULL;
+ kfree(wm8903);
return ret;
}
-static struct snd_soc_device *wm8903_socdev;
-
-static int wm8903_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8903_i2c_remove(struct i2c_client *client)
{
- struct snd_soc_device *socdev = wm8903_socdev;
- struct snd_soc_codec *codec = socdev->codec;
- int ret;
+ struct snd_soc_codec *codec = i2c_get_clientdata(client);
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
+ snd_soc_unregister_dai(&wm8903_dai);
+ snd_soc_unregister_codec(codec);
- ret = wm8903_init(socdev);
- if (ret < 0)
- dev_err(&i2c->dev, "Device initialisation failed\n");
+ wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
- return ret;
-}
+ kfree(codec->private_data);
+
+ wm8903_codec = NULL;
+ wm8903_dai.dev = NULL;
-static int wm8903_i2c_remove(struct i2c_client *client)
-{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- kfree(codec->reg_cache);
return 0;
}
static int wm8903_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8903_setup_data *setup;
- struct snd_soc_codec *codec;
- struct wm8903_priv *wm8903;
- struct i2c_board_info board_info;
- struct i2c_adapter *adapter;
- struct i2c_client *i2c_client;
int ret = 0;
- setup = socdev->codec_data;
-
- if (!setup->i2c_address) {
- dev_err(&pdev->dev, "No codec address provided\n");
- return -ENODEV;
+ if (!wm8903_codec) {
+ dev_err(&pdev->dev, "I2C device not yet probed\n");
+ goto err;
}
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
+ socdev->codec = wm8903_codec;
- wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
- if (wm8903 == NULL) {
- ret = -ENOMEM;
- goto err_codec;
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to create pcms\n");
+ goto err;
}
- codec->private_data = wm8903;
- socdev->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- wm8903_socdev = socdev;
+ wm8903_add_controls(socdev->codec);
+ wm8903_add_widgets(socdev->codec);
- codec->hw_write = (hw_write_t)i2c_master_send;
- ret = i2c_add_driver(&wm8903_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- goto err_priv;
- } else {
- memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "wm8903", I2C_NAME_SIZE);
- board_info.addr = setup->i2c_address;
-
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "Can't get I2C bus %d\n",
- setup->i2c_bus);
- ret = -ENODEV;
- goto err_adapter;
- }
-
- i2c_client = i2c_new_device(adapter, &board_info);
- i2c_put_adapter(adapter);
- if (i2c_client == NULL) {
- dev_err(&pdev->dev,
- "I2C driver registration failed\n");
- ret = -ENODEV;
- goto err_adapter;
- }
+ ret = snd_soc_init_card(socdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "wm8903: failed to register card\n");
+ goto card_err;
}
return ret;
-err_adapter:
- i2c_del_driver(&wm8903_i2c_driver);
-err_priv:
- kfree(codec->private_data);
-err_codec:
- kfree(codec);
+card_err:
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+err:
return ret;
}
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
- i2c_unregister_device(socdev->codec->control_data);
- i2c_del_driver(&wm8903_i2c_driver);
- kfree(codec->private_data);
- kfree(codec);
return 0;
}
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903);
+static int __init wm8903_modinit(void)
+{
+ return i2c_add_driver(&wm8903_i2c_driver);
+}
+module_init(wm8903_modinit);
+
+static void __exit wm8903_exit(void)
+{
+ i2c_del_driver(&wm8903_i2c_driver);
+}
+module_exit(wm8903_exit);
+
MODULE_DESCRIPTION("ASoC WM8903 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>");
MODULE_LICENSE("GPL");
extern struct snd_soc_dai wm8903_dai;
extern struct snd_soc_codec_device soc_codec_dev_wm8903;
-struct wm8903_setup_data {
- int i2c_bus;
- int i2c_address;
-};
-
#define WM8903_MCLK_DIV_2 1
#define WM8903_CLK_SYS 2
#define WM8903_BCLK 3
}
static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
.formats = WM8971_FORMATS,},
.ops = {
.hw_params = wm8971_pcm_hw_params,
- },
- .dai_ops = {
.digital_mute = wm8971_mute,
.set_fmt = wm8971_set_dai_fmt,
.set_sysclk = wm8971_set_dai_sysclk,
wm8971_add_controls(codec);
wm8971_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8971: failed to register card\n");
goto card_err;
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971);
+static int __init wm8971_modinit(void)
+{
+ return snd_soc_register_dai(&wm8971_dai);
+}
+module_init(wm8971_modinit);
+
+static void __exit wm8971_exit(void)
+{
+ snd_soc_unregister_dai(&wm8971_dai);
+}
+module_exit(wm8971_exit);
+
MODULE_DESCRIPTION("ASoC WM8971 driver");
MODULE_AUTHOR("Lab126");
MODULE_LICENSE("GPL");
0x0008, /* R60 - PLL1 */
0x0031, /* R61 - PLL2 */
0x0026, /* R62 - PLL3 */
+ 0x0000, /* R63 - Driver internal */
};
/*
unsigned int reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
- BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
- /* Reset register is uncached */
- if (reg == 0)
+ /* Reset register and reserved registers are uncached */
+ if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1)
return;
cache[reg] = value;
* Set PCM DAI bit size and sample rate.
*/
static int wm8990_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
switch (level) {
case SND_SOC_BIAS_ON:
break;
+
case SND_SOC_BIAS_PREPARE:
+ /* VMID=2*50k */
+ val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
+ ~WM8990_VMID_MODE_MASK;
+ wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
break;
+
case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) {
/* Enable all output discharge bits */
/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
- } else {
- /* ON -> standby */
+ /* Enable workaround for ADC clocking issue. */
+ wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
+ wm8990_write(codec, WM8990_EXT_CTL1, 0xa003);
+ wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0);
}
+
+ /* VMID=2*250k */
+ val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
+ ~WM8990_VMID_MODE_MASK;
+ wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
break;
case SND_SOC_BIAS_OFF:
.rates = WM8990_RATES,
.formats = WM8990_FORMATS,},
.ops = {
- .hw_params = wm8990_hw_params,},
- .dai_ops = {
+ .hw_params = wm8990_hw_params,
.digital_mute = wm8990_mute,
.set_fmt = wm8990_set_dai_fmt,
.set_clkdiv = wm8990_set_dai_clkdiv,
wm8990_add_controls(codec);
wm8990_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8990: failed to register card\n");
goto card_err;
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
+static int __init wm8990_modinit(void)
+{
+ return snd_soc_register_dai(&wm8990_dai);
+}
+module_init(wm8990_modinit);
+
+static void __exit wm8990_exit(void)
+{
+ snd_soc_unregister_dai(&wm8990_dai);
+}
+module_exit(wm8990_exit);
+
MODULE_DESCRIPTION("ASoC WM8990 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
#define WM8990_PLL3 0x3E
#define WM8990_INTDRIVBITS 0x3F
-#define WM8990_REGISTER_COUNT 60
-#define WM8990_MAX_REGISTER 0x3F
+#define WM8990_EXT_ACCESS_ENA 0x75
+#define WM8990_EXT_CTL1 0x7a
/*
* Field Definitions.
return 0;
}
-static int ac97_prepare(struct snd_pcm_substream *substream)
+static int ac97_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
return ac97_write(codec, reg, runtime->rate);
}
-static int ac97_aux_prepare(struct snd_pcm_substream *substream)
+static int ac97_aux_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai wm9712_dai[] = {
{
.name = "AC97 HiFi",
- .type = SND_SOC_DAI_AC97_BUS,
+ .ac97_control = 1,
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
ret = wm9712_reset(codec, 0);
if (ret < 0) {
- printk(KERN_ERR "AC97 link error\n");
+ printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n");
goto reset_err;
}
wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm9712_add_controls(codec);
wm9712_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm9712: failed to register card\n");
goto reset_err;
}
static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
switch (params_format(params)) {
return 0;
}
-static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
+static void wm9713_voiceshutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
+ struct snd_soc_codec *codec = dai->codec;
u16 status;
/* Gracefully shut down the voice interface. */
ac97_write(codec, AC97_EXTENDED_MID, status);
}
-static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
+static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
+ struct snd_soc_codec *codec = dai->codec;
struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
int reg;
u16 vra;
return ac97_write(codec, reg, runtime->rate);
}
-static int ac97_aux_prepare(struct snd_pcm_substream *substream)
+static int ac97_aux_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
+ struct snd_soc_codec *codec = dai->codec;
struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
u16 vra, xsle;
vra = ac97_read(codec, AC97_EXTENDED_STATUS);
struct snd_soc_dai wm9713_dai[] = {
{
.name = "AC97 HiFi",
- .type = SND_SOC_DAI_AC97_BUS,
+ .ac97_control = 1,
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
.rates = WM9713_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
- .prepare = ac97_hifi_prepare,},
- .dai_ops = {
+ .prepare = ac97_hifi_prepare,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,},
},
.rates = WM9713_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
- .prepare = ac97_aux_prepare,},
- .dai_ops = {
+ .prepare = ac97_aux_prepare,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,},
},
.formats = WM9713_PCM_FORMATS,},
.ops = {
.hw_params = wm9713_pcm_hw_params,
- .shutdown = wm9713_voiceshutdown,},
- .dai_ops = {
+ .shutdown = wm9713_voiceshutdown,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,
.set_fmt = wm9713_set_dai_fmt,
}
soc_ac97_ops.reset(codec->ac97);
+ if (soc_ac97_ops.warm_reset)
+ soc_ac97_ops.warm_reset(codec->ac97);
if (ac97_read(codec, 0) != wm9713_reg[0])
return -EIO;
return 0;
wm9713_reset(codec, 0);
ret = wm9713_reset(codec, 1);
if (ret < 0) {
- printk(KERN_ERR "AC97 link error\n");
+ printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n");
goto reset_err;
}
wm9713_add_controls(codec);
wm9713_add_widgets(codec);
- ret = snd_soc_register_card(socdev);
+ ret = snd_soc_init_card(socdev);
if (ret < 0)
goto reset_err;
return 0;
snd_soc_free_ac97_codec(codec);
kfree(codec->private_data);
kfree(codec->reg_cache);
- kfree(codec->dai);
kfree(codec);
return 0;
}
help
Say Y if you want to add support for SoC audio on TI
DaVinci EVM platform.
+
+config SND_DAVINCI_SOC_SFFSDR
+ tristate "SoC Audio support for SFFSDR"
+ depends on SND_DAVINCI_SOC && MACH_DAVINCI_SFFSDR
+ select SND_DAVINCI_SOC_I2S
+ select SND_SOC_PCM3008
+ select SFFSDR_FPGA
+ help
+ Say Y if you want to add support for SoC audio on
+ Lyrtech SFFSDR board.
# DAVINCI Machine Support
snd-soc-evm-objs := davinci-evm.o
+snd-soc-sffsdr-objs := davinci-sffsdr.o
obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o
};
/* davinci-evm audio machine driver */
-static struct snd_soc_machine snd_soc_machine_evm = {
+static struct snd_soc_card snd_soc_card_evm = {
.name = "DaVinci EVM",
+ .platform = &davinci_soc_platform,
.dai_link = &evm_dai,
.num_links = 1,
};
/* evm audio subsystem */
static struct snd_soc_device evm_snd_devdata = {
- .machine = &snd_soc_machine_evm,
- .platform = &davinci_soc_platform,
+ .card = &snd_soc_card_evm,
.codec_dev = &soc_codec_dev_aic3x,
.codec_data = &evm_aic3x_setup,
};
#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1)
#define DAVINCI_MCBSP_PCR_FSRP (1 << 2)
#define DAVINCI_MCBSP_PCR_FSXP (1 << 3)
+#define DAVINCI_MCBSP_PCR_SCLKME (1 << 7)
#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8)
#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9)
#define DAVINCI_MCBSP_PCR_FSRM (1 << 10)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_platform *platform = socdev->card->platform;
u32 w;
+ int ret;
/* Start the sample generator and enable transmitter/receiver */
w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* Stop the DMA to avoid data loss */
+ /* while the transmitter is out of reset to handle XSYNCERR */
+ if (platform->pcm_ops->trigger) {
+ ret = platform->pcm_ops->trigger(substream,
+ SNDRV_PCM_TRIGGER_STOP);
+ if (ret < 0)
+ printk(KERN_DEBUG "Playback DMA stop failed\n");
+ }
+
+ /* Enable the transmitter */
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
- else
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+ /* wait for any unexpected frame sync error to occur */
+ udelay(100);
+
+ /* Disable the transmitter to clear any outstanding XSYNCERR */
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+ /* Restart the DMA */
+ if (platform->pcm_ops->trigger) {
+ ret = platform->pcm_ops->trigger(substream,
+ SNDRV_PCM_TRIGGER_START);
+ if (ret < 0)
+ printk(KERN_DEBUG "Playback DMA start failed\n");
+ }
+ /* Enable the transmitter */
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+
+ } else {
+
+ /* Enable the reciever */
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+ }
+
/* Start frame sync */
w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
}
-static int davinci_i2s_startup(struct snd_pcm_substream *substream)
+static int davinci_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG,
DAVINCI_MCBSP_SRGR_FSGM);
break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ /* McBSP CLKR pin is the input for the Sample Rate Generator.
+ * McBSP FSR and FSX are driven by the Sample Rate Generator. */
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG,
+ DAVINCI_MCBSP_PCR_SCLKME |
+ DAVINCI_MCBSP_PCR_FSXM |
+ DAVINCI_MCBSP_PCR_FSRM);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG,
+ DAVINCI_MCBSP_SRGR_FSGM);
+ break;
case SND_SOC_DAIFMT_CBM_CFM:
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 0);
break;
return -EINVAL;
}
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_RIGHT_J:
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
+ DAVINCI_MCBSP_RCR_RFRLEN1(1) |
+ DAVINCI_MCBSP_RCR_RDATDLY(0));
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
+ DAVINCI_MCBSP_XCR_XFRLEN1(1) |
+ DAVINCI_MCBSP_XCR_XDATDLY(0) |
+ DAVINCI_MCBSP_XCR_XFIG);
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ default:
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
+ DAVINCI_MCBSP_RCR_RFRLEN1(1) |
+ DAVINCI_MCBSP_RCR_RDATDLY(1));
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
+ DAVINCI_MCBSP_XCR_XFRLEN1(1) |
+ DAVINCI_MCBSP_XCR_XDATDLY(1) |
+ DAVINCI_MCBSP_XCR_XFIG);
+ break;
+ }
+
return 0;
}
static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
u32 w;
/* general line settings */
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
- DAVINCI_MCBSP_SPCR_RINTM(3) |
- DAVINCI_MCBSP_SPCR_XINTM(3) |
- DAVINCI_MCBSP_SPCR_FREE);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
- DAVINCI_MCBSP_RCR_RFRLEN1(1) |
- DAVINCI_MCBSP_RCR_RDATDLY(1));
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
- DAVINCI_MCBSP_XCR_XFRLEN1(1) |
- DAVINCI_MCBSP_XCR_XDATDLY(1) |
- DAVINCI_MCBSP_XCR_XFIG);
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+ } else {
+ w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+ }
i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
return -EINVAL;
}
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
- DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
+ DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
- DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
+ } else {
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
+ DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
+ }
return 0;
}
-static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
int ret = 0;
struct snd_soc_dai *dai)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
struct davinci_mcbsp_dev *dev;
struct resource *mem, *ioarea;
struct evm_snd_platform_data *pdata;
struct snd_soc_dai *dai)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
struct resource *mem;
struct snd_soc_dai davinci_i2s_dai = {
.name = "davinci-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.probe = davinci_i2s_probe,
.remove = davinci_i2s_remove,
.playback = {
.ops = {
.startup = davinci_i2s_startup,
.trigger = davinci_i2s_trigger,
- .hw_params = davinci_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = davinci_i2s_hw_params,
.set_fmt = davinci_i2s_set_dai_fmt,
},
};
EXPORT_SYMBOL_GPL(davinci_i2s_dai);
+static int __init davinci_i2s_init(void)
+{
+ return snd_soc_register_dai(&davinci_i2s_dai);
+}
+module_init(davinci_i2s_init);
+
+static void __exit davinci_i2s_exit(void)
+{
+ snd_soc_unregister_dai(&davinci_i2s_dai);
+}
+module_exit(davinci_i2s_exit);
+
MODULE_AUTHOR("Vladimir Barinov");
MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
MODULE_LICENSE("GPL");
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include "davinci-pcm.h"
-#define DAVINCI_PCM_DEBUG 0
-#if DAVINCI_PCM_DEBUG
-#define DPRINTK(x...) printk(KERN_DEBUG x)
-#else
-#define DPRINTK(x...)
-#endif
-
static struct snd_pcm_hardware davinci_pcm_hardware = {
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
dma_offset = prtd->period * period_size;
dma_pos = runtime->dma_addr + dma_offset;
- DPRINTK("audio_set_dma_params_play channel = %d dma_ptr = %x "
- "period_size=%x\n", lch, dma_pos, period_size);
+ pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
+ "dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size);
data_type = prtd->params->data_type;
count = period_size / data_type;
struct snd_pcm_substream *substream = data;
struct davinci_runtime_data *prtd = substream->runtime->private_data;
- DPRINTK("lch=%d, status=0x%x\n", lch, ch_status);
+ pr_debug("davinci_pcm: lch=%d, status=0x%x\n", lch, ch_status);
if (unlikely(ch_status != DMA_COMPLETE))
return;
buf->area = dma_alloc_writecombine(pcm->card->dev, size,
&buf->addr, GFP_KERNEL);
- DPRINTK("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
- (void *) buf->area, (void *) buf->addr, size);
+ pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, "
+ "size=%d\n", (void *) buf->area, (void *) buf->addr, size);
if (!buf->area)
return -ENOMEM;
};
EXPORT_SYMBOL_GPL(davinci_soc_platform);
+static int __init davinci_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&davinci_soc_platform);
+}
+module_init(davinci_soc_platform_init);
+
+static void __exit davinci_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&davinci_soc_platform);
+}
+module_exit(davinci_soc_platform_exit);
+
MODULE_AUTHOR("Vladimir Barinov");
MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * ASoC driver for Lyrtech SFFSDR board.
+ *
+ * Author: Hugo Villeneuve
+ * Copyright (C) 2008 Lyrtech inc
+ *
+ * Based on ASoC driver for TI DAVINCI EVM platform, original copyright follow:
+ * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/dma.h>
+#include <asm/plat-sffsdr/sffsdr-fpga.h>
+
+#include <mach/mcbsp.h>
+#include <mach/edma.h>
+
+#include "../codecs/pcm3008.h"
+#include "davinci-pcm.h"
+#include "davinci-i2s.h"
+
+static int sffsdr_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int fs;
+ int ret = 0;
+
+ /* Set cpu DAI configuration:
+ * CLKX and CLKR are the inputs for the Sample Rate Generator.
+ * FSX and FSR are outputs, driven by the sample Rate Generator. */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_RIGHT_J |
+ SND_SOC_DAIFMT_CBM_CFS |
+ SND_SOC_DAIFMT_IB_NF);
+ if (ret < 0)
+ return ret;
+
+ /* Fsref can be 32000, 44100 or 48000. */
+ fs = params_rate(params);
+
+ pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs);
+
+ return sffsdr_fpga_set_codec_fs(fs);
+}
+
+static struct snd_soc_ops sffsdr_ops = {
+ .hw_params = sffsdr_hw_params,
+};
+
+/* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link sffsdr_dai = {
+ .name = "PCM3008", /* Codec name */
+ .stream_name = "PCM3008 HiFi",
+ .cpu_dai = &davinci_i2s_dai,
+ .codec_dai = &pcm3008_dai,
+ .ops = &sffsdr_ops,
+};
+
+/* davinci-sffsdr audio machine driver */
+static struct snd_soc_card snd_soc_sffsdr = {
+ .name = "DaVinci SFFSDR",
+ .platform = &davinci_soc_platform,
+ .dai_link = &sffsdr_dai,
+ .num_links = 1,
+};
+
+/* sffsdr audio private data */
+static struct pcm3008_setup_data sffsdr_pcm3008_setup = {
+ .dem0_pin = GPIO(45),
+ .dem1_pin = GPIO(46),
+ .pdad_pin = GPIO(47),
+ .pdda_pin = GPIO(38),
+};
+
+/* sffsdr audio subsystem */
+static struct snd_soc_device sffsdr_snd_devdata = {
+ .card = &snd_soc_sffsdr,
+ .codec_dev = &soc_codec_dev_pcm3008,
+ .codec_data = &sffsdr_pcm3008_setup,
+};
+
+static struct resource sffsdr_snd_resources[] = {
+ {
+ .start = DAVINCI_MCBSP_BASE,
+ .end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct evm_snd_platform_data sffsdr_snd_data = {
+ .tx_dma_ch = DAVINCI_DMA_MCBSP_TX,
+ .rx_dma_ch = DAVINCI_DMA_MCBSP_RX,
+};
+
+static struct platform_device *sffsdr_snd_device;
+
+static int __init sffsdr_init(void)
+{
+ int ret;
+
+ sffsdr_snd_device = platform_device_alloc("soc-audio", 0);
+ if (!sffsdr_snd_device) {
+ printk(KERN_ERR "platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata);
+ sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev;
+ sffsdr_snd_device->dev.platform_data = &sffsdr_snd_data;
+
+ ret = platform_device_add_resources(sffsdr_snd_device,
+ sffsdr_snd_resources,
+ ARRAY_SIZE(sffsdr_snd_resources));
+ if (ret) {
+ printk(KERN_ERR "platform device add ressources failed\n");
+ goto error;
+ }
+
+ ret = platform_device_add(sffsdr_snd_device);
+ if (ret)
+ goto error;
+
+ return ret;
+
+error:
+ platform_device_put(sffsdr_snd_device);
+ return ret;
+}
+
+static void __exit sffsdr_exit(void)
+{
+ platform_device_unregister(sffsdr_snd_device);
+}
+
+module_init(sffsdr_init);
+module_exit(sffsdr_exit);
+
+MODULE_AUTHOR("Hugo Villeneuve");
+MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver");
+MODULE_LICENSE("GPL");
config SND_SOC_MPC5200_I2S
tristate "Freescale MPC5200 PSC in I2S mode driver"
+ depends on PPC_MPC52xx && PPC_BESTCOMM
select SND_SOC_OF_SIMPLE
- depends on SND_SOC && PPC_MPC52xx
+ select PPC_BESTCOMM_GEN_BD
help
Say Y here to support the MPC5200 PSCs in I2S mode.
* fsl_dma_new: initialize this PCM driver.
*
* This function is called when the codec driver calls snd_soc_new_pcms(),
- * once for each .dai_link in the machine driver's snd_soc_machine
+ * once for each .dai_link in the machine driver's snd_soc_card
* structure.
*/
static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
}
EXPORT_SYMBOL_GPL(fsl_dma_configure);
+static int __init fsl_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&fsl_soc_platform);
+}
+module_init(fsl_soc_platform_init);
+
+static void __exit fsl_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&fsl_soc_platform);
+}
+module_exit(fsl_soc_platform_exit);
+
MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module");
MODULE_LICENSE("GPL");
* If this is the first stream open, then grab the IRQ and program most of
* the SSI registers.
*/
-static int fsl_ssi_startup(struct snd_pcm_substream *substream)
+static int fsl_ssi_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
* Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
* clock master.
*/
-static int fsl_ssi_prepare(struct snd_pcm_substream *substream)
+static int fsl_ssi_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
* The DMA channel is in external master start and pause mode, which
* means the SSI completely controls the flow of data.
*/
-static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd)
+static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
*
* Shutdown the SSI if there are no other substreams open.
*/
-static void fsl_ssi_shutdown(struct snd_pcm_substream *substream)
+static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
.prepare = fsl_ssi_prepare,
.shutdown = fsl_ssi_shutdown,
.trigger = fsl_ssi_trigger,
- },
- .dai_ops = {
.set_sysclk = fsl_ssi_set_sysclk,
.set_fmt = fsl_ssi_set_fmt,
},
fsl_ssi_dai->private_data = ssi_private;
fsl_ssi_dai->name = ssi_private->name;
fsl_ssi_dai->id = ssi_info->id;
+ fsl_ssi_dai->dev = ssi_info->dev;
+
+ ret = snd_soc_register_dai(fsl_ssi_dai);
+ if (ret != 0) {
+ dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret);
+ kfree(fsl_ssi_dai);
+ return NULL;
+ }
return fsl_ssi_dai;
}
device_remove_file(ssi_private->dev, &ssi_private->dev_attr);
+ snd_soc_unregister_dai(&ssi_private->cpu_dai);
+
kfree(ssi_private);
}
EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai);
* If this is the first stream open, then grab the IRQ and program most of
* the PSC registers.
*/
-static int psc_i2s_startup(struct snd_pcm_substream *substream)
+static int psc_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
}
static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
return 0;
}
-static int psc_i2s_hw_free(struct snd_pcm_substream *substream)
+static int psc_i2s_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
* This function is called by ALSA to start, stop, pause, and resume the DMA
* transfer of data.
*/
-static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
*
* Shutdown the PSC if there are no other substreams open.
*/
-static void psc_i2s_shutdown(struct snd_pcm_substream *substream)
+static void psc_i2s_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
* psc_i2s_dai_template: template CPU Digital Audio Interface
*/
static struct snd_soc_dai psc_i2s_dai_template = {
- .type = SND_SOC_DAI_I2S,
.playback = {
.channels_min = 2,
.channels_max = 2,
.hw_free = psc_i2s_hw_free,
.shutdown = psc_i2s_shutdown,
.trigger = psc_i2s_trigger,
- },
- .dai_ops = {
.set_sysclk = psc_i2s_set_sysclk,
.set_fmt = psc_i2s_set_fmt,
},
if (rc)
dev_info(psc_i2s->dev, "error creating sysfs files\n");
+ snd_soc_register_platform(&psc_i2s_pcm_soc_platform);
+
/* Tell the ASoC OF helpers about it */
of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node,
&psc_i2s->dai);
dev_dbg(&op->dev, "psc_i2s_remove()\n");
+ snd_soc_unregister_platform(&psc_i2s_pcm_soc_platform);
+
bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task);
bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task);
struct mpc8610_hpcd_data {
struct snd_soc_device sound_devdata;
struct snd_soc_dai_link dai;
- struct snd_soc_machine machine;
+ struct snd_soc_card machine;
unsigned int dai_format;
unsigned int codec_clk_direction;
unsigned int cpu_clk_direction;
/**
* mpc8610_hpcd_machine: ASoC machine data
*/
-static struct snd_soc_machine mpc8610_hpcd_machine = {
+static struct snd_soc_card mpc8610_hpcd_machine = {
.probe = mpc8610_hpcd_machine_probe,
.remove = mpc8610_hpcd_machine_remove,
.name = "MPC8610 HPCD",
goto error;
}
- machine_data->sound_devdata.machine = &mpc8610_hpcd_machine;
+ machine_data->sound_devdata.card = &mpc8610_hpcd_machine;
machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270;
- machine_data->sound_devdata.platform = &fsl_soc_platform;
+ machine_data->machine.platform = &fsl_soc_platform;
sound_device->dev.platform_data = machine_data;
int id;
struct list_head list;
struct snd_soc_device device;
- struct snd_soc_machine machine;
+ struct snd_soc_card card;
struct snd_soc_dai_link dai_link;
struct platform_device *pdev;
struct device_node *platform_node;
/* Initialize the structure and add it to the global list */
of_soc->codec_node = codec_node;
of_soc->id = of_snd_soc_next_index++;
- of_soc->machine.dai_link = &of_soc->dai_link;
- of_soc->machine.num_links = 1;
- of_soc->device.machine = &of_soc->machine;
+ of_soc->card.dai_link = &of_soc->dai_link;
+ of_soc->card.num_links = 1;
+ of_soc->device.card = &of_soc->card;
of_soc->dai_link.ops = &of_snd_soc_ops;
list_add(&of_soc->list, &of_snd_soc_device_list);
of_soc->platform_node = node;
of_soc->dai_link.cpu_dai = cpu_dai;
- of_soc->device.platform = platform;
- of_soc->machine.name = of_soc->dai_link.cpu_dai->name;
+ of_soc->card.platform = platform;
+ of_soc->card.name = of_soc->dai_link.cpu_dai->name;
/* Now try to register the SoC device */
of_snd_soc_register_device(of_soc);
config SND_OMAP_SOC
tristate "SoC Audio for the Texas Instruments OMAP chips"
- depends on ARCH_OMAP && SND_SOC
+ depends on ARCH_OMAP
config SND_OMAP_SOC_MCBSP
tristate
select SND_SOC_TLV320AIC23
help
Say Y if you want to add support for SoC audio on osk5912.
+
+config SND_OMAP_SOC_OVERO
+ tristate "SoC Audio support for Gumstix Overo"
+ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OVERO
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on the Gumstix Overo.
+
+config SND_OMAP_SOC_OMAP2EVM
+ tristate "SoC Audio support for OMAP2EVM board"
+ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP2EVM
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on the omap2evm board.
+
+config SND_OMAP_SOC_SDP3430
+ tristate "SoC Audio support for Texas Instruments SDP3430"
+ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on Texas Instruments
+ SDP3430.
+
+config SND_OMAP_SOC_OMAP3_PANDORA
+ tristate "SoC Audio support for OMAP3 Pandora"
+ depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
+ select SND_OMAP_SOC_MCBSP
+ select SND_SOC_TWL4030
+ help
+ Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
# OMAP Machine Support
snd-soc-n810-objs := n810.o
snd-soc-osk5912-objs := osk5912.o
+snd-soc-overo-objs := overo.o
+snd-soc-omap2evm-objs := omap2evm.o
+snd-soc-sdp3430-objs := sdp3430.o
+snd-soc-omap3pandora-objs := omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
+obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
+obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
+obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
static int n810_startup(struct snd_pcm_substream *substream)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->socdev->codec;
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
+
n810_ext_control(codec);
return clk_enable(sys_clkout2);
}
};
/* Audio machine driver */
-static struct snd_soc_machine snd_soc_machine_n810 = {
+static struct snd_soc_card snd_soc_n810 = {
.name = "N810",
+ .platform = &omap_soc_platform,
.dai_link = &n810_dai,
.num_links = 1,
};
/* Audio subsystem */
static struct snd_soc_device n810_snd_devdata = {
- .machine = &snd_soc_machine_n810,
- .platform = &omap_soc_platform,
+ .card = &snd_soc_n810,
.codec_dev = &soc_codec_dev_aic3x,
.codec_data = &n810_aic33_setup,
};
#include "omap-mcbsp.h"
#include "omap-pcm.h"
-#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_44100 | \
- SNDRV_PCM_RATE_48000 | \
- SNDRV_PCM_RATE_KNOT)
+#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
struct omap_mcbsp_data {
unsigned int bus_id;
static const unsigned long omap34xx_mcbsp_port[][2] = {};
#endif
-static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
+static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
return err;
}
-static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
+static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
}
}
-static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd)
+static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
}
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
- int wlen;
+ int wlen, channels;
unsigned long port;
if (cpu_class_is_omap1()) {
return 0;
}
- switch (params_channels(params)) {
+ channels = params_channels(params);
+ switch (channels) {
case 2:
- /* Set 1 word per (McBPSP) frame and use dual-phase frames */
- regs->rcr2 |= RFRLEN2(1 - 1) | RPHASE;
+ /* Use dual-phase frames */
+ regs->rcr2 |= RPHASE;
+ regs->xcr2 |= XPHASE;
+ case 1:
+ /* Set 1 word per (McBSP) frame */
+ regs->rcr2 |= RFRLEN2(1 - 1);
regs->rcr1 |= RFRLEN1(1 - 1);
- regs->xcr2 |= XFRLEN2(1 - 1) | XPHASE;
+ regs->xcr2 |= XFRLEN2(1 - 1);
regs->xcr1 |= XFRLEN1(1 - 1);
break;
default:
regs->srgr1 |= FWID(wlen - 1);
break;
case SND_SOC_DAIFMT_DSP_A:
- regs->srgr2 |= FPER(wlen * 2 - 1);
- regs->srgr1 |= FWID(wlen * 2 - 2);
+ regs->srgr2 |= FPER(wlen * channels - 1);
+ regs->srgr1 |= FWID(wlen * channels - 2);
break;
}
#define OMAP_MCBSP_DAI_BUILDER(link_id) \
{ \
- .name = "omap-mcbsp-dai-(link_id)", \
+ .name = "omap-mcbsp-dai-"#link_id, \
.id = (link_id), \
- .type = SND_SOC_DAI_I2S, \
.playback = { \
- .channels_min = 2, \
+ .channels_min = 1, \
.channels_max = 2, \
.rates = OMAP_MCBSP_RATES, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
}, \
.capture = { \
- .channels_min = 2, \
+ .channels_min = 1, \
.channels_max = 2, \
.rates = OMAP_MCBSP_RATES, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
.shutdown = omap_mcbsp_dai_shutdown, \
.trigger = omap_mcbsp_dai_trigger, \
.hw_params = omap_mcbsp_dai_hw_params, \
- }, \
- .dai_ops = { \
.set_fmt = omap_mcbsp_dai_set_dai_fmt, \
.set_clkdiv = omap_mcbsp_dai_set_clkdiv, \
.set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \
EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
+static int __init snd_omap_mcbsp_init(void)
+{
+ return snd_soc_register_dais(omap_mcbsp_dai,
+ ARRAY_SIZE(omap_mcbsp_dai));
+}
+module_init(snd_omap_mcbsp_init);
+
+static void __exit snd_omap_mcbsp_exit(void)
+{
+ snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
+}
+module_exit(snd_omap_mcbsp_exit);
+
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
MODULE_DESCRIPTION("OMAP I2S SoC Interface");
MODULE_LICENSE("GPL");
};
EXPORT_SYMBOL_GPL(omap_soc_platform);
+static int __init omap_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&omap_soc_platform);
+}
+module_init(omap_soc_platform_init);
+
+static void __exit omap_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&omap_soc_platform);
+}
+module_exit(omap_soc_platform_exit);
+
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
MODULE_DESCRIPTION("OMAP PCM DMA module");
MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * omap2evm.c -- SoC audio machine driver for omap2evm board
+ *
+ * Author: Arun KS <arunks@mistralsolutions.com>
+ *
+ * Based on sound/soc/omap/overo.c by Steve Sakoman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+static int omap2evm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops omap2evm_ops = {
+ .hw_params = omap2evm_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap2evm_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &omap2evm_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_omap2evm = {
+ .name = "omap2evm",
+ .platform = &omap_soc_platform,
+ .dai_link = &omap2evm_dai,
+ .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device omap2evm_snd_devdata = {
+ .card = &snd_soc_omap2evm,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *omap2evm_snd_device;
+
+static int __init omap2evm_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_omap2evm()) {
+ pr_debug("Not omap2evm!\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "omap2evm SoC init\n");
+
+ omap2evm_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!omap2evm_snd_device) {
+ printk(KERN_ERR "Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata);
+ omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev;
+ *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
+ ret = platform_device_add(omap2evm_snd_device);
+ if (ret)
+ goto err1;
+
+ return 0;
+
+err1:
+ printk(KERN_ERR "Unable to add platform device\n");
+ platform_device_put(omap2evm_snd_device);
+
+ return ret;
+}
+module_init(omap2evm_soc_init);
+
+static void __exit omap2evm_soc_exit(void)
+{
+ platform_device_unregister(omap2evm_snd_device);
+}
+module_exit(omap2evm_soc_exit);
+
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_DESCRIPTION("ALSA SoC omap2evm");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * omap3beagle.c -- SoC audio for OMAP3 Beagle
+ *
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops omap3beagle_ops = {
+ .hw_params = omap3beagle_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap3beagle_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &omap3beagle_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_omap3beagle = {
+ .name = "omap3beagle",
+ .platform = &omap_soc_platform,
+ .dai_link = &omap3beagle_dai,
+ .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device omap3beagle_snd_devdata = {
+ .card = &snd_soc_omap3beagle,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *omap3beagle_snd_device;
+
+static int __init omap3beagle_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_omap3_beagle()) {
+ pr_debug("Not OMAP3 Beagle!\n");
+ return -ENODEV;
+ }
+ pr_info("OMAP3 Beagle SoC init\n");
+
+ omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!omap3beagle_snd_device) {
+ printk(KERN_ERR "Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata);
+ omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
+ *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
+ ret = platform_device_add(omap3beagle_snd_device);
+ if (ret)
+ goto err1;
+
+ return 0;
+
+err1:
+ printk(KERN_ERR "Unable to add platform device\n");
+ platform_device_put(omap3beagle_snd_device);
+
+ return ret;
+}
+
+static void __exit omap3beagle_soc_exit(void)
+{
+ platform_device_unregister(omap3beagle_snd_device);
+}
+
+module_init(omap3beagle_soc_init);
+module_exit(omap3beagle_soc_exit);
+
+MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
+MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * omap3pandora.c -- SoC audio for Pandora Handheld Console
+ *
+ * Author: Gražvydas Ignotas <notasas@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+#define OMAP3_PANDORA_DAC_POWER_GPIO 118
+#define OMAP3_PANDORA_AMP_POWER_GPIO 14
+
+#define PREFIX "ASoC omap3pandora: "
+
+static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai,
+ struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set codec system clock\n");
+ return ret;
+ }
+
+ /* Set McBSP clock to external */
+ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, 0,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set cpu system clock\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 8);
+ if (ret < 0) {
+ pr_err(PREFIX "can't set SRG clock divider\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+ return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+}
+
+static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+ return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+}
+
+static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
+ gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1);
+ } else {
+ gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
+ mdelay(1);
+ gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
+ }
+
+ return 0;
+}
+
+/*
+ * Audio paths on Pandora board:
+ *
+ * |O| ---> PCM DAC +-> AMP -> Headphone Jack
+ * |M| A +--------> Line Out
+ * |A| <~~clk~~+
+ * |P| <--- TWL4030 <--------- Line In and MICs
+ */
+static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("PCM DAC", "Playback", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM,
+ 0, 0, NULL, 0, omap3pandora_hp_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+};
+
+static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
+ SND_SOC_DAPM_MIC("Mic (external)", NULL),
+ SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_route omap3pandora_out_map[] = {
+ {"Headphone Amplifier", NULL, "PCM DAC"},
+ {"Line Out", NULL, "PCM DAC"},
+ {"Headphone Jack", NULL, "Headphone Amplifier"},
+};
+
+static const struct snd_soc_dapm_route omap3pandora_in_map[] = {
+ {"INL", NULL, "Line In"},
+ {"INR", NULL, "Line In"},
+ {"INL", NULL, "Mic (Internal)"},
+ {"INR", NULL, "Mic (external)"},
+};
+
+static int omap3pandora_out_init(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets,
+ ARRAY_SIZE(omap3pandora_out_dapm_widgets));
+ if (ret < 0)
+ return ret;
+
+ snd_soc_dapm_add_routes(codec, omap3pandora_out_map,
+ ARRAY_SIZE(omap3pandora_out_map));
+
+ return snd_soc_dapm_sync(codec);
+}
+
+static int omap3pandora_in_init(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets,
+ ARRAY_SIZE(omap3pandora_in_dapm_widgets));
+ if (ret < 0)
+ return ret;
+
+ snd_soc_dapm_add_routes(codec, omap3pandora_in_map,
+ ARRAY_SIZE(omap3pandora_in_map));
+
+ return snd_soc_dapm_sync(codec);
+}
+
+static struct snd_soc_ops omap3pandora_out_ops = {
+ .hw_params = omap3pandora_out_hw_params,
+};
+
+static struct snd_soc_ops omap3pandora_in_ops = {
+ .hw_params = omap3pandora_in_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link omap3pandora_dai[] = {
+ {
+ .name = "PCM1773",
+ .stream_name = "HiFi Out",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &omap3pandora_out_ops,
+ .init = omap3pandora_out_init,
+ }, {
+ .name = "TWL4030",
+ .stream_name = "Line/Mic In",
+ .cpu_dai = &omap_mcbsp_dai[1],
+ .codec_dai = &twl4030_dai,
+ .ops = &omap3pandora_in_ops,
+ .init = omap3pandora_in_init,
+ }
+};
+
+/* SoC card */
+static struct snd_soc_card snd_soc_card_omap3pandora = {
+ .name = "omap3pandora",
+ .platform = &omap_soc_platform,
+ .dai_link = omap3pandora_dai,
+ .num_links = ARRAY_SIZE(omap3pandora_dai),
+};
+
+/* Audio subsystem */
+static struct snd_soc_device omap3pandora_snd_data = {
+ .card = &snd_soc_card_omap3pandora,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *omap3pandora_snd_device;
+
+static int __init omap3pandora_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_omap3_pandora()) {
+ pr_debug(PREFIX "Not OMAP3 Pandora\n");
+ return -ENODEV;
+ }
+ pr_info("OMAP3 Pandora SoC init\n");
+
+ ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power");
+ if (ret) {
+ pr_err(PREFIX "Failed to get DAC power GPIO\n");
+ return ret;
+ }
+
+ ret = gpio_direction_output(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
+ if (ret) {
+ pr_err(PREFIX "Failed to set DAC power GPIO direction\n");
+ goto fail0;
+ }
+
+ ret = gpio_request(OMAP3_PANDORA_AMP_POWER_GPIO, "amp_power");
+ if (ret) {
+ pr_err(PREFIX "Failed to get amp power GPIO\n");
+ goto fail0;
+ }
+
+ ret = gpio_direction_output(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
+ if (ret) {
+ pr_err(PREFIX "Failed to set amp power GPIO direction\n");
+ goto fail1;
+ }
+
+ omap3pandora_snd_device = platform_device_alloc("soc-audio", -1);
+ if (omap3pandora_snd_device == NULL) {
+ pr_err(PREFIX "Platform device allocation failed\n");
+ ret = -ENOMEM;
+ goto fail1;
+ }
+
+ platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data);
+ omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev;
+ *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */
+ *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */
+
+ ret = platform_device_add(omap3pandora_snd_device);
+ if (ret) {
+ pr_err(PREFIX "Unable to add platform device\n");
+ goto fail2;
+ }
+
+ return 0;
+
+fail2:
+ platform_device_put(omap3pandora_snd_device);
+fail1:
+ gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
+fail0:
+ gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
+ return ret;
+}
+module_init(omap3pandora_soc_init);
+
+static void __exit omap3pandora_soc_exit(void)
+{
+ platform_device_unregister(omap3pandora_snd_device);
+ gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
+ gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
+}
+module_exit(omap3pandora_soc_exit);
+
+MODULE_AUTHOR("Grazvydas Ignotas <notasas@gmail.com>");
+MODULE_DESCRIPTION("ALSA SoC OMAP3 Pandora");
+MODULE_LICENSE("GPL");
};
/* Audio machine driver */
-static struct snd_soc_machine snd_soc_machine_osk = {
+static struct snd_soc_card snd_soc_card_osk = {
.name = "OSK5912",
+ .platform = &omap_soc_platform,
.dai_link = &osk_dai,
.num_links = 1,
};
/* Audio subsystem */
static struct snd_soc_device osk_snd_devdata = {
- .machine = &snd_soc_machine_osk,
- .platform = &omap_soc_platform,
+ .card = &snd_soc_card_osk,
.codec_dev = &soc_codec_dev_tlv320aic23,
};
--- /dev/null
+/*
+ * overo.c -- SoC audio for Gumstix Overo
+ *
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+static int overo_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops overo_ops = {
+ .hw_params = overo_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link overo_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &overo_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_card_overo = {
+ .name = "overo",
+ .platform = &omap_soc_platform,
+ .dai_link = &overo_dai,
+ .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device overo_snd_devdata = {
+ .card = &snd_soc_card_overo,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *overo_snd_device;
+
+static int __init overo_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_overo()) {
+ pr_debug("Not Overo!\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "overo SoC init\n");
+
+ overo_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!overo_snd_device) {
+ printk(KERN_ERR "Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(overo_snd_device, &overo_snd_devdata);
+ overo_snd_devdata.dev = &overo_snd_device->dev;
+ *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
+ ret = platform_device_add(overo_snd_device);
+ if (ret)
+ goto err1;
+
+ return 0;
+
+err1:
+ printk(KERN_ERR "Unable to add platform device\n");
+ platform_device_put(overo_snd_device);
+
+ return ret;
+}
+module_init(overo_soc_init);
+
+static void __exit overo_soc_exit(void)
+{
+ platform_device_unregister(overo_snd_device);
+}
+module_exit(overo_soc_exit);
+
+MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
+MODULE_DESCRIPTION("ALSA SoC overo");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * sdp3430.c -- SoC audio for TI OMAP3430 SDP
+ *
+ * Author: Misael Lopez Cruz <x0052729@ti.com>
+ *
+ * Based on:
+ * Author: Steve Sakoman <steve@sakoman.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+static int sdp3430_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret;
+
+ /* Set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec DAI configuration\n");
+ return ret;
+ }
+
+ /* Set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set cpu DAI configuration\n");
+ return ret;
+ }
+
+ /* Set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops sdp3430_ops = {
+ .hw_params = sdp3430_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link sdp3430_dai = {
+ .name = "TWL4030",
+ .stream_name = "TWL4030",
+ .cpu_dai = &omap_mcbsp_dai[0],
+ .codec_dai = &twl4030_dai,
+ .ops = &sdp3430_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_machine snd_soc_machine_sdp3430 = {
+ .name = "SDP3430",
+ .platform = &omap_soc_platform,
+ .dai_link = &sdp3430_dai,
+ .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device sdp3430_snd_devdata = {
+ .machine = &snd_soc_machine_sdp3430,
+ .codec_dev = &soc_codec_dev_twl4030,
+};
+
+static struct platform_device *sdp3430_snd_device;
+
+static int __init sdp3430_soc_init(void)
+{
+ int ret;
+
+ if (!machine_is_omap_3430sdp()) {
+ pr_debug("Not SDP3430!\n");
+ return -ENODEV;
+ }
+ printk(KERN_INFO "SDP3430 SoC init\n");
+
+ sdp3430_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!sdp3430_snd_device) {
+ printk(KERN_ERR "Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata);
+ sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev;
+ *(unsigned int *)sdp3430_dai.cpu_dai->private_data = 1; /* McBSP2 */
+
+ ret = platform_device_add(sdp3430_snd_device);
+ if (ret)
+ goto err1;
+
+ return 0;
+
+err1:
+ printk(KERN_ERR "Unable to add platform device\n");
+ platform_device_put(sdp3430_snd_device);
+
+ return ret;
+}
+module_init(sdp3430_soc_init);
+
+static void __exit sdp3430_soc_exit(void)
+{
+ platform_device_unregister(sdp3430_snd_device);
+}
+module_exit(sdp3430_soc_exit);
+
+MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC SDP3430");
+MODULE_LICENSE("GPL");
+
config SND_PXA2XX_SOC_I2S
tristate
+config SND_PXA_SOC_SSP
+ tristate
+
config SND_PXA2XX_SOC_CORGI
tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
help
Say Y if you want to add support for SoC audio on
CompuLab EM-x270.
+
+config SND_PXA2XX_SOC_PALM27X
+ bool "SoC Audio support for Palm T|X, T5 and LifeDrive"
+ depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || MACH_PALMT5)
+ select SND_PXA2XX_SOC_AC97
+ select SND_SOC_WM9712
+ help
+ Say Y if you want to add support for SoC audio on
+ Palm T|X, T5 or LifeDrive handheld computer.
+
+config SND_SOC_ZYLONITE
+ tristate "SoC Audio support for Marvell Zylonite"
+ depends on SND_PXA2XX_SOC && MACH_ZYLONITE
+ select SND_PXA2XX_SOC_AC97
+ select SND_PXA_SOC_SSP
+ select SND_SOC_WM9713
+ help
+ Say Y if you want to add support for SoC audio on the
+ Marvell Zylonite reference platform.
snd-soc-pxa2xx-objs := pxa2xx-pcm.o
snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
+snd-soc-pxa-ssp-objs := pxa-ssp.o
obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
+obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
# PXA Machine Support
snd-soc-corgi-objs := corgi.o
snd-soc-e800-objs := e800_wm9712.o
snd-soc-spitz-objs := spitz.o
snd-soc-em-x270-objs := em-x270.o
+snd-soc-palm27x-objs := palm27x.o
+snd-soc-zylonite-objs := zylonite.o
obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
+obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
+obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
}
/* we need to unmute the HP at shutdown as the mute burns power on corgi */
-static int corgi_shutdown(struct snd_pcm_substream *substream)
+static void corgi_shutdown(struct snd_pcm_substream *substream)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->socdev->codec;
-
/* set = unmute headphone */
gpio_set_value(CORGI_GPIO_MUTE_L, 1);
gpio_set_value(CORGI_GPIO_MUTE_R, 1);
- return 0;
}
static int corgi_hw_params(struct snd_pcm_substream *substream,
};
/* corgi audio machine driver */
-static struct snd_soc_machine snd_soc_machine_corgi = {
+static struct snd_soc_card snd_soc_corgi = {
.name = "Corgi",
+ .platform = &pxa2xx_soc_platform,
.dai_link = &corgi_dai,
.num_links = 1,
};
/* corgi audio subsystem */
static struct snd_soc_device corgi_snd_devdata = {
- .machine = &snd_soc_machine_corgi,
- .platform = &pxa2xx_soc_platform,
+ .card = &snd_soc_corgi,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &corgi_wm8731_setup,
};
#include "pxa2xx-pcm.h"
#include "pxa2xx-ac97.h"
-static struct snd_soc_machine e800;
+static struct snd_soc_card e800;
static struct snd_soc_dai_link e800_dai[] = {
{
},
};
-static struct snd_soc_machine e800 = {
+static struct snd_soc_card e800 = {
.name = "Toshiba e800",
+ .platform = &pxa2xx_soc_platform,
.dai_link = e800_dai,
.num_links = ARRAY_SIZE(e800_dai),
};
static struct snd_soc_device e800_snd_devdata = {
- .machine = &e800,
- .platform = &pxa2xx_soc_platform,
+ .card = &e800,
.codec_dev = &soc_codec_dev_wm9712,
};
#include <linux/moduleparam.h>
#include <linux/device.h>
-#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
},
};
-static struct snd_soc_machine em_x270 = {
+static struct snd_soc_card em_x270 = {
.name = "EM-X270",
+ .platform = &pxa2xx_soc_platform,
.dai_link = em_x270_dai,
.num_links = ARRAY_SIZE(em_x270_dai),
};
static struct snd_soc_device em_x270_snd_devdata = {
- .machine = &em_x270,
- .platform = &pxa2xx_soc_platform,
+ .card = &em_x270,
.codec_dev = &soc_codec_dev_wm9712,
};
--- /dev/null
+/*
+ * linux/sound/soc/pxa/palm27x.c
+ *
+ * SoC Audio driver for Palm T|X, T5 and LifeDrive
+ *
+ * based on tosa.c
+ *
+ * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/audio.h>
+#include <mach/palmasoc.h>
+
+#include "../codecs/wm9712.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+
+static int palm27x_jack_func = 1;
+static int palm27x_spk_func = 1;
+static int palm27x_ep_gpio = -1;
+
+static void palm27x_ext_control(struct snd_soc_codec *codec)
+{
+ if (!palm27x_spk_func)
+ snd_soc_dapm_enable_pin(codec, "Speaker");
+ else
+ snd_soc_dapm_disable_pin(codec, "Speaker");
+
+ if (!palm27x_jack_func)
+ snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+ else
+ snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+
+ snd_soc_dapm_sync(codec);
+}
+
+static int palm27x_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->socdev->codec;
+
+ /* check the jack status at stream startup */
+ palm27x_ext_control(codec);
+ return 0;
+}
+
+static struct snd_soc_ops palm27x_ops = {
+ .startup = palm27x_startup,
+};
+
+static irqreturn_t palm27x_interrupt(int irq, void *v)
+{
+ palm27x_spk_func = gpio_get_value(palm27x_ep_gpio);
+ palm27x_jack_func = !palm27x_spk_func;
+ return IRQ_HANDLED;
+}
+
+static int palm27x_get_jack(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = palm27x_jack_func;
+ return 0;
+}
+
+static int palm27x_set_jack(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (palm27x_jack_func == ucontrol->value.integer.value[0])
+ return 0;
+
+ palm27x_jack_func = ucontrol->value.integer.value[0];
+ palm27x_ext_control(codec);
+ return 1;
+}
+
+static int palm27x_get_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = palm27x_spk_func;
+ return 0;
+}
+
+static int palm27x_set_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (palm27x_spk_func == ucontrol->value.integer.value[0])
+ return 0;
+
+ palm27x_spk_func = ucontrol->value.integer.value[0];
+ palm27x_ext_control(codec);
+ return 1;
+}
+
+/* PalmTX machine dapm widgets */
+static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+/* PalmTX audio map */
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* headphone connected to HPOUTL, HPOUTR */
+ {"Headphone Jack", NULL, "HPOUTL"},
+ {"Headphone Jack", NULL, "HPOUTR"},
+
+ /* ext speaker connected to ROUT2, LOUT2 */
+ {"Speaker", NULL, "LOUT2"},
+ {"Speaker", NULL, "ROUT2"},
+};
+
+static const char *jack_function[] = {"Headphone", "Off"};
+static const char *spk_function[] = {"On", "Off"};
+static const struct soc_enum palm27x_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, jack_function),
+ SOC_ENUM_SINGLE_EXT(2, spk_function),
+};
+
+static const struct snd_kcontrol_new palm27x_controls[] = {
+ SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack,
+ palm27x_set_jack),
+ SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk,
+ palm27x_set_spk),
+};
+
+static int palm27x_ac97_init(struct snd_soc_codec *codec)
+{
+ int i, err;
+
+ snd_soc_dapm_nc_pin(codec, "OUT3");
+ snd_soc_dapm_nc_pin(codec, "MONOOUT");
+
+ /* add palm27x specific controls */
+ for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&palm27x_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ /* add palm27x specific widgets */
+ snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
+ ARRAY_SIZE(palm27x_dapm_widgets));
+
+ /* set up palm27x specific audio path audio_map */
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_sync(codec);
+ return 0;
+}
+
+static struct snd_soc_dai_link palm27x_dai[] = {
+{
+ .name = "AC97 HiFi",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+ .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+ .init = palm27x_ac97_init,
+ .ops = &palm27x_ops,
+},
+{
+ .name = "AC97 Aux",
+ .stream_name = "AC97 Aux",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+ .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
+ .ops = &palm27x_ops,
+},
+};
+
+static struct snd_soc_card palm27x_asoc = {
+ .name = "Palm/PXA27x",
+ .platform = &pxa2xx_soc_platform,
+ .dai_link = palm27x_dai,
+ .num_links = ARRAY_SIZE(palm27x_dai),
+};
+
+static struct snd_soc_device palm27x_snd_devdata = {
+ .card = &palm27x_asoc,
+ .codec_dev = &soc_codec_dev_wm9712,
+};
+
+static struct platform_device *palm27x_snd_device;
+
+static int __init palm27x_asoc_init(void)
+{
+ int ret;
+
+ if (!(machine_is_palmtx() || machine_is_palmt5() ||
+ machine_is_palmld()))
+ return -ENODEV;
+
+ ret = gpio_request(palm27x_ep_gpio, "Headphone Jack");
+ if (ret)
+ return ret;
+ ret = gpio_direction_input(palm27x_ep_gpio);
+ if (ret)
+ goto err_alloc;
+
+ if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "Headphone jack", NULL))
+ goto err_alloc;
+
+ palm27x_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!palm27x_snd_device) {
+ ret = -ENOMEM;
+ goto err_dev;
+ }
+
+ platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata);
+ palm27x_snd_devdata.dev = &palm27x_snd_device->dev;
+ ret = platform_device_add(palm27x_snd_device);
+
+ if (ret != 0)
+ goto put_device;
+
+ return 0;
+
+put_device:
+ platform_device_put(palm27x_snd_device);
+err_dev:
+ free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
+err_alloc:
+ gpio_free(palm27x_ep_gpio);
+
+ return ret;
+}
+
+static void __exit palm27x_asoc_exit(void)
+{
+ free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
+ gpio_free(palm27x_ep_gpio);
+ platform_device_unregister(palm27x_snd_device);
+}
+
+void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data)
+{
+ palm27x_ep_gpio = data->jack_gpio;
+}
+
+module_init(palm27x_asoc_init);
+module_exit(palm27x_asoc_exit);
+
+/* Module information */
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive");
+MODULE_LICENSE("GPL");
};
/* poodle audio machine driver */
-static struct snd_soc_machine snd_soc_machine_poodle = {
+static struct snd_soc_card snd_soc_poodle = {
.name = "Poodle",
+ .platform = &pxa2xx_soc_platform,
.dai_link = &poodle_dai,
.num_links = 1,
};
/* poodle audio subsystem */
static struct snd_soc_device poodle_snd_devdata = {
- .machine = &snd_soc_machine_poodle,
- .platform = &pxa2xx_soc_platform,
+ .card = &snd_soc_poodle,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &poodle_wm8731_setup,
};
--- /dev/null
+#define DEBUG
+/*
+ * pxa-ssp.c -- ALSA Soc Audio Layer
+ *
+ * Copyright 2005,2008 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ * Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * TODO:
+ * o Test network mode for > 16bit sample size
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/pxa2xx-lib.h>
+
+#include <mach/hardware.h>
+#include <mach/pxa-regs.h>
+#include <mach/regs-ssp.h>
+#include <mach/audio.h>
+#include <mach/ssp.h>
+
+#include "pxa2xx-pcm.h"
+#include "pxa-ssp.h"
+
+/*
+ * SSP audio private data
+ */
+struct ssp_priv {
+ struct ssp_dev dev;
+ unsigned int sysclk;
+ int dai_fmt;
+#ifdef CONFIG_PM
+ struct ssp_state state;
+#endif
+};
+
+#define PXA2xx_SSP1_BASE 0x41000000
+#define PXA27x_SSP2_BASE 0x41700000
+#define PXA27x_SSP3_BASE 0x41900000
+#define PXA3xx_SSP4_BASE 0x41a00000
+
+static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_out = {
+ .name = "SSP1 PCM Mono out",
+ .dev_addr = PXA2xx_SSP1_BASE + SSDR,
+ .drcmr = &DRCMR(14),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_in = {
+ .name = "SSP1 PCM Mono in",
+ .dev_addr = PXA2xx_SSP1_BASE + SSDR,
+ .drcmr = &DRCMR(13),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_out = {
+ .name = "SSP1 PCM Stereo out",
+ .dev_addr = PXA2xx_SSP1_BASE + SSDR,
+ .drcmr = &DRCMR(14),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_in = {
+ .name = "SSP1 PCM Stereo in",
+ .dev_addr = PXA2xx_SSP1_BASE + SSDR,
+ .drcmr = &DRCMR(13),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_out = {
+ .name = "SSP2 PCM Mono out",
+ .dev_addr = PXA27x_SSP2_BASE + SSDR,
+ .drcmr = &DRCMR(16),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_in = {
+ .name = "SSP2 PCM Mono in",
+ .dev_addr = PXA27x_SSP2_BASE + SSDR,
+ .drcmr = &DRCMR(15),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_out = {
+ .name = "SSP2 PCM Stereo out",
+ .dev_addr = PXA27x_SSP2_BASE + SSDR,
+ .drcmr = &DRCMR(16),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_in = {
+ .name = "SSP2 PCM Stereo in",
+ .dev_addr = PXA27x_SSP2_BASE + SSDR,
+ .drcmr = &DRCMR(15),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_out = {
+ .name = "SSP3 PCM Mono out",
+ .dev_addr = PXA27x_SSP3_BASE + SSDR,
+ .drcmr = &DRCMR(67),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_in = {
+ .name = "SSP3 PCM Mono in",
+ .dev_addr = PXA27x_SSP3_BASE + SSDR,
+ .drcmr = &DRCMR(66),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_out = {
+ .name = "SSP3 PCM Stereo out",
+ .dev_addr = PXA27x_SSP3_BASE + SSDR,
+ .drcmr = &DRCMR(67),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_in = {
+ .name = "SSP3 PCM Stereo in",
+ .dev_addr = PXA27x_SSP3_BASE + SSDR,
+ .drcmr = &DRCMR(66),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_out = {
+ .name = "SSP4 PCM Mono out",
+ .dev_addr = PXA3xx_SSP4_BASE + SSDR,
+ .drcmr = &DRCMR(67),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_in = {
+ .name = "SSP4 PCM Mono in",
+ .dev_addr = PXA3xx_SSP4_BASE + SSDR,
+ .drcmr = &DRCMR(66),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH2,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_out = {
+ .name = "SSP4 PCM Stereo out",
+ .dev_addr = PXA3xx_SSP4_BASE + SSDR,
+ .drcmr = &DRCMR(67),
+ .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_in = {
+ .name = "SSP4 PCM Stereo in",
+ .dev_addr = PXA3xx_SSP4_BASE + SSDR,
+ .drcmr = &DRCMR(66),
+ .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
+ DCMD_BURST16 | DCMD_WIDTH4,
+};
+
+static void dump_registers(struct ssp_device *ssp)
+{
+ dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n",
+ ssp_read_reg(ssp, SSCR0), ssp_read_reg(ssp, SSCR1),
+ ssp_read_reg(ssp, SSTO));
+
+ dev_dbg(&ssp->pdev->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n",
+ ssp_read_reg(ssp, SSPSP), ssp_read_reg(ssp, SSSR),
+ ssp_read_reg(ssp, SSACD));
+}
+
+static struct pxa2xx_pcm_dma_params *ssp_dma_params[4][4] = {
+ {
+ &pxa_ssp1_pcm_mono_out, &pxa_ssp1_pcm_mono_in,
+ &pxa_ssp1_pcm_stereo_out, &pxa_ssp1_pcm_stereo_in,
+ },
+ {
+ &pxa_ssp2_pcm_mono_out, &pxa_ssp2_pcm_mono_in,
+ &pxa_ssp2_pcm_stereo_out, &pxa_ssp2_pcm_stereo_in,
+ },
+ {
+ &pxa_ssp3_pcm_mono_out, &pxa_ssp3_pcm_mono_in,
+ &pxa_ssp3_pcm_stereo_out, &pxa_ssp3_pcm_stereo_in,
+ },
+ {
+ &pxa_ssp4_pcm_mono_out, &pxa_ssp4_pcm_mono_in,
+ &pxa_ssp4_pcm_stereo_out, &pxa_ssp4_pcm_stereo_in,
+ },
+};
+
+static int pxa_ssp_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct ssp_priv *priv = cpu_dai->private_data;
+ int ret = 0;
+
+ if (!cpu_dai->active) {
+ ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ);
+ if (ret < 0)
+ return ret;
+ ssp_disable(&priv->dev);
+ }
+ return ret;
+}
+
+static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct ssp_priv *priv = cpu_dai->private_data;
+
+ if (!cpu_dai->active) {
+ ssp_disable(&priv->dev);
+ ssp_exit(&priv->dev);
+ }
+}
+
+#ifdef CONFIG_PM
+
+static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ ssp_save_state(&priv->dev, &priv->state);
+ clk_disable(priv->dev.ssp->clk);
+ return 0;
+}
+
+static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ clk_enable(priv->dev.ssp->clk);
+ ssp_restore_state(&priv->dev, &priv->state);
+ ssp_enable(&priv->dev);
+
+ return 0;
+}
+
+#else
+#define pxa_ssp_suspend NULL
+#define pxa_ssp_resume NULL
+#endif
+
+/**
+ * ssp_set_clkdiv - set SSP clock divider
+ * @div: serial clock rate divider
+ */
+static void ssp_set_scr(struct ssp_dev *dev, u32 div)
+{
+ struct ssp_device *ssp = dev->ssp;
+ u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
+
+ ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
+}
+
+/*
+ * Set the SSP ports SYSCLK.
+ */
+static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ int val;
+
+ u32 sscr0 = ssp_read_reg(ssp, SSCR0) &
+ ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
+
+ dev_dbg(&ssp->pdev->dev,
+ "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n",
+ cpu_dai->id, clk_id, freq);
+
+ switch (clk_id) {
+ case PXA_SSP_CLK_NET_PLL:
+ sscr0 |= SSCR0_MOD;
+ break;
+ case PXA_SSP_CLK_PLL:
+ /* Internal PLL is fixed */
+ if (cpu_is_pxa25x())
+ priv->sysclk = 1843200;
+ else
+ priv->sysclk = 13000000;
+ break;
+ case PXA_SSP_CLK_EXT:
+ priv->sysclk = freq;
+ sscr0 |= SSCR0_ECS;
+ break;
+ case PXA_SSP_CLK_NET:
+ priv->sysclk = freq;
+ sscr0 |= SSCR0_NCS | SSCR0_MOD;
+ break;
+ case PXA_SSP_CLK_AUDIO:
+ priv->sysclk = 0;
+ ssp_set_scr(&priv->dev, 1);
+ sscr0 |= SSCR0_ADC;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ /* The SSP clock must be disabled when changing SSP clock mode
+ * on PXA2xx. On PXA3xx it must be enabled when doing so. */
+ if (!cpu_is_pxa3xx())
+ clk_disable(priv->dev.ssp->clk);
+ val = ssp_read_reg(ssp, SSCR0) | sscr0;
+ ssp_write_reg(ssp, SSCR0, val);
+ if (!cpu_is_pxa3xx())
+ clk_enable(priv->dev.ssp->clk);
+
+ return 0;
+}
+
+/*
+ * Set the SSP clock dividers.
+ */
+static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
+ int div_id, int div)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ int val;
+
+ switch (div_id) {
+ case PXA_SSP_AUDIO_DIV_ACDS:
+ val = (ssp_read_reg(ssp, SSACD) & ~0x7) | SSACD_ACDS(div);
+ ssp_write_reg(ssp, SSACD, val);
+ break;
+ case PXA_SSP_AUDIO_DIV_SCDB:
+ val = ssp_read_reg(ssp, SSACD);
+ val &= ~SSACD_SCDB;
+#if defined(CONFIG_PXA3xx)
+ if (cpu_is_pxa3xx())
+ val &= ~SSACD_SCDX8;
+#endif
+ switch (div) {
+ case PXA_SSP_CLK_SCDB_1:
+ val |= SSACD_SCDB;
+ break;
+ case PXA_SSP_CLK_SCDB_4:
+ break;
+#if defined(CONFIG_PXA3xx)
+ case PXA_SSP_CLK_SCDB_8:
+ if (cpu_is_pxa3xx())
+ val |= SSACD_SCDX8;
+ else
+ return -EINVAL;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+ ssp_write_reg(ssp, SSACD, val);
+ break;
+ case PXA_SSP_DIV_SCR:
+ ssp_set_scr(&priv->dev, div);
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/*
+ * Configure the PLL frequency pxa27x and (afaik - pxa320 only)
+ */
+static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70;
+
+#if defined(CONFIG_PXA3xx)
+ if (cpu_is_pxa3xx())
+ ssp_write_reg(ssp, SSACDD, 0);
+#endif
+
+ switch (freq_out) {
+ case 5622000:
+ break;
+ case 11345000:
+ ssacd |= (0x1 << 4);
+ break;
+ case 12235000:
+ ssacd |= (0x2 << 4);
+ break;
+ case 14857000:
+ ssacd |= (0x3 << 4);
+ break;
+ case 32842000:
+ ssacd |= (0x4 << 4);
+ break;
+ case 48000000:
+ ssacd |= (0x5 << 4);
+ break;
+ case 0:
+ /* Disable */
+ break;
+
+ default:
+#ifdef CONFIG_PXA3xx
+ /* PXA3xx has a clock ditherer which can be used to generate
+ * a wider range of frequencies - calculate a value for it.
+ */
+ if (cpu_is_pxa3xx()) {
+ u32 val;
+ u64 tmp = 19968;
+ tmp *= 1000000;
+ do_div(tmp, freq_out);
+ val = tmp;
+
+ val = (val << 16) | 64;;
+ ssp_write_reg(ssp, SSACDD, val);
+
+ ssacd |= (0x6 << 4);
+
+ dev_dbg(&ssp->pdev->dev,
+ "Using SSACDD %x to supply %dHz\n",
+ val, freq_out);
+ break;
+ }
+#endif
+
+ return -EINVAL;
+ }
+
+ ssp_write_reg(ssp, SSACD, ssacd);
+
+ return 0;
+}
+
+/*
+ * Set the active slots in TDM/Network mode
+ */
+static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
+ unsigned int mask, int slots)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ u32 sscr0;
+
+ sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7);
+
+ /* set number of active slots */
+ sscr0 |= SSCR0_SlotsPerFrm(slots);
+ ssp_write_reg(ssp, SSCR0, sscr0);
+
+ /* set active slot mask */
+ ssp_write_reg(ssp, SSTSA, mask);
+ ssp_write_reg(ssp, SSRSA, mask);
+ return 0;
+}
+
+/*
+ * Tristate the SSP DAI lines
+ */
+static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
+ int tristate)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ u32 sscr1;
+
+ sscr1 = ssp_read_reg(ssp, SSCR1);
+ if (tristate)
+ sscr1 &= ~SSCR1_TTE;
+ else
+ sscr1 |= SSCR1_TTE;
+ ssp_write_reg(ssp, SSCR1, sscr1);
+
+ return 0;
+}
+
+/*
+ * Set up the SSP DAI format.
+ * The SSP Port must be inactive before calling this function as the
+ * physical interface format is changed.
+ */
+static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ u32 sscr0;
+ u32 sscr1;
+ u32 sspsp;
+
+ /* reset port settings */
+ sscr0 = ssp_read_reg(ssp, SSCR0) &
+ (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
+ sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
+ sspsp = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ sscr1 |= SSCR1_SCLKDIR;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ssp_write_reg(ssp, SSCR0, sscr0);
+ ssp_write_reg(ssp, SSCR1, sscr1);
+ ssp_write_reg(ssp, SSPSP, sspsp);
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ sscr0 |= SSCR0_MOD | SSCR0_PSP;
+ sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ sspsp |= SSPSP_FSRT;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ sspsp |= SSPSP_SFRMP | SSPSP_FSRT;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ sspsp |= SSPSP_SFRMP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ case SND_SOC_DAIFMT_DSP_A:
+ sspsp |= SSPSP_FSRT;
+ case SND_SOC_DAIFMT_DSP_B:
+ sscr0 |= SSCR0_MOD | SSCR0_PSP;
+ sscr1 |= SSCR1_TRAIL | SSCR1_RWOT;
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ sspsp |= SSPSP_SFRMP;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ ssp_write_reg(ssp, SSCR0, sscr0);
+ ssp_write_reg(ssp, SSCR1, sscr1);
+ ssp_write_reg(ssp, SSPSP, sspsp);
+
+ dump_registers(ssp);
+
+ /* Since we are configuring the timings for the format by hand
+ * we have to defer some things until hw_params() where we
+ * know parameters like the sample size.
+ */
+ priv->dai_fmt = fmt;
+
+ return 0;
+}
+
+/*
+ * Set the SSP audio DMA parameters and sample size.
+ * Can be called multiple times by oss emulation.
+ */
+static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ int dma = 0, chn = params_channels(params);
+ u32 sscr0;
+ u32 sspsp;
+ int width = snd_pcm_format_physical_width(params_format(params));
+
+ /* select correct DMA params */
+ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+ dma = 1; /* capture DMA offset is 1,3 */
+ if (chn == 2)
+ dma += 2; /* stereo DMA offset is 2, mono is 0 */
+ cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
+
+ dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma);
+
+ /* we can only change the settings if the port is not in use */
+ if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
+ return 0;
+
+ /* clear selected SSP bits */
+ sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
+ ssp_write_reg(ssp, SSCR0, sscr0);
+
+ /* bit size */
+ sscr0 = ssp_read_reg(ssp, SSCR0);
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+#ifdef CONFIG_PXA3xx
+ if (cpu_is_pxa3xx())
+ sscr0 |= SSCR0_FPCKE;
+#endif
+ sscr0 |= SSCR0_DataSize(16);
+ if (params_channels(params) > 1)
+ sscr0 |= SSCR0_EDSS;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
+ /* we must be in network mode (2 slots) for 24 bit stereo */
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
+ /* we must be in network mode (2 slots) for 32 bit stereo */
+ break;
+ }
+ ssp_write_reg(ssp, SSCR0, sscr0);
+
+ switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ /* Cleared when the DAI format is set */
+ sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width);
+ ssp_write_reg(ssp, SSPSP, sspsp);
+ break;
+ default:
+ break;
+ }
+
+ /* We always use a network mode so we always require TDM slots
+ * - complain loudly and fail if they've not been set up yet.
+ */
+ if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) {
+ dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
+ return -EINVAL;
+ }
+
+ dump_registers(ssp);
+
+ return 0;
+}
+
+static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret = 0;
+ struct ssp_priv *priv = cpu_dai->private_data;
+ struct ssp_device *ssp = priv->dev.ssp;
+ int val;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_RESUME:
+ ssp_enable(&priv->dev);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ val = ssp_read_reg(ssp, SSCR1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ val |= SSCR1_TSRE;
+ else
+ val |= SSCR1_RSRE;
+ ssp_write_reg(ssp, SSCR1, val);
+ val = ssp_read_reg(ssp, SSSR);
+ ssp_write_reg(ssp, SSSR, val);
+ break;
+ case SNDRV_PCM_TRIGGER_START:
+ val = ssp_read_reg(ssp, SSCR1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ val |= SSCR1_TSRE;
+ else
+ val |= SSCR1_RSRE;
+ ssp_write_reg(ssp, SSCR1, val);
+ ssp_enable(&priv->dev);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ val = ssp_read_reg(ssp, SSCR1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ val &= ~SSCR1_TSRE;
+ else
+ val &= ~SSCR1_RSRE;
+ ssp_write_reg(ssp, SSCR1, val);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ ssp_disable(&priv->dev);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ val = ssp_read_reg(ssp, SSCR1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ val &= ~SSCR1_TSRE;
+ else
+ val &= ~SSCR1_RSRE;
+ ssp_write_reg(ssp, SSCR1, val);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ dump_registers(ssp);
+
+ return ret;
+}
+
+static int pxa_ssp_probe(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ struct ssp_priv *priv;
+ int ret;
+
+ priv = kzalloc(sizeof(struct ssp_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev.ssp = ssp_request(dai->id, "SoC audio");
+ if (priv->dev.ssp == NULL) {
+ ret = -ENODEV;
+ goto err_priv;
+ }
+
+ dai->private_data = priv;
+
+ return 0;
+
+err_priv:
+ kfree(priv);
+ return ret;
+}
+
+static void pxa_ssp_remove(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ struct ssp_priv *priv = dai->private_data;
+ ssp_free(priv->dev.ssp);
+}
+
+#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
+ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai pxa_ssp_dai[] = {
+ {
+ .name = "pxa2xx-ssp1",
+ .id = 0,
+ .probe = pxa_ssp_probe,
+ .remove = pxa_ssp_remove,
+ .suspend = pxa_ssp_suspend,
+ .resume = pxa_ssp_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .ops = {
+ .startup = pxa_ssp_startup,
+ .shutdown = pxa_ssp_shutdown,
+ .trigger = pxa_ssp_trigger,
+ .hw_params = pxa_ssp_hw_params,
+ .set_sysclk = pxa_ssp_set_dai_sysclk,
+ .set_clkdiv = pxa_ssp_set_dai_clkdiv,
+ .set_pll = pxa_ssp_set_dai_pll,
+ .set_fmt = pxa_ssp_set_dai_fmt,
+ .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
+ .set_tristate = pxa_ssp_set_dai_tristate,
+ },
+ },
+ { .name = "pxa2xx-ssp2",
+ .id = 1,
+ .probe = pxa_ssp_probe,
+ .remove = pxa_ssp_remove,
+ .suspend = pxa_ssp_suspend,
+ .resume = pxa_ssp_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .ops = {
+ .startup = pxa_ssp_startup,
+ .shutdown = pxa_ssp_shutdown,
+ .trigger = pxa_ssp_trigger,
+ .hw_params = pxa_ssp_hw_params,
+ .set_sysclk = pxa_ssp_set_dai_sysclk,
+ .set_clkdiv = pxa_ssp_set_dai_clkdiv,
+ .set_pll = pxa_ssp_set_dai_pll,
+ .set_fmt = pxa_ssp_set_dai_fmt,
+ .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
+ .set_tristate = pxa_ssp_set_dai_tristate,
+ },
+ },
+ {
+ .name = "pxa2xx-ssp3",
+ .id = 2,
+ .probe = pxa_ssp_probe,
+ .remove = pxa_ssp_remove,
+ .suspend = pxa_ssp_suspend,
+ .resume = pxa_ssp_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .ops = {
+ .startup = pxa_ssp_startup,
+ .shutdown = pxa_ssp_shutdown,
+ .trigger = pxa_ssp_trigger,
+ .hw_params = pxa_ssp_hw_params,
+ .set_sysclk = pxa_ssp_set_dai_sysclk,
+ .set_clkdiv = pxa_ssp_set_dai_clkdiv,
+ .set_pll = pxa_ssp_set_dai_pll,
+ .set_fmt = pxa_ssp_set_dai_fmt,
+ .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
+ .set_tristate = pxa_ssp_set_dai_tristate,
+ },
+ },
+ {
+ .name = "pxa2xx-ssp4",
+ .id = 3,
+ .probe = pxa_ssp_probe,
+ .remove = pxa_ssp_remove,
+ .suspend = pxa_ssp_suspend,
+ .resume = pxa_ssp_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = PXA_SSP_RATES,
+ .formats = PXA_SSP_FORMATS,
+ },
+ .ops = {
+ .startup = pxa_ssp_startup,
+ .shutdown = pxa_ssp_shutdown,
+ .trigger = pxa_ssp_trigger,
+ .hw_params = pxa_ssp_hw_params,
+ .set_sysclk = pxa_ssp_set_dai_sysclk,
+ .set_clkdiv = pxa_ssp_set_dai_clkdiv,
+ .set_pll = pxa_ssp_set_dai_pll,
+ .set_fmt = pxa_ssp_set_dai_fmt,
+ .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
+ .set_tristate = pxa_ssp_set_dai_tristate,
+ },
+ },
+};
+EXPORT_SYMBOL_GPL(pxa_ssp_dai);
+
+static int __init pxa_ssp_init(void)
+{
+ return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
+}
+module_init(pxa_ssp_init);
+
+static void __exit pxa_ssp_exit(void)
+{
+ snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
+}
+module_exit(pxa_ssp_exit);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("PXA SSP/PCM SoC Interface");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * ASoC PXA SSP port support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PXA_SSP_H
+#define _PXA_SSP_H
+
+/* pxa DAI SSP IDs */
+#define PXA_DAI_SSP1 0
+#define PXA_DAI_SSP2 1
+#define PXA_DAI_SSP3 2
+#define PXA_DAI_SSP4 3
+
+/* SSP clock sources */
+#define PXA_SSP_CLK_PLL 0
+#define PXA_SSP_CLK_EXT 1
+#define PXA_SSP_CLK_NET 2
+#define PXA_SSP_CLK_AUDIO 3
+#define PXA_SSP_CLK_NET_PLL 4
+
+/* SSP audio dividers */
+#define PXA_SSP_AUDIO_DIV_ACDS 0
+#define PXA_SSP_AUDIO_DIV_SCDB 1
+#define PXA_SSP_DIV_SCR 2
+
+/* SSP ACDS audio dividers values */
+#define PXA_SSP_CLK_AUDIO_DIV_1 0
+#define PXA_SSP_CLK_AUDIO_DIV_2 1
+#define PXA_SSP_CLK_AUDIO_DIV_4 2
+#define PXA_SSP_CLK_AUDIO_DIV_8 3
+#define PXA_SSP_CLK_AUDIO_DIV_16 4
+#define PXA_SSP_CLK_AUDIO_DIV_32 5
+
+/* SSP divider bypass */
+#define PXA_SSP_CLK_SCDB_4 0
+#define PXA_SSP_CLK_SCDB_1 1
+#define PXA_SSP_CLK_SCDB_8 2
+
+#define PXA_SSP_PLL_OUT 0
+
+extern struct snd_soc_dai pxa_ssp_dai[4];
+
+#endif
};
#ifdef CONFIG_PM
-static int pxa2xx_ac97_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int pxa2xx_ac97_suspend(struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_suspend();
}
-static int pxa2xx_ac97_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_resume();
}
}
static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
}
static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
}
static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
{
.name = "pxa2xx-ac97",
.id = 0,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.probe = pxa2xx_ac97_probe,
.remove = pxa2xx_ac97_remove,
.suspend = pxa2xx_ac97_suspend,
{
.name = "pxa2xx-ac97-aux",
.id = 1,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.playback = {
.stream_name = "AC97 Aux Playback",
.channels_min = 1,
{
.name = "pxa2xx-ac97-mic",
.id = 2,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.capture = {
.stream_name = "AC97 Mic Capture",
.channels_min = 1,
EXPORT_SYMBOL_GPL(pxa_ac97_dai);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
+static int __init pxa_ac97_init(void)
+{
+ return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
+}
+module_init(pxa_ac97_init);
+
+static void __exit pxa_ac97_exit(void)
+{
+ snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
+}
+module_exit(pxa_ac97_exit);
+
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
MODULE_LICENSE("GPL");
},
};
-static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
+static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
}
static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
return 0;
}
-static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
int ret = 0;
return ret;
}
-static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
+static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
SACR1 |= SACR1_DRPL;
}
#ifdef CONFIG_PM
-static int pxa2xx_i2s_suspend(struct platform_device *dev,
- struct snd_soc_dai *dai)
+static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
return 0;
}
-static int pxa2xx_i2s_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
struct snd_soc_dai pxa_i2s_dai = {
.name = "pxa2xx-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.suspend = pxa2xx_i2s_suspend,
.resume = pxa2xx_i2s_resume,
.playback = {
.startup = pxa2xx_i2s_startup,
.shutdown = pxa2xx_i2s_shutdown,
.trigger = pxa2xx_i2s_trigger,
- .hw_params = pxa2xx_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = pxa2xx_i2s_hw_params,
.set_fmt = pxa2xx_i2s_set_dai_fmt,
.set_sysclk = pxa2xx_i2s_set_dai_sysclk,
},
static int pxa2xx_i2s_probe(struct platform_device *dev)
{
+ int ret;
+
clk_i2s = clk_get(&dev->dev, "I2SCLK");
- return IS_ERR(clk_i2s) ? PTR_ERR(clk_i2s) : 0;
+ if (IS_ERR(clk_i2s))
+ return PTR_ERR(clk_i2s);
+
+ pxa_i2s_dai.dev = &dev->dev;
+ ret = snd_soc_register_dai(&pxa_i2s_dai);
+ if (ret != 0)
+ clk_put(clk_i2s);
+
+ return ret;
}
static int __devexit pxa2xx_i2s_remove(struct platform_device *dev)
{
+ snd_soc_unregister_dai(&pxa_i2s_dai);
clk_put(clk_i2s);
clk_i2s = ERR_PTR(-ENOENT);
return 0;
return 0;
}
-struct snd_pcm_ops pxa2xx_pcm_ops = {
+static struct snd_pcm_ops pxa2xx_pcm_ops = {
.open = __pxa2xx_pcm_open,
.close = __pxa2xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
};
EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
+static int __init pxa2xx_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&pxa2xx_soc_platform);
+}
+module_init(pxa2xx_soc_platform_init);
+
+static void __exit pxa2xx_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&pxa2xx_soc_platform);
+}
+module_exit(pxa2xx_soc_platform_exit);
+
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
MODULE_LICENSE("GPL");
};
/* spitz audio machine driver */
-static struct snd_soc_machine snd_soc_machine_spitz = {
+static struct snd_soc_card snd_soc_spitz = {
.name = "Spitz",
+ .platform = &pxa2xx_soc_platform,
.dai_link = &spitz_dai,
.num_links = 1,
};
/* spitz audio subsystem */
static struct snd_soc_device spitz_snd_devdata = {
- .machine = &snd_soc_machine_spitz,
- .platform = &pxa2xx_soc_platform,
+ .card = &snd_soc_spitz,
.codec_dev = &soc_codec_dev_wm8750,
.codec_data = &spitz_wm8750_setup,
};
#include "pxa2xx-pcm.h"
#include "pxa2xx-ac97.h"
-static struct snd_soc_machine tosa;
+static struct snd_soc_card tosa;
#define TOSA_HP 0
#define TOSA_MIC_INT 1
},
};
-static struct snd_soc_machine tosa = {
+static int tosa_probe(struct platform_device *dev)
+{
+ int ret;
+
+ ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
+ if (ret)
+ return ret;
+ ret = gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
+ if (ret)
+ gpio_free(TOSA_GPIO_L_MUTE);
+
+ return ret;
+}
+
+static int tosa_remove(struct platform_device *dev)
+{
+ gpio_free(TOSA_GPIO_L_MUTE);
+ return 0;
+}
+
+static struct snd_soc_card tosa = {
.name = "Tosa",
+ .platform = &pxa2xx_soc_platform,
.dai_link = tosa_dai,
.num_links = ARRAY_SIZE(tosa_dai),
+ .probe = tosa_probe,
+ .remove = tosa_remove,
};
static struct snd_soc_device tosa_snd_devdata = {
- .machine = &tosa,
- .platform = &pxa2xx_soc_platform,
+ .card = &tosa,
.codec_dev = &soc_codec_dev_wm9712,
};
if (!machine_is_tosa())
return -ENODEV;
- ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
- if (ret)
- return ret;
- gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
-
tosa_snd_device = platform_device_alloc("soc-audio", -1);
if (!tosa_snd_device) {
ret = -ENOMEM;
platform_device_put(tosa_snd_device);
err_alloc:
- gpio_free(TOSA_GPIO_L_MUTE);
-
return ret;
}
static void __exit tosa_exit(void)
{
platform_device_unregister(tosa_snd_device);
- gpio_free(TOSA_GPIO_L_MUTE);
}
module_init(tosa_init);
--- /dev/null
+/*
+ * zylonite.c -- SoC audio for Zylonite
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "../codecs/wm9713.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+#include "pxa-ssp.h"
+
+static struct snd_soc_card zylonite;
+
+static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Headset Microphone", NULL),
+ SND_SOC_DAPM_MIC("Handset Microphone", NULL),
+ SND_SOC_DAPM_SPK("Multiactor", NULL),
+ SND_SOC_DAPM_SPK("Headset Earpiece", NULL),
+};
+
+/* Currently supported audio map */
+static const struct snd_soc_dapm_route audio_map[] = {
+
+ /* Headphone output connected to HPL/HPR */
+ { "Headphone", NULL, "HPL" },
+ { "Headphone", NULL, "HPR" },
+
+ /* On-board earpiece */
+ { "Headset Earpiece", NULL, "OUT3" },
+
+ /* Headphone mic */
+ { "MIC2A", NULL, "Mic Bias" },
+ { "Mic Bias", NULL, "Headset Microphone" },
+
+ /* On-board mic */
+ { "MIC1", NULL, "Mic Bias" },
+ { "Mic Bias", NULL, "Handset Microphone" },
+
+ /* Multiactor differentially connected over SPKL/SPKR */
+ { "Multiactor", NULL, "SPKL" },
+ { "Multiactor", NULL, "SPKR" },
+};
+
+static int zylonite_wm9713_init(struct snd_soc_codec *codec)
+{
+ /* Currently we only support use of the AC97 clock here. If
+ * CLK_POUT is selected by SW15 then the clock API will need
+ * to be used to request and enable it here.
+ */
+
+ snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
+ ARRAY_SIZE(zylonite_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ /* Static setup for now */
+ snd_soc_dapm_enable_pin(codec, "Headphone");
+ snd_soc_dapm_enable_pin(codec, "Headset Earpiece");
+
+ snd_soc_dapm_sync(codec);
+ return 0;
+}
+
+static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ unsigned int pll_out = 0;
+ unsigned int acds = 0;
+ unsigned int wm9713_div = 0;
+ int ret = 0;
+
+ switch (params_rate(params)) {
+ case 8000:
+ wm9713_div = 12;
+ pll_out = 2048000;
+ break;
+ case 16000:
+ wm9713_div = 6;
+ pll_out = 4096000;
+ break;
+ case 48000:
+ default:
+ wm9713_div = 2;
+ pll_out = 12288000;
+ acds = 1;
+ break;
+ }
+
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai,
+ params_channels(params),
+ params_channels(params));
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1);
+ if (ret < 0)
+ return ret;
+
+ /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs
+ * to be set instead.
+ */
+ ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV,
+ WM9713_PCMDIV(wm9713_div));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops zylonite_voice_ops = {
+ .hw_params = zylonite_voice_hw_params,
+};
+
+static struct snd_soc_dai_link zylonite_dai[] = {
+{
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+ .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
+ .init = zylonite_wm9713_init,
+},
+{
+ .name = "AC97 Aux",
+ .stream_name = "AC97 Aux",
+ .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+ .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
+},
+{
+ .name = "WM9713 Voice",
+ .stream_name = "WM9713 Voice",
+ .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3],
+ .codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE],
+ .ops = &zylonite_voice_ops,
+},
+};
+
+static struct snd_soc_card zylonite = {
+ .name = "Zylonite",
+ .platform = &pxa2xx_soc_platform,
+ .dai_link = zylonite_dai,
+ .num_links = ARRAY_SIZE(zylonite_dai),
+};
+
+static struct snd_soc_device zylonite_snd_ac97_devdata = {
+ .card = &zylonite,
+ .codec_dev = &soc_codec_dev_wm9713,
+};
+
+static struct platform_device *zylonite_snd_ac97_device;
+
+static int __init zylonite_init(void)
+{
+ int ret;
+
+ zylonite_snd_ac97_device = platform_device_alloc("soc-audio", -1);
+ if (!zylonite_snd_ac97_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(zylonite_snd_ac97_device,
+ &zylonite_snd_ac97_devdata);
+ zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev;
+
+ ret = platform_device_add(zylonite_snd_ac97_device);
+ if (ret != 0)
+ platform_device_put(zylonite_snd_ac97_device);
+
+ return ret;
+}
+
+static void __exit zylonite_exit(void)
+{
+ platform_device_unregister(zylonite_snd_ac97_device);
+}
+
+module_init(zylonite_init);
+module_exit(zylonite_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("ALSA SoC WM9713 Zylonite");
+MODULE_LICENSE("GPL");
Say Y if you want to add support for SoC audio on ln2440sbc
with the ALC650.
+config SND_S3C24XX_SOC_S3C24XX_UDA134X
+ tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
+ depends on SND_S3C24XX_SOC
+ select SND_S3C24XX_SOC_I2S
+ select SND_SOC_UDA134X
snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
+snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
+obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
#include "s3c24xx-pcm.h"
#include "s3c24xx-ac97.h"
-static struct snd_soc_machine ln2440sbc;
+static struct snd_soc_card ln2440sbc;
static struct snd_soc_dai_link ln2440sbc_dai[] = {
{
},
};
-static struct snd_soc_machine ln2440sbc = {
+static struct snd_soc_card ln2440sbc = {
.name = "LN2440SBC",
+ .platform = &s3c24xx_soc_platform,
.dai_link = ln2440sbc_dai,
.num_links = ARRAY_SIZE(ln2440sbc_dai),
};
static struct snd_soc_device ln2440sbc_snd_ac97_devdata = {
- .machine = &ln2440sbc,
- .platform = &s3c24xx_soc_platform,
+ .card = &ln2440sbc,
.codec_dev = &soc_codec_dev_ac97,
};
#define NEO_CAPTURE_HEADSET 7
#define NEO_CAPTURE_BLUETOOTH 8
-static struct snd_soc_machine neo1973;
+static struct snd_soc_card neo1973;
static struct i2c_client *i2c;
static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
static struct snd_soc_dai bt_dai = {
.name = "Bluetooth",
.id = 0,
- .type = SND_SOC_DAI_PCM,
.playback = {
.channels_min = 1,
.channels_max = 1,
},
};
-static struct snd_soc_machine neo1973 = {
+static struct snd_soc_card neo1973 = {
.name = "neo1973",
+ .platform = &s3c24xx_soc_platform,
.dai_link = neo1973_dai,
.num_links = ARRAY_SIZE(neo1973_dai),
};
};
static struct snd_soc_device neo1973_snd_devdata = {
- .machine = &neo1973,
- .platform = &s3c24xx_soc_platform,
+ .card = &neo1973,
.codec_dev = &soc_codec_dev_wm8753,
.codec_data = &neo1973_wm8753_setup,
};
}
static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
u32 iismod;
return 0;
}
-static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
unsigned long irqs;
}
#ifdef CONFIG_PM
-static int s3c2412_i2s_suspend(struct platform_device *dev,
- struct snd_soc_dai *dai)
+static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
{
struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
u32 iismod;
iismod = readl(i2s->regs + S3C2412_IISMOD);
if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
- dev_warn(&dev->dev, "%s: RXDMA active?\n", __func__);
+ pr_warning("%s: RXDMA active?\n", __func__);
if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
- dev_warn(&dev->dev, "%s: TXDMA active?\n", __func__);
+ pr_warning("%s: TXDMA active?\n", __func__);
if (iismod & S3C2412_IISCON_IIS_ACTIVE)
- dev_warn(&dev->dev, "%s: IIS active\n", __func__);
+ pr_warning("%s: IIS active\n", __func__);
}
return 0;
}
-static int s3c2412_i2s_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
+static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
{
struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
- dev_info(&pdev->dev, "dai_active %d, IISMOD %08x, IISCON %08x\n",
- dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
+ pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
+ dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
if (dai->active) {
writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
struct snd_soc_dai s3c2412_i2s_dai = {
.name = "s3c2412-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.probe = s3c2412_i2s_probe,
.suspend = s3c2412_i2s_suspend,
.resume = s3c2412_i2s_resume,
.ops = {
.trigger = s3c2412_i2s_trigger,
.hw_params = s3c2412_i2s_hw_params,
- },
- .dai_ops = {
.set_fmt = s3c2412_i2s_set_fmt,
.set_clkdiv = s3c2412_i2s_set_clkdiv,
.set_sysclk = s3c2412_i2s_set_sysclk,
};
EXPORT_SYMBOL_GPL(s3c2412_i2s_dai);
+static int __init s3c2412_i2s_init(void)
+{
+ return snd_soc_register_dai(&s3c2412_i2s_dai);
+}
+module_init(s3c2412_i2s_init);
+
+static void __exit s3c2412_i2s_exit(void)
+{
+ snd_soc_unregister_dai(&s3c2412_i2s_dai);
+}
+module_exit(s3c2412_i2s_exit);
+
+
/* Module information */
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");
}
static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
return 0;
}
-static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
+static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
u32 ac_glbctrl;
}
static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
}
static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
- int cmd)
+ int cmd, struct snd_soc_dai *dai)
{
u32 ac_glbctrl;
{
.name = "s3c2443-ac97",
.id = 0,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.probe = s3c2443_ac97_probe,
.remove = s3c2443_ac97_remove,
.playback = {
{
.name = "pxa2xx-ac97-mic",
.id = 1,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.capture = {
.stream_name = "AC97 Mic Capture",
.channels_min = 1,
EXPORT_SYMBOL_GPL(s3c2443_ac97_dai);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
+static int __init s3c2443_ac97_init(void)
+{
+ return snd_soc_register_dais(s3c2443_ac97_dai,
+ ARRAY_SIZE(s3c2443_ac97_dai));
+}
+module_init(s3c2443_ac97_init);
+
+static void __exit s3c2443_ac97_exit(void)
+{
+ snd_soc_unregister_dais(s3c2443_ac97_dai,
+ ARRAY_SIZE(s3c2443_ac97_dai));
+}
+module_exit(s3c2443_ac97_exit);
+
+
MODULE_AUTHOR("Graeme Gregory");
MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip");
MODULE_LICENSE("GPL");
}
static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
u32 iismod;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
+ iismod &= ~S3C2410_IISMOD_16BIT;
+ ((struct s3c24xx_pcm_dma_params *)
+ rtd->dai->cpu_dai->dma_data)->dma_size = 1;
break;
case SNDRV_PCM_FORMAT_S16_LE:
iismod |= S3C2410_IISMOD_16BIT;
+ ((struct s3c24xx_pcm_dma_params *)
+ rtd->dai->cpu_dai->dma_data)->dma_size = 2;
break;
+ default:
+ return -EINVAL;
}
writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
return 0;
}
-static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
int ret = 0;
}
#ifdef CONFIG_PM
-static int s3c24xx_i2s_suspend(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
+static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
{
DBG("Entered %s\n", __func__);
return 0;
}
-static int s3c24xx_i2s_resume(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
+static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
{
DBG("Entered %s\n", __func__);
clk_enable(s3c24xx_i2s.iis_clk);
struct snd_soc_dai s3c24xx_i2s_dai = {
.name = "s3c24xx-i2s",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.probe = s3c24xx_i2s_probe,
.suspend = s3c24xx_i2s_suspend,
.resume = s3c24xx_i2s_resume,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.trigger = s3c24xx_i2s_trigger,
- .hw_params = s3c24xx_i2s_hw_params,},
- .dai_ops = {
+ .hw_params = s3c24xx_i2s_hw_params,
.set_fmt = s3c24xx_i2s_set_fmt,
.set_clkdiv = s3c24xx_i2s_set_clkdiv,
.set_sysclk = s3c24xx_i2s_set_sysclk,
};
EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai);
+static int __init s3c24xx_i2s_init(void)
+{
+ return snd_soc_register_dai(&s3c24xx_i2s_dai);
+}
+module_init(s3c24xx_i2s_init);
+
+static void __exit s3c24xx_i2s_exit(void)
+{
+ snd_soc_unregister_dai(&s3c24xx_i2s_dai);
+}
+module_exit(s3c24xx_i2s_exit);
+
/* Module information */
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");
};
EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
+static int __init s3c24xx_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&s3c24xx_soc_platform);
+}
+module_init(s3c24xx_soc_platform_init);
+
+static void __exit s3c24xx_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&s3c24xx_soc_platform);
+}
+module_exit(s3c24xx_soc_platform_exit);
+
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module");
MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * Modifications by Christian Pellegrin <chripell@evolware.org>
+ *
+ * s3c24xx_uda134x.c -- S3C24XX_UDA134X ALSA SoC Audio board driver
+ *
+ * Copyright 2007 Dension Audio Systems Ltd.
+ * Author: Zoltan Devai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/s3c24xx_uda134x.h>
+#include <sound/uda134x.h>
+
+#include <asm/plat-s3c24xx/regs-iis.h>
+
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+#include "../codecs/uda134x.h"
+
+
+/* #define ENFORCE_RATES 1 */
+/*
+ Unfortunately the S3C24XX in master mode has a limited capacity of
+ generating the clock for the codec. If you define this only rates
+ that are really available will be enforced. But be careful, most
+ user level application just want the usual sampling frequencies (8,
+ 11.025, 22.050, 44.1 kHz) and anyway resampling is a costly
+ operation for embedded systems. So if you aren't very lucky or your
+ hardware engineer wasn't very forward-looking it's better to leave
+ this undefined. If you do so an approximate value for the requested
+ sampling rate in the range -/+ 5% will be chosen. If this in not
+ possible an error will be returned.
+*/
+
+static struct clk *xtal;
+static struct clk *pclk;
+/* this is need because we don't have a place where to keep the
+ * pointers to the clocks in each substream. We get the clocks only
+ * when we are actually using them so we don't block stuff like
+ * frequency change or oscillator power-off */
+static int clk_users;
+static DEFINE_MUTEX(clk_lock);
+
+static unsigned int rates[33 * 2];
+#ifdef ENFORCE_RATES
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+};
+#endif
+
+static struct platform_device *s3c24xx_uda134x_snd_device;
+
+static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+#ifdef ENFORCE_RATES
+ struct snd_pcm_runtime *runtime = substream->runtime;;
+#endif
+
+ mutex_lock(&clk_lock);
+ pr_debug("%s %d\n", __func__, clk_users);
+ if (clk_users == 0) {
+ xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
+ if (!xtal) {
+ printk(KERN_ERR "%s cannot get xtal\n", __func__);
+ ret = -EBUSY;
+ } else {
+ pclk = clk_get(&s3c24xx_uda134x_snd_device->dev,
+ "pclk");
+ if (!pclk) {
+ printk(KERN_ERR "%s cannot get pclk\n",
+ __func__);
+ clk_put(xtal);
+ ret = -EBUSY;
+ }
+ }
+ if (!ret) {
+ int i, j;
+
+ for (i = 0; i < 2; i++) {
+ int fs = i ? 256 : 384;
+
+ rates[i*33] = clk_get_rate(xtal) / fs;
+ for (j = 1; j < 33; j++)
+ rates[i*33 + j] = clk_get_rate(pclk) /
+ (j * fs);
+ }
+ }
+ }
+ clk_users += 1;
+ mutex_unlock(&clk_lock);
+ if (!ret) {
+#ifdef ENFORCE_RATES
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates);
+ if (ret < 0)
+ printk(KERN_ERR "%s cannot set constraints\n",
+ __func__);
+#endif
+ }
+ return ret;
+}
+
+static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream)
+{
+ mutex_lock(&clk_lock);
+ pr_debug("%s %d\n", __func__, clk_users);
+ clk_users -= 1;
+ if (clk_users == 0) {
+ clk_put(xtal);
+ xtal = NULL;
+ clk_put(pclk);
+ pclk = NULL;
+ }
+ mutex_unlock(&clk_lock);
+}
+
+static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ unsigned int clk = 0;
+ int ret = 0;
+ int clk_source, fs_mode;
+ unsigned long rate = params_rate(params);
+ long err, cerr;
+ unsigned int div;
+ int i, bi;
+
+ err = 999999;
+ bi = 0;
+ for (i = 0; i < 2*33; i++) {
+ cerr = rates[i] - rate;
+ if (cerr < 0)
+ cerr = -cerr;
+ if (cerr < err) {
+ err = cerr;
+ bi = i;
+ }
+ }
+ if (bi / 33 == 1)
+ fs_mode = S3C2410_IISMOD_256FS;
+ else
+ fs_mode = S3C2410_IISMOD_384FS;
+ if (bi % 33 == 0) {
+ clk_source = S3C24XX_CLKSRC_MPLL;
+ div = 1;
+ } else {
+ clk_source = S3C24XX_CLKSRC_PCLK;
+ div = bi % 33;
+ }
+ pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi);
+
+ clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate;
+ pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__,
+ fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS",
+ clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK",
+ div, clk, err);
+
+ if ((err * 100 / rate) > 5) {
+ printk(KERN_ERR "S3C24XX_UDA134X: effective frequency "
+ "too different from desired (%ld%%)\n",
+ err * 100 / rate);
+ return -EINVAL;
+ }
+
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, fs_mode);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
+ S3C2410_IISMOD_32FS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
+ S3C24XX_PRESCALE(div, div));
+ if (ret < 0)
+ return ret;
+
+ /* set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops s3c24xx_uda134x_ops = {
+ .startup = s3c24xx_uda134x_startup,
+ .shutdown = s3c24xx_uda134x_shutdown,
+ .hw_params = s3c24xx_uda134x_hw_params,
+};
+
+static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
+ .name = "UDA134X",
+ .stream_name = "UDA134X",
+ .codec_dai = &uda134x_dai,
+ .cpu_dai = &s3c24xx_i2s_dai,
+ .ops = &s3c24xx_uda134x_ops,
+};
+
+static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
+ .name = "S3C24XX_UDA134X",
+ .platform = &s3c24xx_soc_platform,
+ .dai_link = &s3c24xx_uda134x_dai_link,
+ .num_links = 1,
+};
+
+static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins;
+
+static void setdat(int v)
+{
+ gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0);
+}
+
+static void setclk(int v)
+{
+ gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0);
+}
+
+static void setmode(int v)
+{
+ gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
+}
+
+static struct uda134x_platform_data s3c24xx_uda134x = {
+ .l3 = {
+ .setdat = setdat,
+ .setclk = setclk,
+ .setmode = setmode,
+ .data_hold = 1,
+ .data_setup = 1,
+ .clock_high = 1,
+ .mode_hold = 1,
+ .mode = 1,
+ .mode_setup = 1,
+ },
+};
+
+static struct snd_soc_device s3c24xx_uda134x_snd_devdata = {
+ .card = &snd_soc_s3c24xx_uda134x,
+ .codec_dev = &soc_codec_dev_uda134x,
+ .codec_data = &s3c24xx_uda134x,
+};
+
+static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
+{
+ if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
+ printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
+ "l3 %s pin already in use", fun);
+ return -EBUSY;
+ }
+ gpio_direction_output(pin, 0);
+ return 0;
+}
+
+static int s3c24xx_uda134x_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n");
+
+ s3c24xx_uda134x_l3_pins = pdev->dev.platform_data;
+ if (s3c24xx_uda134x_l3_pins == NULL) {
+ printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
+ "unable to find platform data\n");
+ return -ENODEV;
+ }
+ s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power;
+ s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model;
+
+ if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data,
+ "data") < 0)
+ return -EBUSY;
+ if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk,
+ "clk") < 0) {
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
+ return -EBUSY;
+ }
+ if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode,
+ "mode") < 0) {
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
+ return -EBUSY;
+ }
+
+ s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
+ if (!s3c24xx_uda134x_snd_device) {
+ printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
+ "Unable to register\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(s3c24xx_uda134x_snd_device,
+ &s3c24xx_uda134x_snd_devdata);
+ s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev;
+ ret = platform_device_add(s3c24xx_uda134x_snd_device);
+ if (ret) {
+ printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
+ platform_device_put(s3c24xx_uda134x_snd_device);
+ }
+
+ return ret;
+}
+
+static int s3c24xx_uda134x_remove(struct platform_device *pdev)
+{
+ platform_device_unregister(s3c24xx_uda134x_snd_device);
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
+ gpio_free(s3c24xx_uda134x_l3_pins->l3_mode);
+ return 0;
+}
+
+static struct platform_driver s3c24xx_uda134x_driver = {
+ .probe = s3c24xx_uda134x_probe,
+ .remove = s3c24xx_uda134x_remove,
+ .driver = {
+ .name = "s3c24xx_uda134x",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init s3c24xx_uda134x_init(void)
+{
+ return platform_driver_register(&s3c24xx_uda134x_driver);
+}
+
+static void __exit s3c24xx_uda134x_exit(void)
+{
+ platform_driver_unregister(&s3c24xx_uda134x_driver);
+}
+
+
+module_init(s3c24xx_uda134x_init);
+module_exit(s3c24xx_uda134x_exit);
+
+MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
+MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver");
+MODULE_LICENSE("GPL");
#include "s3c24xx-pcm.h"
#include "s3c24xx-ac97.h"
-static struct snd_soc_machine smdk2443;
+static struct snd_soc_card smdk2443;
static struct snd_soc_dai_link smdk2443_dai[] = {
{
},
};
-static struct snd_soc_machine smdk2443 = {
+static struct snd_soc_card smdk2443 = {
.name = "SMDK2443",
+ .platform = &s3c24xx_soc_platform,
.dai_link = smdk2443_dai,
.num_links = ARRAY_SIZE(smdk2443_dai),
};
static struct snd_soc_device smdk2443_snd_ac97_devdata = {
- .machine = &smdk2443,
- .platform = &s3c24xx_soc_platform,
+ .card = &smdk2443,
.codec_dev = &soc_codec_dev_ac97,
};
};
EXPORT_SYMBOL_GPL(sh7760_soc_platform);
+static int __init sh7760_soc_platform_init(void)
+{
+ return snd_soc_register_platform(&sh7760_soc_platform);
+}
+module_init(sh7760_soc_platform_init);
+
+static void __exit sh7760_soc_platform_exit(void)
+{
+ snd_soc_unregister_platform(&sh7760_soc_platform);
+}
+module_exit(sh7760_soc_platform_exit);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
EXPORT_SYMBOL_GPL(soc_ac97_ops);
static int hac_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id];
{
.name = "HAC0",
.id = 0,
- .type = SND_SOC_DAI_AC97,
+ .ac97_control = 1,
.playback = {
.rates = AC97_RATES,
.formats = AC97_FMTS,
#ifdef CONFIG_CPU_SUBTYPE_SH7760
{
.name = "HAC1",
+ .ac97_control = 1,
.id = 1,
- .type = SND_SOC_DAI_AC97,
.playback = {
.rates = AC97_RATES,
.formats = AC97_FMTS,
};
EXPORT_SYMBOL_GPL(sh4_hac_dai);
+static int __init sh4_hac_init(void)
+{
+ return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
+}
+module_init(sh4_hac_init);
+
+static void __exit sh4_hac_exit(void)
+{
+ snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
+}
+module_exit(sh4_hac_exit);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
.ops = NULL,
};
-static struct snd_soc_machine sh7760_ac97_soc_machine = {
+static struct snd_soc_card sh7760_ac97_soc_machine = {
.name = "SH7760 AC97",
+ .platform = &sh7760_soc_platform,
.dai_link = &sh7760_ac97_dai,
.num_links = 1,
};
static struct snd_soc_device sh7760_ac97_snd_devdata = {
- .machine = &sh7760_ac97_soc_machine,
- .platform = &sh7760_soc_platform,
+ .card = &sh7760_ac97_soc_machine,
.codec_dev = &soc_codec_dev_ac97,
};
* track usage of the SSI; it is simplex-only so prevent attempts of
* concurrent playback + capture. FIXME: any locking required?
*/
-static int ssi_startup(struct snd_pcm_substream *substream)
+static int ssi_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
return 0;
}
-static void ssi_shutdown(struct snd_pcm_substream *substream)
+static void ssi_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
ssi->inuse = 0;
}
-static int ssi_trigger(struct snd_pcm_substream *substream, int cmd)
+static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
}
static int ssi_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
{
.name = "SSI0",
.id = 0,
- .type = SND_SOC_DAI_I2S,
.playback = {
.rates = SSI_RATES,
.formats = SSI_FMTS,
.shutdown = ssi_shutdown,
.trigger = ssi_trigger,
.hw_params = ssi_hw_params,
- },
- .dai_ops = {
.set_sysclk = ssi_set_sysclk,
.set_clkdiv = ssi_set_clkdiv,
.set_fmt = ssi_set_fmt,
{
.name = "SSI1",
.id = 1,
- .type = SND_SOC_DAI_I2S,
.playback = {
.rates = SSI_RATES,
.formats = SSI_FMTS,
.shutdown = ssi_shutdown,
.trigger = ssi_trigger,
.hw_params = ssi_hw_params,
- },
- .dai_ops = {
.set_sysclk = ssi_set_sysclk,
.set_clkdiv = ssi_set_clkdiv,
.set_fmt = ssi_set_fmt,
};
EXPORT_SYMBOL_GPL(sh4_ssi_dai);
+static int __init sh4_ssi_init(void)
+{
+ return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
+}
+module_init(sh4_ssi_init);
+
+static void __exit sh4_ssi_exit(void)
+{
+ snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
+}
+module_exit(sh4_ssi_exit);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/bitops.h>
+#include <linux/debugfs.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
-/* debug */
-#define SOC_DEBUG 0
-#if SOC_DEBUG
-#define dbg(format, arg...) printk(format, ## arg)
-#else
-#define dbg(format, arg...)
-#endif
-
static DEFINE_MUTEX(pcm_mutex);
static DEFINE_MUTEX(io_mutex);
static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *debugfs_root;
+#endif
+
+static DEFINE_MUTEX(client_mutex);
+static LIST_HEAD(card_list);
+static LIST_HEAD(dai_list);
+static LIST_HEAD(platform_list);
+static LIST_HEAD(codec_list);
+
+static int snd_soc_register_card(struct snd_soc_card *card);
+static int snd_soc_unregister_card(struct snd_soc_card *card);
+
/*
* This is a timeout to do a DAPM powerdown after a stream is closed().
* It can be used to eliminate pops between different playback streams, e.g.
}
#endif
-static inline const char *get_dai_name(int type)
-{
- switch (type) {
- case SND_SOC_DAI_AC97_BUS:
- case SND_SOC_DAI_AC97:
- return "AC97";
- case SND_SOC_DAI_I2S:
- return "I2S";
- case SND_SOC_DAI_PCM:
- return "PCM";
- }
- return NULL;
-}
-
/*
* Called by ALSA when a PCM substream is opened, the runtime->hw record is
* then initialized and any private data can be allocated. This also calls
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_card *card = socdev->card;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
int ret = 0;
/* startup the audio subsystem */
if (cpu_dai->ops.startup) {
- ret = cpu_dai->ops.startup(substream);
+ ret = cpu_dai->ops.startup(substream, cpu_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: can't open interface %s\n",
cpu_dai->name);
}
if (codec_dai->ops.startup) {
- ret = codec_dai->ops.startup(substream);
+ ret = codec_dai->ops.startup(substream, codec_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: can't open codec %s\n",
codec_dai->name);
goto machine_err;
}
- dbg("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
- dbg("asoc: rate mask 0x%x\n", runtime->hw.rates);
- dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
- runtime->hw.channels_max);
- dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
- runtime->hw.rate_max);
+ pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
+ pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
+ pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
+ runtime->hw.channels_max);
+ pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
+ runtime->hw.rate_max);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
cpu_dai->playback.active = codec_dai->playback.active = 1;
platform_err:
if (cpu_dai->ops.shutdown)
- cpu_dai->ops.shutdown(substream);
+ cpu_dai->ops.shutdown(substream, cpu_dai);
out:
mutex_unlock(&pcm_mutex);
return ret;
*/
static void close_delayed_work(struct work_struct *work)
{
- struct snd_soc_device *socdev =
- container_of(work, struct snd_soc_device, delayed_work.work);
+ struct snd_soc_card *card = container_of(work, struct snd_soc_card,
+ delayed_work.work);
+ struct snd_soc_device *socdev = card->socdev;
struct snd_soc_codec *codec = socdev->codec;
struct snd_soc_dai *codec_dai;
int i;
for (i = 0; i < codec->num_dai; i++) {
codec_dai = &codec->dai[i];
- dbg("pop wq checking: %s status: %s waiting: %s\n",
- codec_dai->playback.stream_name,
- codec_dai->playback.active ? "active" : "inactive",
- codec_dai->pop_wait ? "yes" : "no");
+ pr_debug("pop wq checking: %s status: %s waiting: %s\n",
+ codec_dai->playback.stream_name,
+ codec_dai->playback.active ? "active" : "inactive",
+ codec_dai->pop_wait ? "yes" : "no");
/* are we waiting on this codec DAI stream */
if (codec_dai->pop_wait == 1) {
/* Reduce power if no longer active */
if (codec->active == 0) {
- dbg("pop wq D1 %s %s\n", codec->name,
- codec_dai->playback.stream_name);
+ pr_debug("pop wq D1 %s %s\n", codec->name,
+ codec_dai->playback.stream_name);
snd_soc_dapm_set_bias_level(socdev,
SND_SOC_BIAS_PREPARE);
}
/* Fall into standby if no longer active */
if (codec->active == 0) {
- dbg("pop wq D3 %s %s\n", codec->name,
- codec_dai->playback.stream_name);
+ pr_debug("pop wq D3 %s %s\n", codec->name,
+ codec_dai->playback.stream_name);
snd_soc_dapm_set_bias_level(socdev,
SND_SOC_BIAS_STANDBY);
}
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_card *card = socdev->card;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->codec;
snd_soc_dai_digital_mute(codec_dai, 1);
if (cpu_dai->ops.shutdown)
- cpu_dai->ops.shutdown(substream);
+ cpu_dai->ops.shutdown(substream, cpu_dai);
if (codec_dai->ops.shutdown)
- codec_dai->ops.shutdown(substream);
+ codec_dai->ops.shutdown(substream, codec_dai);
if (machine->ops && machine->ops->shutdown)
machine->ops->shutdown(substream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* start delayed pop wq here for playback streams */
codec_dai->pop_wait = 1;
- schedule_delayed_work(&socdev->delayed_work,
+ schedule_delayed_work(&card->delayed_work,
msecs_to_jiffies(pmdown_time));
} else {
/* capture streams can be powered down now */
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_card *card = socdev->card;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->codec;
}
if (codec_dai->ops.prepare) {
- ret = codec_dai->ops.prepare(substream);
+ ret = codec_dai->ops.prepare(substream, codec_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: codec DAI prepare error\n");
goto out;
}
if (cpu_dai->ops.prepare) {
- ret = cpu_dai->ops.prepare(substream);
+ ret = cpu_dai->ops.prepare(substream, cpu_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: cpu DAI prepare error\n");
goto out;
}
}
- /* we only want to start a DAPM playback stream if we are not waiting
- * on an existing one stopping */
- if (codec_dai->pop_wait) {
- /* we are waiting for the delayed work to start */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- snd_soc_dapm_stream_event(socdev->codec,
- codec_dai->capture.stream_name,
- SND_SOC_DAPM_STREAM_START);
- else {
- codec_dai->pop_wait = 0;
- cancel_delayed_work(&socdev->delayed_work);
- snd_soc_dai_digital_mute(codec_dai, 0);
- }
- } else {
- /* no delayed work - do we need to power up codec */
- if (codec->bias_level != SND_SOC_BIAS_ON) {
+ /* cancel any delayed stream shutdown that is pending */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+ codec_dai->pop_wait) {
+ codec_dai->pop_wait = 0;
+ cancel_delayed_work(&card->delayed_work);
+ }
- snd_soc_dapm_set_bias_level(socdev,
- SND_SOC_BIAS_PREPARE);
+ /* do we need to power up codec */
+ if (codec->bias_level != SND_SOC_BIAS_ON) {
+ snd_soc_dapm_set_bias_level(socdev,
+ SND_SOC_BIAS_PREPARE);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(codec,
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dapm_stream_event(codec,
codec_dai->playback.stream_name,
SND_SOC_DAPM_STREAM_START);
- else
- snd_soc_dapm_stream_event(codec,
+ else
+ snd_soc_dapm_stream_event(codec,
codec_dai->capture.stream_name,
SND_SOC_DAPM_STREAM_START);
- snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
- snd_soc_dai_digital_mute(codec_dai, 0);
+ snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
+ snd_soc_dai_digital_mute(codec_dai, 0);
- } else {
- /* codec already powered - power on widgets */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(codec,
+ } else {
+ /* codec already powered - power on widgets */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dapm_stream_event(codec,
codec_dai->playback.stream_name,
SND_SOC_DAPM_STREAM_START);
- else
- snd_soc_dapm_stream_event(codec,
+ else
+ snd_soc_dapm_stream_event(codec,
codec_dai->capture.stream_name,
SND_SOC_DAPM_STREAM_START);
- snd_soc_dai_digital_mute(codec_dai, 0);
- }
+ snd_soc_dai_digital_mute(codec_dai, 0);
}
out:
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
int ret = 0;
}
if (codec_dai->ops.hw_params) {
- ret = codec_dai->ops.hw_params(substream, params);
+ ret = codec_dai->ops.hw_params(substream, params, codec_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: can't set codec %s hw params\n",
codec_dai->name);
}
if (cpu_dai->ops.hw_params) {
- ret = cpu_dai->ops.hw_params(substream, params);
+ ret = cpu_dai->ops.hw_params(substream, params, cpu_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: interface %s hw params failed\n",
cpu_dai->name);
platform_err:
if (cpu_dai->ops.hw_free)
- cpu_dai->ops.hw_free(substream);
+ cpu_dai->ops.hw_free(substream, cpu_dai);
interface_err:
if (codec_dai->ops.hw_free)
- codec_dai->ops.hw_free(substream);
+ codec_dai->ops.hw_free(substream, codec_dai);
codec_err:
if (machine->ops && machine->ops->hw_free)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->codec;
/* now free hw params for the DAI's */
if (codec_dai->ops.hw_free)
- codec_dai->ops.hw_free(substream);
+ codec_dai->ops.hw_free(substream, codec_dai);
if (cpu_dai->ops.hw_free)
- cpu_dai->ops.hw_free(substream);
+ cpu_dai->ops.hw_free(substream, cpu_dai);
mutex_unlock(&pcm_mutex);
return 0;
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_card *card= socdev->card;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
int ret;
if (codec_dai->ops.trigger) {
- ret = codec_dai->ops.trigger(substream, cmd);
+ ret = codec_dai->ops.trigger(substream, cmd, codec_dai);
if (ret < 0)
return ret;
}
}
if (cpu_dai->ops.trigger) {
- ret = cpu_dai->ops.trigger(substream, cmd);
+ ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai);
if (ret < 0)
return ret;
}
static int soc_suspend(struct platform_device *pdev, pm_message_t state)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
struct snd_soc_codec *codec = socdev->codec;
int i;
snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot);
/* mute any active DAC's */
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
- if (dai->dai_ops.digital_mute && dai->playback.active)
- dai->dai_ops.digital_mute(dai, 1);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
+ if (dai->ops.digital_mute && dai->playback.active)
+ dai->ops.digital_mute(dai, 1);
}
/* suspend all pcms */
- for (i = 0; i < machine->num_links; i++)
- snd_pcm_suspend_all(machine->dai_link[i].pcm);
+ for (i = 0; i < card->num_links; i++)
+ snd_pcm_suspend_all(card->dai_link[i].pcm);
- if (machine->suspend_pre)
- machine->suspend_pre(pdev, state);
+ if (card->suspend_pre)
+ card->suspend_pre(pdev, state);
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
- if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97)
- cpu_dai->suspend(pdev, cpu_dai);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ if (cpu_dai->suspend && !cpu_dai->ac97_control)
+ cpu_dai->suspend(cpu_dai);
if (platform->suspend)
- platform->suspend(pdev, cpu_dai);
+ platform->suspend(cpu_dai);
}
/* close any waiting streams and save state */
- run_delayed_work(&socdev->delayed_work);
+ run_delayed_work(&card->delayed_work);
codec->suspend_bias_level = codec->bias_level;
for (i = 0; i < codec->num_dai; i++) {
if (codec_dev->suspend)
codec_dev->suspend(pdev, state);
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
- if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97)
- cpu_dai->suspend(pdev, cpu_dai);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ if (cpu_dai->suspend && cpu_dai->ac97_control)
+ cpu_dai->suspend(cpu_dai);
}
- if (machine->suspend_post)
- machine->suspend_post(pdev, state);
+ if (card->suspend_post)
+ card->suspend_post(pdev, state);
return 0;
}
*/
static void soc_resume_deferred(struct work_struct *work)
{
- struct snd_soc_device *socdev = container_of(work,
- struct snd_soc_device,
- deferred_resume_work);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = container_of(work,
+ struct snd_soc_card,
+ deferred_resume_work);
+ struct snd_soc_device *socdev = card->socdev;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
struct snd_soc_codec *codec = socdev->codec;
struct platform_device *pdev = to_platform_device(socdev->dev);
* so userspace apps are blocked from touching us
*/
- dev_info(socdev->dev, "starting resume work\n");
+ dev_dbg(socdev->dev, "starting resume work\n");
- if (machine->resume_pre)
- machine->resume_pre(pdev);
+ if (card->resume_pre)
+ card->resume_pre(pdev);
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
- if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97)
- cpu_dai->resume(pdev, cpu_dai);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ if (cpu_dai->resume && cpu_dai->ac97_control)
+ cpu_dai->resume(cpu_dai);
}
if (codec_dev->resume)
}
/* unmute any active DACs */
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
- if (dai->dai_ops.digital_mute && dai->playback.active)
- dai->dai_ops.digital_mute(dai, 0);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
+ if (dai->ops.digital_mute && dai->playback.active)
+ dai->ops.digital_mute(dai, 0);
}
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
- if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97)
- cpu_dai->resume(pdev, cpu_dai);
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ if (cpu_dai->resume && !cpu_dai->ac97_control)
+ cpu_dai->resume(cpu_dai);
if (platform->resume)
- platform->resume(pdev, cpu_dai);
+ platform->resume(cpu_dai);
}
- if (machine->resume_post)
- machine->resume_post(pdev);
+ if (card->resume_post)
+ card->resume_post(pdev);
- dev_info(socdev->dev, "resume work completed\n");
+ dev_dbg(socdev->dev, "resume work completed\n");
/* userspace can access us now we are back as we were before */
snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0);
static int soc_resume(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_card *card = socdev->card;
- dev_info(socdev->dev, "scheduling resume work\n");
+ dev_dbg(socdev->dev, "scheduling resume work\n");
- if (!schedule_work(&socdev->deferred_resume_work))
- dev_err(socdev->dev, "work item may be lost\n");
+ if (!schedule_work(&card->deferred_resume_work))
+ dev_err(socdev->dev, "resume work item may be lost\n");
return 0;
}
#define soc_resume NULL
#endif
-/* probes a new socdev */
-static int soc_probe(struct platform_device *pdev)
+static void snd_soc_instantiate_card(struct snd_soc_card *card)
{
- int ret = 0, i;
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_platform *platform = socdev->platform;
- struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
+ struct platform_device *pdev = container_of(card->dev,
+ struct platform_device,
+ dev);
+ struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
+ struct snd_soc_platform *platform;
+ struct snd_soc_dai *dai;
+ int i, found, ret, ac97;
+
+ if (card->instantiated)
+ return;
+
+ found = 0;
+ list_for_each_entry(platform, &platform_list, list)
+ if (card->platform == platform) {
+ found = 1;
+ break;
+ }
+ if (!found) {
+ dev_dbg(card->dev, "Platform %s not registered\n",
+ card->platform->name);
+ return;
+ }
+
+ ac97 = 0;
+ for (i = 0; i < card->num_links; i++) {
+ found = 0;
+ list_for_each_entry(dai, &dai_list, list)
+ if (card->dai_link[i].cpu_dai == dai) {
+ found = 1;
+ break;
+ }
+ if (!found) {
+ dev_dbg(card->dev, "DAI %s not registered\n",
+ card->dai_link[i].cpu_dai->name);
+ return;
+ }
- if (machine->probe) {
- ret = machine->probe(pdev);
+ if (card->dai_link[i].cpu_dai->ac97_control)
+ ac97 = 1;
+ }
+
+ /* If we have AC97 in the system then don't wait for the
+ * codec. This will need revisiting if we have to handle
+ * systems with mixed AC97 and non-AC97 parts. Only check for
+ * DAIs currently; we can't do this per link since some AC97
+ * codecs have non-AC97 DAIs.
+ */
+ if (!ac97)
+ for (i = 0; i < card->num_links; i++) {
+ found = 0;
+ list_for_each_entry(dai, &dai_list, list)
+ if (card->dai_link[i].codec_dai == dai) {
+ found = 1;
+ break;
+ }
+ if (!found) {
+ dev_dbg(card->dev, "DAI %s not registered\n",
+ card->dai_link[i].codec_dai->name);
+ return;
+ }
+ }
+
+ /* Note that we do not current check for codec components */
+
+ dev_dbg(card->dev, "All components present, instantiating\n");
+
+ /* Found everything, bring it up */
+ if (card->probe) {
+ ret = card->probe(pdev);
if (ret < 0)
- return ret;
+ return;
}
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
if (cpu_dai->probe) {
ret = cpu_dai->probe(pdev, cpu_dai);
if (ret < 0)
}
/* DAPM stream work */
- INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
+ INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work);
#ifdef CONFIG_PM
/* deferred resume work */
- INIT_WORK(&socdev->deferred_resume_work, soc_resume_deferred);
+ INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
#endif
- return 0;
+ card->instantiated = 1;
+
+ return;
platform_err:
if (codec_dev->remove)
cpu_dai_err:
for (i--; i >= 0; i--) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
if (cpu_dai->remove)
cpu_dai->remove(pdev, cpu_dai);
}
- if (machine->remove)
- machine->remove(pdev);
+ if (card->remove)
+ card->remove(pdev);
+}
- return ret;
+/*
+ * Attempt to initialise any uninitalised cards. Must be called with
+ * client_mutex.
+ */
+static void snd_soc_instantiate_cards(void)
+{
+ struct snd_soc_card *card;
+ list_for_each_entry(card, &card_list, list)
+ snd_soc_instantiate_card(card);
+}
+
+/* probes a new socdev */
+static int soc_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_card *card = socdev->card;
+
+ /* Bodge while we push things out of socdev */
+ card->socdev = socdev;
+
+ /* Bodge while we unpick instantiation */
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Failed to register card\n");
+ return ret;
+ }
+
+ return 0;
}
/* removes a socdev */
{
int i;
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_machine *machine = socdev->machine;
- struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
- run_delayed_work(&socdev->delayed_work);
+ run_delayed_work(&card->delayed_work);
if (platform->remove)
platform->remove(pdev);
if (codec_dev->remove)
codec_dev->remove(pdev);
- for (i = 0; i < machine->num_links; i++) {
- struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
if (cpu_dai->remove)
cpu_dai->remove(pdev, cpu_dai);
}
- if (machine->remove)
- machine->remove(pdev);
+ if (card->remove)
+ card->remove(pdev);
+
+ snd_soc_unregister_card(card);
return 0;
}
struct snd_soc_dai_link *dai_link, int num)
{
struct snd_soc_codec *codec = socdev->codec;
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *codec_dai = dai_link->codec_dai;
struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
struct snd_soc_pcm_runtime *rtd;
codec_dai->codec = socdev->codec;
/* check client and interface hw capabilities */
- sprintf(new_name, "%s %s-%s-%d", dai_link->stream_name, codec_dai->name,
- get_dai_name(cpu_dai->type), num);
+ sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name,
+ num);
if (codec_dai->playback.channels_min)
playback = 1;
dai_link->pcm = pcm;
pcm->private_data = rtd;
- soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap;
- soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer;
- soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl;
- soc_pcm_ops.copy = socdev->platform->pcm_ops->copy;
- soc_pcm_ops.silence = socdev->platform->pcm_ops->silence;
- soc_pcm_ops.ack = socdev->platform->pcm_ops->ack;
- soc_pcm_ops.page = socdev->platform->pcm_ops->page;
+ soc_pcm_ops.mmap = platform->pcm_ops->mmap;
+ soc_pcm_ops.pointer = platform->pcm_ops->pointer;
+ soc_pcm_ops.ioctl = platform->pcm_ops->ioctl;
+ soc_pcm_ops.copy = platform->pcm_ops->copy;
+ soc_pcm_ops.silence = platform->pcm_ops->silence;
+ soc_pcm_ops.ack = platform->pcm_ops->ack;
+ soc_pcm_ops.page = platform->pcm_ops->page;
if (playback)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
if (capture)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
- ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm);
+ ret = platform->pcm_new(codec->card, codec_dai, pcm);
if (ret < 0) {
printk(KERN_ERR "asoc: platform pcm constructor failed\n");
kfree(rtd);
return ret;
}
- pcm->private_free = socdev->platform->pcm_free;
+ pcm->private_free = platform->pcm_free;
printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
cpu_dai->name);
return ret;
}
/* codec register dump */
-static ssize_t codec_reg_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf)
{
- struct snd_soc_device *devdata = dev_get_drvdata(dev);
struct snd_soc_codec *codec = devdata->codec;
int i, step = 1, count = 0;
return count;
}
+static ssize_t codec_reg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct snd_soc_device *devdata = dev_get_drvdata(dev);
+ return soc_codec_reg_show(devdata, buf);
+}
+
static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
+#ifdef CONFIG_DEBUG_FS
+static int codec_reg_open_file(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t ret;
+ struct snd_soc_codec *codec = file->private_data;
+ struct device *card_dev = codec->card->dev;
+ struct snd_soc_device *devdata = card_dev->driver_data;
+ char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ ret = soc_codec_reg_show(devdata, buf);
+ if (ret >= 0)
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t codec_reg_write_file(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ char buf[32];
+ int buf_size;
+ char *start = buf;
+ unsigned long reg, value;
+ int step = 1;
+ struct snd_soc_codec *codec = file->private_data;
+
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ if (codec->reg_cache_step)
+ step = codec->reg_cache_step;
+
+ while (*start == ' ')
+ start++;
+ reg = simple_strtoul(start, &start, 16);
+ if ((reg >= codec->reg_cache_size) || (reg % step))
+ return -EINVAL;
+ while (*start == ' ')
+ start++;
+ if (strict_strtoul(start, 16, &value))
+ return -EINVAL;
+ codec->write(codec, reg, value);
+ return buf_size;
+}
+
+static const struct file_operations codec_reg_fops = {
+ .open = codec_reg_open_file,
+ .read = codec_reg_read_file,
+ .write = codec_reg_write_file,
+};
+
+static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
+{
+ codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
+ debugfs_root, codec,
+ &codec_reg_fops);
+ if (!codec->debugfs_reg)
+ printk(KERN_WARNING
+ "ASoC: Failed to create codec register debugfs file\n");
+
+ codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
+ debugfs_root,
+ &codec->pop_time);
+ if (!codec->debugfs_pop_time)
+ printk(KERN_WARNING
+ "Failed to create pop time debugfs file\n");
+}
+
+static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
+{
+ debugfs_remove(codec->debugfs_pop_time);
+ debugfs_remove(codec->debugfs_reg);
+}
+
+#else
+
+static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
+{
+}
+
+static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
+{
+}
+#endif
+
/**
* snd_soc_new_ac97_codec - initailise AC97 device
* @codec: audio codec
int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_card *card = socdev->card;
int ret = 0, i;
mutex_lock(&codec->mutex);
strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
/* create the pcms */
- for (i = 0; i < machine->num_links; i++) {
- ret = soc_new_pcm(socdev, &machine->dai_link[i], i);
+ for (i = 0; i < card->num_links; i++) {
+ ret = soc_new_pcm(socdev, &card->dai_link[i], i);
if (ret < 0) {
printk(KERN_ERR "asoc: can't create pcm %s\n",
- machine->dai_link[i].stream_name);
+ card->dai_link[i].stream_name);
mutex_unlock(&codec->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
/**
- * snd_soc_register_card - register sound card
+ * snd_soc_init_card - register sound card
* @socdev: the SoC audio device
*
* Register a SoC sound card. Also registers an AC97 device if the
*
* Returns 0 for success, else error.
*/
-int snd_soc_register_card(struct snd_soc_device *socdev)
+int snd_soc_init_card(struct snd_soc_device *socdev)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_card *card = socdev->card;
int ret = 0, i, ac97 = 0, err = 0;
- for (i = 0; i < machine->num_links; i++) {
- if (socdev->machine->dai_link[i].init) {
- err = socdev->machine->dai_link[i].init(codec);
+ for (i = 0; i < card->num_links; i++) {
+ if (card->dai_link[i].init) {
+ err = card->dai_link[i].init(codec);
if (err < 0) {
printk(KERN_ERR "asoc: failed to init %s\n",
- socdev->machine->dai_link[i].stream_name);
+ card->dai_link[i].stream_name);
continue;
}
}
- if (socdev->machine->dai_link[i].codec_dai->type ==
- SND_SOC_DAI_AC97_BUS)
+ if (card->dai_link[i].codec_dai->ac97_control)
ac97 = 1;
}
snprintf(codec->card->shortname, sizeof(codec->card->shortname),
- "%s", machine->name);
+ "%s", card->name);
snprintf(codec->card->longname, sizeof(codec->card->longname),
- "%s (%s)", machine->name, codec->name);
+ "%s (%s)", card->name, codec->name);
ret = snd_card_register(codec->card);
if (ret < 0) {
if (err < 0)
printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
+ soc_init_codec_debugfs(socdev->codec);
mutex_unlock(&codec->mutex);
out:
return ret;
}
-EXPORT_SYMBOL_GPL(snd_soc_register_card);
+EXPORT_SYMBOL_GPL(snd_soc_init_card);
/**
* snd_soc_free_pcms - free sound card and pcms
#endif
mutex_lock(&codec->mutex);
+ soc_cleanup_codec_debugfs(socdev->codec);
#ifdef CONFIG_SND_SOC_AC97_BUS
for (i = 0; i < codec->num_dai; i++) {
codec_dai = &codec->dai[i];
- if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) {
+ if (codec_dai->ac97_control && codec->ac97) {
soc_ac97_dev_unregister(codec);
goto free_card;
}
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
- if (dai->dai_ops.set_sysclk)
- return dai->dai_ops.set_sysclk(dai, clk_id, freq, dir);
+ if (dai->ops.set_sysclk)
+ return dai->ops.set_sysclk(dai, clk_id, freq, dir);
else
return -EINVAL;
}
int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
int div_id, int div)
{
- if (dai->dai_ops.set_clkdiv)
- return dai->dai_ops.set_clkdiv(dai, div_id, div);
+ if (dai->ops.set_clkdiv)
+ return dai->ops.set_clkdiv(dai, div_id, div);
else
return -EINVAL;
}
int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int pll_id, unsigned int freq_in, unsigned int freq_out)
{
- if (dai->dai_ops.set_pll)
- return dai->dai_ops.set_pll(dai, pll_id, freq_in, freq_out);
+ if (dai->ops.set_pll)
+ return dai->ops.set_pll(dai, pll_id, freq_in, freq_out);
else
return -EINVAL;
}
/**
* snd_soc_dai_set_fmt - configure DAI hardware audio format.
* @dai: DAI
- * @clk_id: DAI specific clock ID
* @fmt: SND_SOC_DAIFMT_ format value.
*
* Configures the DAI hardware format and clocking.
*/
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
- if (dai->dai_ops.set_fmt)
- return dai->dai_ops.set_fmt(dai, fmt);
+ if (dai->ops.set_fmt)
+ return dai->ops.set_fmt(dai, fmt);
else
return -EINVAL;
}
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int mask, int slots)
{
- if (dai->dai_ops.set_sysclk)
- return dai->dai_ops.set_tdm_slot(dai, mask, slots);
+ if (dai->ops.set_sysclk)
+ return dai->ops.set_tdm_slot(dai, mask, slots);
else
return -EINVAL;
}
*/
int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
{
- if (dai->dai_ops.set_sysclk)
- return dai->dai_ops.set_tristate(dai, tristate);
+ if (dai->ops.set_sysclk)
+ return dai->ops.set_tristate(dai, tristate);
else
return -EINVAL;
}
*/
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
{
- if (dai->dai_ops.digital_mute)
- return dai->dai_ops.digital_mute(dai, mute);
+ if (dai->ops.digital_mute)
+ return dai->ops.digital_mute(dai, mute);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
-static int __devinit snd_soc_init(void)
+/**
+ * snd_soc_register_card - Register a card with the ASoC core
+ *
+ * @param card Card to register
+ *
+ * Note that currently this is an internal only function: it will be
+ * exposed to machine drivers after further backporting of ASoC v2
+ * registration APIs.
+ */
+static int snd_soc_register_card(struct snd_soc_card *card)
+{
+ if (!card->name || !card->dev)
+ return -EINVAL;
+
+ INIT_LIST_HEAD(&card->list);
+ card->instantiated = 0;
+
+ mutex_lock(&client_mutex);
+ list_add(&card->list, &card_list);
+ snd_soc_instantiate_cards();
+ mutex_unlock(&client_mutex);
+
+ dev_dbg(card->dev, "Registered card '%s'\n", card->name);
+
+ return 0;
+}
+
+/**
+ * snd_soc_unregister_card - Unregister a card with the ASoC core
+ *
+ * @param card Card to unregister
+ *
+ * Note that currently this is an internal only function: it will be
+ * exposed to machine drivers after further backporting of ASoC v2
+ * registration APIs.
+ */
+static int snd_soc_unregister_card(struct snd_soc_card *card)
+{
+ mutex_lock(&client_mutex);
+ list_del(&card->list);
+ mutex_unlock(&client_mutex);
+
+ dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
+
+ return 0;
+}
+
+/**
+ * snd_soc_register_dai - Register a DAI with the ASoC core
+ *
+ * @param dai DAI to register
+ */
+int snd_soc_register_dai(struct snd_soc_dai *dai)
+{
+ if (!dai->name)
+ return -EINVAL;
+
+ /* The device should become mandatory over time */
+ if (!dai->dev)
+ printk(KERN_WARNING "No device for DAI %s\n", dai->name);
+
+ INIT_LIST_HEAD(&dai->list);
+
+ mutex_lock(&client_mutex);
+ list_add(&dai->list, &dai_list);
+ snd_soc_instantiate_cards();
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Registered DAI '%s'\n", dai->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_dai);
+
+/**
+ * snd_soc_unregister_dai - Unregister a DAI from the ASoC core
+ *
+ * @param dai DAI to unregister
+ */
+void snd_soc_unregister_dai(struct snd_soc_dai *dai)
+{
+ mutex_lock(&client_mutex);
+ list_del(&dai->list);
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Unregistered DAI '%s'\n", dai->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
+
+/**
+ * snd_soc_register_dais - Register multiple DAIs with the ASoC core
+ *
+ * @param dai Array of DAIs to register
+ * @param count Number of DAIs
+ */
+int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count)
+{
+ int i, ret;
+
+ for (i = 0; i < count; i++) {
+ ret = snd_soc_register_dai(&dai[i]);
+ if (ret != 0)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ for (i--; i >= 0; i--)
+ snd_soc_unregister_dai(&dai[i]);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_dais);
+
+/**
+ * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
+ *
+ * @param dai Array of DAIs to unregister
+ * @param count Number of DAIs
+ */
+void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ snd_soc_unregister_dai(&dai[i]);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
+
+/**
+ * snd_soc_register_platform - Register a platform with the ASoC core
+ *
+ * @param platform platform to register
+ */
+int snd_soc_register_platform(struct snd_soc_platform *platform)
+{
+ if (!platform->name)
+ return -EINVAL;
+
+ INIT_LIST_HEAD(&platform->list);
+
+ mutex_lock(&client_mutex);
+ list_add(&platform->list, &platform_list);
+ snd_soc_instantiate_cards();
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Registered platform '%s'\n", platform->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_platform);
+
+/**
+ * snd_soc_unregister_platform - Unregister a platform from the ASoC core
+ *
+ * @param platform platform to unregister
+ */
+void snd_soc_unregister_platform(struct snd_soc_platform *platform)
{
- printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
+ mutex_lock(&client_mutex);
+ list_del(&platform->list);
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Unregistered platform '%s'\n", platform->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
+
+/**
+ * snd_soc_register_codec - Register a codec with the ASoC core
+ *
+ * @param codec codec to register
+ */
+int snd_soc_register_codec(struct snd_soc_codec *codec)
+{
+ if (!codec->name)
+ return -EINVAL;
+
+ /* The device should become mandatory over time */
+ if (!codec->dev)
+ printk(KERN_WARNING "No device for codec %s\n", codec->name);
+
+ INIT_LIST_HEAD(&codec->list);
+
+ mutex_lock(&client_mutex);
+ list_add(&codec->list, &codec_list);
+ snd_soc_instantiate_cards();
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Registered codec '%s'\n", codec->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_codec);
+
+/**
+ * snd_soc_unregister_codec - Unregister a codec from the ASoC core
+ *
+ * @param codec codec to unregister
+ */
+void snd_soc_unregister_codec(struct snd_soc_codec *codec)
+{
+ mutex_lock(&client_mutex);
+ list_del(&codec->list);
+ mutex_unlock(&client_mutex);
+
+ pr_debug("Unregistered codec '%s'\n", codec->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
+
+static int __init snd_soc_init(void)
+{
+#ifdef CONFIG_DEBUG_FS
+ debugfs_root = debugfs_create_dir("asoc", NULL);
+ if (IS_ERR(debugfs_root) || !debugfs_root) {
+ printk(KERN_WARNING
+ "ASoC: Failed to create debugfs directory\n");
+ debugfs_root = NULL;
+ }
+#endif
+
return platform_driver_register(&soc_driver);
}
-static void snd_soc_exit(void)
+static void __exit snd_soc_exit(void)
{
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove_recursive(debugfs_root);
+#endif
platform_driver_unregister(&soc_driver);
}
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/jiffies.h>
-#include <linux/debugfs.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
module_param(dapm_status, int, 0);
MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
-static struct dentry *asoc_debugfs;
-
-static u32 pop_time;
-
-static void pop_wait(void)
+static void pop_wait(u32 pop_time)
{
if (pop_time)
schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
}
-static void pop_dbg(const char *fmt, ...)
+static void pop_dbg(u32 pop_time, const char *fmt, ...)
{
va_list args;
if (pop_time) {
vprintk(fmt, args);
- pop_wait();
+ pop_wait(pop_time);
}
va_end(args);
change = old != new;
if (change) {
- pop_dbg("pop test %s : %s in %d ms\n", widget->name,
- widget->power ? "on" : "off", pop_time);
+ pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n",
+ widget->name, widget->power ? "on" : "off",
+ codec->pop_time);
snd_soc_write(codec, widget->reg, new);
- pop_wait();
+ pop_wait(codec->pop_time);
}
pr_debug("reg %x old %x new %x change %d\n", widget->reg,
old, new, change);
struct snd_soc_dapm_widget *w)
{
int i, ret = 0;
- char name[32];
+ size_t name_len;
struct snd_soc_dapm_path *path;
/* add kcontrol */
continue;
/* add dapm control with long name */
- snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
- path->long_name = kstrdup (name, GFP_KERNEL);
+ name_len = 2 + strlen(w->name)
+ + strlen(w->kcontrols[i].name);
+ path->long_name = kmalloc(name_len, GFP_KERNEL);
if (path->long_name == NULL)
return -ENOMEM;
+ snprintf(path->long_name, name_len, "%s %s",
+ w->name, w->kcontrols[i].name);
+ path->long_name[name_len - 1] = '\0';
+
path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
path->long_name);
ret = snd_ctl_add(codec->card, path->kcontrol);
int snd_soc_dapm_sys_add(struct device *dev)
{
- int ret = 0;
-
if (!dapm_status)
return 0;
-
- ret = device_create_file(dev, &dev_attr_dapm_widget);
- if (ret != 0)
- return ret;
-
- asoc_debugfs = debugfs_create_dir("asoc", NULL);
- if (!IS_ERR(asoc_debugfs) && asoc_debugfs)
- debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs,
- &pop_time);
- else
- asoc_debugfs = NULL;
-
- return 0;
+ return device_create_file(dev, &dev_attr_dapm_widget);
}
static void snd_soc_dapm_sys_remove(struct device *dev)
if (dapm_status) {
device_remove_file(dev, &dev_attr_dapm_widget);
}
-
- if (asoc_debugfs)
- debugfs_remove_recursive(asoc_debugfs);
}
/* free all dapm widgets and resources */
return ret;
}
-/**
- * snd_soc_dapm_connect_input - connect dapm widgets
- * @codec: audio codec
- * @sink: name of target widget
- * @control: mixer control name
- * @source: name of source name
- *
- * Connects 2 dapm widgets together via a named audio path. The sink is
- * the widget receiving the audio signal, whilst the source is the sender
- * of the audio signal.
- *
- * This function has been deprecated in favour of snd_soc_dapm_add_routes().
- *
- * Returns 0 for success else error.
- */
-int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
- const char *control, const char *source)
-{
- return snd_soc_dapm_add_route(codec, sink, control, source);
-}
-EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
-
/**
* snd_soc_dapm_add_routes - Add routes between DAPM widgets
* @codec: codec
for (i = 0; i < num; i++) {
ret = snd_soc_dapm_new_control(codec, widget);
- if (ret < 0)
+ if (ret < 0) {
+ printk(KERN_ERR
+ "ASoC: Failed to create DAPM control %s: %d\n",
+ widget->name, ret);
return ret;
+ }
widget++;
}
return 0;
enum snd_soc_bias_level level)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_card *card = socdev->card;
int ret = 0;
- if (machine->set_bias_level)
- ret = machine->set_bias_level(machine, level);
+ if (card->set_bias_level)
+ ret = card->set_bias_level(card, level);
if (ret == 0 && codec->set_bias_level)
ret = codec->set_bias_level(codec, level);
void unregister_sound_midi(int unit)
{
- return sound_remove_unit(&chains[2], unit);
+ sound_remove_unit(&chains[2], unit);
}
EXPORT_SYMBOL(unregister_sound_midi);
void unregister_sound_dsp(int unit)
{
- return sound_remove_unit(&chains[3], unit);
+ sound_remove_unit(&chains[3], unit);
}
return NULL;
}
-int soundcore_open(struct inode *inode, struct file *file)
+static int soundcore_open(struct inode *inode, struct file *file)
{
int chain;
int unit = iminor(inode);