]> code.ossystems Code Review - openembedded-core.git/commitdiff
linux-rp-2.6.23: Add zyonite touchscreend driver forward port
authorRichard Purdie <richard@openedhand.com>
Wed, 13 Feb 2008 16:29:55 +0000 (16:29 +0000)
committerRichard Purdie <richard@openedhand.com>
Wed, 13 Feb 2008 16:29:55 +0000 (16:29 +0000)
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@3793 311d38ba-8fff-0310-9ca6-ca027cbcb966

meta/packages/linux/linux-rp-2.6.23/zylonite_mtd-r0.patch
meta/packages/linux/linux-rp-2.6.23/zylonite_touch-r0.patch [new file with mode: 0644]
meta/packages/linux/linux-rp_2.6.23.bb

index 231b3d76c9335417dc71f31415e9234f592101ae..cb5a9c5f72c7b05ea6ab6a8be7117b2ad2693dad 100644 (file)
@@ -4,8 +4,8 @@ Flash driver forward ported to 2.6.14
 
 Index: linux-2.6.23/drivers/mtd/nand/Kconfig
 ===================================================================
---- linux-2.6.23.orig/drivers/mtd/nand/Kconfig 2008-02-12 18:02:36.000000000 +0000
-+++ linux-2.6.23/drivers/mtd/nand/Kconfig      2008-02-12 18:03:07.000000000 +0000
+--- linux-2.6.23.orig/drivers/mtd/nand/Kconfig 2007-10-09 21:31:38.000000000 +0100
++++ linux-2.6.23/drivers/mtd/nand/Kconfig      2008-02-13 00:59:45.000000000 +0000
 @@ -223,6 +223,10 @@
        tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
        depends on ARCH_PXA
@@ -19,8 +19,8 @@ Index: linux-2.6.23/drivers/mtd/nand/Kconfig
        depends on BASLER_EXCITE
 Index: linux-2.6.23/drivers/mtd/nand/Makefile
 ===================================================================
---- linux-2.6.23.orig/drivers/mtd/nand/Makefile        2008-02-12 18:02:36.000000000 +0000
-+++ linux-2.6.23/drivers/mtd/nand/Makefile     2008-02-12 18:03:27.000000000 +0000
+--- linux-2.6.23.orig/drivers/mtd/nand/Makefile        2007-10-09 21:31:38.000000000 +0100
++++ linux-2.6.23/drivers/mtd/nand/Makefile     2008-02-13 00:59:45.000000000 +0000
 @@ -19,6 +19,7 @@
  obj-$(CONFIG_MTD_NAND_H1900)          += h1910.o
  obj-$(CONFIG_MTD_NAND_RTC_FROM4)      += rtc_from4.o
@@ -32,7 +32,7 @@ Index: linux-2.6.23/drivers/mtd/nand/Makefile
 Index: linux-2.6.23/drivers/mtd/nand/mhn_nand.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23/drivers/mtd/nand/mhn_nand.c   2008-02-12 23:54:00.000000000 +0000
++++ linux-2.6.23/drivers/mtd/nand/mhn_nand.c   2008-02-13 00:59:45.000000000 +0000
 @@ -0,0 +1,3869 @@
 +/*
 + *  drivers/mtd/nand/mhn_nand.c
@@ -3905,8 +3905,8 @@ Index: linux-2.6.23/drivers/mtd/nand/mhn_nand.c
 +
 Index: linux-2.6.23/arch/arm/mach-pxa/zylonite.c
 ===================================================================
---- linux-2.6.23.orig/arch/arm/mach-pxa/zylonite.c     2008-02-12 21:12:29.000000000 +0000
-+++ linux-2.6.23/arch/arm/mach-pxa/zylonite.c  2008-02-13 00:50:30.000000000 +0000
+--- linux-2.6.23.orig/arch/arm/mach-pxa/zylonite.c     2008-02-13 00:59:45.000000000 +0000
++++ linux-2.6.23/arch/arm/mach-pxa/zylonite.c  2008-02-13 09:11:02.000000000 +0000
 @@ -29,6 +29,8 @@
  #include "generic.h"
  
@@ -3916,7 +3916,7 @@ Index: linux-2.6.23/arch/arm/mach-pxa/zylonite.c
  int gpio_eth_irq;
  
  int lcd_id;
-@@ -54,6 +56,11 @@
+@@ -54,6 +56,16 @@
        .resource       = smc91x_resources,
  };
  
@@ -3924,11 +3924,16 @@ Index: linux-2.6.23/arch/arm/mach-pxa/zylonite.c
 +      .name           = "monahans-nand-flash",
 +      .id             = -1,
 +};
++
++static struct platform_device touch_device = {
++      .name           = "pxa2xx-touch",
++      .id             = -1,
++};
 +
  #if defined(CONFIG_FB_PXA) || (CONFIG_FB_PXA_MODULES)
  static void zylonite_backlight_power(int on)
  {
-@@ -96,7 +103,7 @@
+@@ -96,7 +108,7 @@
  };
  
  static struct pxafb_mode_info sharp_ls037_modes[] = {
@@ -3937,7 +3942,7 @@ Index: linux-2.6.23/arch/arm/mach-pxa/zylonite.c
                .pixclock       = 158000,
                .xres           = 240,
                .yres           = 320,
-@@ -109,8 +116,8 @@
+@@ -109,8 +121,8 @@
                .lower_margin   = 3,
                .sync           = 0,
        },
@@ -3948,7 +3953,7 @@ Index: linux-2.6.23/arch/arm/mach-pxa/zylonite.c
                .xres           = 480,
                .yres           = 640,
                .bpp            = 16,
-@@ -137,6 +144,11 @@
+@@ -137,6 +149,11 @@
        /* backlight GPIO: output, default on */
        gpio_direction_output(gpio_backlight, 1);
  
@@ -3960,20 +3965,35 @@ Index: linux-2.6.23/arch/arm/mach-pxa/zylonite.c
        if (lcd_id & 0x20) {
                set_pxa_fb_info(&zylonite_sharp_lcd_info);
                return;
-@@ -169,6 +181,8 @@
+@@ -169,6 +186,8 @@
        smc91x_resources[1].start = gpio_to_irq(gpio_eth_irq);
        smc91x_resources[1].end   = gpio_to_irq(gpio_eth_irq);
        platform_device_register(&smc91x_device);
 +      platform_device_register(&nand_device);
-+      printk(KERN_ERR "Nand device registered\n");
++      platform_device_register(&touch_device);
  
        zylonite_init_lcd();
  }
 Index: linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa300.c
 ===================================================================
---- linux-2.6.23.orig/arch/arm/mach-pxa/zylonite_pxa300.c      2008-02-12 20:52:26.000000000 +0000
-+++ linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa300.c   2008-02-13 00:26:37.000000000 +0000
-@@ -104,6 +104,30 @@
+--- linux-2.6.23.orig/arch/arm/mach-pxa/zylonite_pxa300.c      2008-02-13 00:59:45.000000000 +0000
++++ linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa300.c   2008-02-13 14:01:13.000000000 +0000
+@@ -62,12 +62,12 @@
+       GPIO110_UART3_RXD,
+       /* AC97 */
+-      GPIO23_AC97_nACRESET,
++      /*GPIO23_AC97_nACRESET,
+       GPIO24_AC97_SYSCLK,
+       GPIO29_AC97_BITCLK,
+       GPIO25_AC97_SDATA_IN_0,
+       GPIO27_AC97_SDATA_OUT,
+-      GPIO28_AC97_SYNC,
++      GPIO28_AC97_SYNC,*/
+       /* Keypad */
+       GPIO107_KP_DKIN_0,
+@@ -104,6 +104,41 @@
        /* Ethernet */
        GPIO2_nCS3,
        GPIO99_GPIO,
@@ -4001,10 +4021,21 @@ Index: linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa300.c
 +      MFP_CFG_X(DF_IO12, AF1, DS08X, PULL_LOW),
 +      MFP_CFG_X(DF_IO13, AF1, DS08X, PULL_LOW),
 +      MFP_CFG_X(DF_IO14, AF1, DS08X, PULL_LOW),
++
++      /* AC97 */
++      MFP_CFG_X(GPIO23, AF1, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO27, AF1, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO28, AF1, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO29, AF1, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO25, AF1, DS03X, PULL_LOW),
++
++      MFP_CFG_X(GPIO26, AF0, DS01X, PULL_LOW), /* Interrupt */
++      MFP_CFG_X(GPIO24, AF0, DS03X, PULL_LOW), /*SYSCLK external */
++      MFP_CFG_X(GPIO11, AF0, DS01X, PULL_LOW),
  };
  
  static mfp_cfg_t pxa310_mfp_cfg[] __initdata = {
-@@ -163,6 +187,9 @@
+@@ -163,6 +198,9 @@
                pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
  }
  
@@ -4014,7 +4045,7 @@ Index: linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa300.c
  void __init zylonite_pxa300_init(void)
  {
        if (cpu_is_pxa300() || cpu_is_pxa310()) {
-@@ -174,6 +201,8 @@
+@@ -174,6 +212,8 @@
  
                /* GPIO pin assignment */
                gpio_backlight = mfp_to_gpio(MFP_PIN_GPIO20);
@@ -4025,8 +4056,8 @@ Index: linux-2.6.23/arch/arm/mach-pxa/zylonite_pxa300.c
        if (cpu_is_pxa300()) {
 Index: linux-2.6.23/drivers/video/pxafb.c
 ===================================================================
---- linux-2.6.23.orig/drivers/video/pxafb.c    2008-02-13 00:05:42.000000000 +0000
-+++ linux-2.6.23/drivers/video/pxafb.c 2008-02-13 00:06:02.000000000 +0000
+--- linux-2.6.23.orig/drivers/video/pxafb.c    2008-02-13 00:59:45.000000000 +0000
++++ linux-2.6.23/drivers/video/pxafb.c 2008-02-13 00:59:45.000000000 +0000
 @@ -1543,9 +1543,9 @@
          if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
                  dev_warn(&dev->dev, "machine LCCR0 setting contains illegal bits: %08x\n",
@@ -4042,8 +4073,8 @@ Index: linux-2.6.23/drivers/video/pxafb.c
             (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
 Index: linux-2.6.23/include/asm-arm/arch-pxa/mfp-pxa300.h
 ===================================================================
---- linux-2.6.23.orig/include/asm-arm/arch-pxa/mfp-pxa300.h    2008-02-13 00:44:38.000000000 +0000
-+++ linux-2.6.23/include/asm-arm/arch-pxa/mfp-pxa300.h 2008-02-13 00:49:38.000000000 +0000
+--- linux-2.6.23.orig/include/asm-arm/arch-pxa/mfp-pxa300.h    2008-02-13 00:59:45.000000000 +0000
++++ linux-2.6.23/include/asm-arm/arch-pxa/mfp-pxa300.h 2008-02-13 00:59:45.000000000 +0000
 @@ -175,13 +175,13 @@
  #define GPIO68_LCD_LDD_14     MFP_CFG_DRV(GPIO68, AF1, DS01X)
  #define GPIO69_LCD_LDD_15     MFP_CFG_DRV(GPIO69, AF1, DS01X)
diff --git a/meta/packages/linux/linux-rp-2.6.23/zylonite_touch-r0.patch b/meta/packages/linux/linux-rp-2.6.23/zylonite_touch-r0.patch
new file mode 100644 (file)
index 0000000..1c00696
--- /dev/null
@@ -0,0 +1,1548 @@
+Index: linux-2.6.23/drivers/input/touchscreen/Kconfig
+===================================================================
+--- linux-2.6.23.orig/drivers/input/touchscreen/Kconfig        2008-02-13 01:12:29.000000000 +0000
++++ linux-2.6.23/drivers/input/touchscreen/Kconfig     2008-02-13 01:13:20.000000000 +0000
+@@ -54,6 +54,12 @@
+         To compile this driver as a module, choose M here: the
+         module will be called corgi_ts.
++config TOUCHSCREEN_ZYLONITE
++      tristate "Zylonite touchscreen driver"
++      default y
++      help
++        Say Y here for the Zylonite touchscreen driver
++
+ config TOUCHSCREEN_FUJITSU
+       tristate "Fujitsu serial touchscreen"
+       select SERIO
+Index: linux-2.6.23/drivers/input/touchscreen/Makefile
+===================================================================
+--- linux-2.6.23.orig/drivers/input/touchscreen/Makefile       2008-02-13 01:12:29.000000000 +0000
++++ linux-2.6.23/drivers/input/touchscreen/Makefile    2008-02-13 01:13:38.000000000 +0000
+@@ -19,3 +19,4 @@
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)    += touchwin.o
+ obj-$(CONFIG_TOUCHSCREEN_UCB1400)     += ucb1400_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_TSC2101)     += tsc2101_ts.o
++obj-$(CONFIG_TOUCHSCREEN_ZYLONITE)    += zylonite-ts.o
+Index: linux-2.6.23/drivers/input/touchscreen/zylonite-ts.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23/drivers/input/touchscreen/zylonite-ts.c       2008-02-13 16:19:15.000000000 +0000
+@@ -0,0 +1,1517 @@
++/*
++ *  drivers/input/touchscreen/mhn_audio_touch.c.
++ *
++ *  Author:   bridge.wu@marvell.com
++ *  Created:  Nov 17, 2006
++ *  Copyright:        Marvell Corporation.
++ *
++ *  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/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++
++#include <asm/semaphore.h>
++#include <asm/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/mfp.h>
++//#include <asm/arch/ipmc.h>
++#include <linux/suspend.h>
++#include <linux/spinlock.h>
++
++//#include <asm/arch/codec/acodec.h>
++//#include <asm/arch/mhn_audio_plat.h>
++
++#define OSCC               __REG(0x41350000)  /* Oscillator Configuration Register */
++#define AC97_DIV      __REG(0x41340014)
++
++#define ALSA_ZY_CARD_DEBUG
++#undef ALSA_ZY_CARD_DEBUG
++
++#define WM_9713_ID  0x4C13 /* this should be the 7E register value */
++
++#ifdef ALSA_ZY_CARD_DEBUG
++#define dbg(format, arg...) printk(KERN_DEBUG format, ##arg)
++#else
++#define dbg(format, arg...)
++#endif
++
++#define DEBUG
++#undef DEBUG
++#ifdef DEBUG
++unsigned int start_time;
++unsigned int end_time;
++unsigned int time;
++#define PRINT_TIME() do {\
++        time = ((end_time > start_time))?\
++                (end_time - start_time)*100/325:\
++                (0xffffffff - start_time + end_time)*100/325;\
++        printk("\n%s:%dus\n", __FUNCTION__, time);\
++} while(0)
++#endif
++
++
++
++
++/* 9713 specific
++ *    Register Name                   Index
++ */
++#define RESET                         0X00
++#define SPEAKER_VOLUME                        0X02
++#define HEADPHONE_VOLUME              0X04
++#define OUT3_OUT4_VOLUME              0X06
++#define MONOVOL_MONOINPGA_ROUTE               0X08
++#define LINE_IN_PGA_VOL_ROUTE         0X0A
++#define DAC_PGA_VOL_ROUTE             0X0C
++#define MIC_PGA_VOLUME                        0X0E
++#define MIC_ROUTING                   0X10
++#define REC_PGA_VOL                   0X12
++#define REC_ROUTE_MUX_SEL             0X14
++#define PCBEEP_VOL_ROUTE              0X16
++#define VXDAC_VOLUME_ROUTE            0X18
++#define AUX_DAC_VOL_ROUTE             0X1A
++#define OUTPUT_PGA_MUX                        0X1C
++#define DAC_3D_CTRL_INV_MUX_SEL               0X1E
++#define DAC_TONE_CTRL                 0X20
++#define MIC_BIAS                      0X22
++#define OUTPUT_VOL_MAPPING_JACK               0X24
++#define POWERDOWN_CTRL_STAT           0X26
++#define EXTENDED_AUD_ID                       0X28
++#define EXTENDED_AUD_STAT_CTRL        0X2A
++#define AUDIO_DAC_RATE                        0X2C
++#define AUX_DAC_RATE                  0X2E
++#define AUDIO_ADC_RATE                        0X32
++#define PCM_CODEC_CTRL                        0X36
++#define SPDIF_CTRL                    0X3A
++#define POWER_DOWN_1                  0X3C
++#define POWER_DOWN_2                  0X3E
++#define GENERAL_PURPOSE_WM_13         0X40
++#define FAST_POWERUP_CTRL             0X42
++#define MCLK_PLL_CTRL_1                       0X44
++#define MCLK_PLL_CTRL_2                       0X46
++#define GPIO_PIN_CFG                  0X4C
++#define GPIO_PIN_POL_TYPE             0X4E
++#define GPIO_PIN_STICKY               0X50
++#define GPIO_PIN_WAKEUP                       0X52
++#define GPIO_PIN_STATUS                       0X54
++#define GPIO_PIN_SHARING              0X56
++#define GPIO_PULL_UP_DOWN_CTRL                0X58
++#define ADD_FUNC_1                    0X5A
++#define ADD_FUNC_2                    0X5C
++#define ALC_CTRL                      0X60
++#define ALC_NOISE_GATE_CTRL           0X62
++#define AUX_DAC_INPUT_CTRL            0X64
++#define TEST_REG_1                    0X68
++#define TEST_REG_2                    0X6A
++#define TEST_REG_3                    0X6C
++#define TEST_REG_4                    0X6E
++#define DIGITIZER_1_WM13              0x74
++#define DIGITIZER_2_WM13              0x76
++#define DIGITIZER_3_WM13              0x78
++#define DIGITIZER_READ_BACK           0x7a
++#define VENDOR_ID1                    0x7c
++#define VENDOR_ID2                    0x7e
++
++#define ZY_TOUCH_SAMPLE_X 1
++#define ZY_TOUCH_SAMPLE_Y 2
++
++#define ZY_EVENT_TYPE_NONE                    0
++#define ZY_EVENT_TYPE_PDN                     1
++
++
++typedef enum _zy_acodec_error_t {
++    ZY_ACODEC_SUCCESS = 0,    /* successful completion of a function */
++    ZY_ACODEC_GENERAL_SW_ERR, /* null pointer to registers or other software error */
++    ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT, /* time-out for waiting for respponse */
++    ZY_ACODEC_SAMPLERATE_NOT_SUPPORTED, /* the sample rate is not supported either in controller or codec */
++    ZY_ACODEC_FEATURE_NO_SUPPORTED, /* this codec feature is not supported  */
++    ZY_ACODEC_GENERAL_HW_ERR ,/* other hardware error besides time out */
++    ZY_ACODEC_ROUTE_NO_SUPPORTED, /* the codec can not set the route required */
++    ZY_ACODEC_SLEEP /* the codec is sleep */
++} zy_acodec_error_t;
++
++typedef unsigned int zy_acodec_device_id_t;
++
++typedef enum _codec_state {
++      ZY_CODEC_SLEEP  = 0,
++      ZY_CODEC_WAKEUP = 1
++} acodec_state_t;
++
++typedef enum {
++       ZY_FM = 0,
++       ZY_MIC1 = 1,
++       ZY_MIC2 = 2,
++       ZY_SPEAKER =3,
++       ZY_HEADSET =4,
++       ZY_HANDSET =5,
++} vol_port_type_t;
++
++typedef struct _context_t {
++      int  use_count;                 /* probe/remove and suspend/resume usage count, sync among multiple devices */
++      zy_acodec_device_id_t acodec_id;/* - an ID that uniquely identifies the codec to be used */
++      unsigned long init_number;      /* used by driver to track whether it is inited or not */
++
++      void *p_voice_reg;              /* pointer to Monahans registers that has PCM interface to codec */
++      void *p_hifi_reg;               /* pointer to Monahans registers that has hifi interface to codec */
++      void *p_ctrl_reg;               /* pointer to Monahans registers that has control interface to codec */
++      int  *p_ost_regs;               /* needed for time out */
++      void *p_save_memory;            /* pointer to a memory region to save context while suspend */
++      void *p_zy_scenario;            /* pointer to the scenario data structure  */
++      long u_max_read_write_time_out_ms;/* input the max time to wait in milliseconds before giving up on a read or write operation */
++      long u_max_setup_time_out_ms;   /* input the maximum time in milliseconds to wait during initial setup of the ACODEC controller and codec */
++
++      /* member functions these pointers must be set by */
++      zy_acodec_error_t (* g_pfn_codec_specific_init)      (struct _context_t *p_device_context);
++      zy_acodec_error_t (* g_pfn_codec_specific_dinit)    (struct _context_t *p_device_context);
++      zy_acodec_error_t (* g_pfn_acodec_read)             (struct _context_t *p_dev_context, unsigned short reg_addr, unsigned short *p_reg_value);
++      zy_acodec_error_t (* g_pfn_acodec_write)            (struct _context_t *p_dev_context, unsigned short reg_addr, unsigned short reg_value);
++
++      /* add for route */
++      zy_acodec_error_t (* g_pfn_set_route)           (struct _context_t *p_device_context, unsigned short * rout_map ,unsigned short* current_map);
++      /* add for sleep the codec */
++      zy_acodec_error_t (* g_pfn_sleep_codec)           (struct _context_t *p_device_context);
++      /* add for Wake up the codec */
++      zy_acodec_error_t (* g_pfn_wake_codec)           (struct _context_t *p_device_context);
++      /* add for get codec state */
++      zy_acodec_error_t (* g_pfn_get_state)           (struct _context_t *p_device_context, acodec_state_t *p_state);
++      /* add for volume */
++      zy_acodec_error_t (* g_pfn_get_vol)(struct _context_t *p_device_context, vol_port_type_t port,  unsigned short *gain_in_db);
++      zy_acodec_error_t (* g_pfn_set_vol)(struct _context_t *p_device_context, vol_port_type_t port,  unsigned short gain_in_db);
++
++        void (* g_pfn_get_event)(struct _context_t *p_device_context, unsigned char * event_type);
++        void (* g_pfn_event_ack)(struct _context_t *p_device_context, unsigned char event_type);
++        zy_acodec_error_t (* g_pfn_enable_touch)(struct _context_t *p_device_context);
++        zy_acodec_error_t (* g_pfn_disable_touch)(struct _context_t *p_device_context);
++} zy_acocec_context_t, *p_zy_acocec_context_t;
++
++
++
++
++
++static p_zy_acocec_context_t p_zy_codec_ctxt = NULL;
++
++#include <linux/input.h>
++//#include <asm/arch/codec/wm9713.h>
++
++#define PEN_DOWN              1
++#define PEN_UP                        0
++#define TS_SAMPLE_INTERVAL    1
++
++typedef struct {
++      struct input_dev *idev;
++      struct timer_list *timer;
++      int  use_count;
++} codec_zy_ts_t;
++
++codec_zy_ts_t codec_zy_ts;
++
++static struct input_dev *codec_zy_ts_input;
++
++#ifdef CONFIG_PM
++static volatile int touch_suspend = 0 ;
++#endif
++
++#define ZY_AC97_CODEC_REGS_NUM        0x40
++
++typedef struct
++{  //   Register symbol     // Usage
++    volatile unsigned long pocr;           // PCM Out Control Register
++    volatile unsigned long picr;           // PCM In Control Register
++    volatile unsigned long mccr;           // Mic In Control Register
++    volatile unsigned long gcr;            // Global Control Register
++    volatile unsigned long posr;           // PCM Out Status Register
++    volatile unsigned long pisr;           // PCM In Status Register
++    volatile unsigned long mcsr;           // Mic In Status Register
++    volatile unsigned long gsr;            // Global Status Register
++    volatile unsigned long car;            // CODEC Access Register
++    volatile unsigned long pcscr;          // PCM Surround Out Control
++    volatile unsigned long pcssr;          // PCM Surround Out Status
++    volatile unsigned long pcsdr;          // PCM Surround Out Data
++    volatile unsigned long pcclcr;         // PCM Center/LFE Out Control
++    volatile unsigned long pcclsr;         // PCM Center/LFE Out Status
++    volatile unsigned long pccldr;         // PCM Center/LFE Out Data
++    volatile unsigned long reserved1;       //
++    volatile unsigned long pcdr;           // PCM FIFO Data Register
++    volatile unsigned long reserved2 [0x7];      // 0x4050-0044 through 0x4050-005C
++    volatile unsigned long mcdr;           // Mic-in FIFO Data Register
++    volatile unsigned long reserved3 [0x27];   // 0x4050-0064 through 0x4050-00FC
++    volatile unsigned long mocr;           // MODEM Out Control Register
++    volatile unsigned long reserved4;
++    volatile unsigned long micr;           // MODEM In Control Register
++    volatile unsigned long reserved5;
++    volatile unsigned long mosr;           // MODEM Out Status Register
++    volatile unsigned long reserved6;
++    volatile unsigned long misr;           // MODEM In Status Register
++    volatile unsigned long reserved7 [0x9];      // 0x4050-011C through 0x4050-013C
++    volatile unsigned long modr;           // MODEM FIFO Data Register
++    volatile unsigned long reserved8 [0x2F];   // 0x4050-0144 through 0x4050-01FC
++                            // Primary Audio CODEC registers access
++    volatile unsigned long codec_regs_primary_aud   [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 01 Audio CODEC registers access
++    volatile unsigned long codec_regs_secondary_aud [ZY_AC97_CODEC_REGS_NUM];
++                            // Primary MODEM CODEC registers access
++    volatile unsigned long codec_regs_primary_mdm   [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 01 MODEM CODEC registers access
++    volatile unsigned long codec_regs_secondary_mdm [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 10 MODEM CODEC registers access
++    volatile unsigned long codec_regs_third_mdm [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 11 MODEM CODEC registers access
++    volatile unsigned long codec_regs_fouth_mdm [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 10 Audio CODEC registers access
++    volatile unsigned long codec_regs_third_aud [ZY_AC97_CODEC_REGS_NUM];
++                            // Secondary ID 11 Audio CODEC registers access
++    volatile unsigned long codec_regs_fouth_aud [ZY_AC97_CODEC_REGS_NUM];
++}  zy_ac97_acodec_t, *p_zy_ac97acodec_t ;
++
++
++/* Constants for the Global Control Register and Global Status Register */
++
++// AC97 Global Control Register bit mask constants
++
++#define ZY_AC97_GCR_GIE_MSK          (1u << 0 )
++#define ZY_AC97_GCR_COLD_RESET_MSK   (1u << 1 )
++#define ZY_AC97_GCR_WARM_RESET_MSK   (1u << 2 )
++#define ZY_AC97_GCR_LINK_OFF_MSK     (1u << 3 )
++#define ZY_AC97_GCR_PCRSM_IEN_MSK    (1u << 4 )
++#define ZY_AC97_GCR_SCRSM_IEN_MSK    (1u << 5 )
++#define ZY_AC97_GCR_PCRDY_IEN_MSK    (1u << 8 )
++#define ZY_AC97_GCR_SCRDY_IEN_MSK    (1u << 9 )
++#define ZY_AC97_GCR_SDONE_IE_MSK     (1u << 18)
++#define ZY_AC97_GCR_CDONE_IE_MSK     (1u << 19)
++#define ZY_AC97_GCR_nDMAEN_MSK       (1u << 24)
++#define ZY_AC97_GCR_CLKBPB_MSK       (1u << 31)
++#define ZY_AC97_GCR_FRCRST_MSK       (1u << 30)
++// Global Status Register bit mask constants
++
++#define ZY_AC97_GSR_GSCI_MSK       (1u << 0 )
++#define ZY_AC97_GSR_MIINT_MSK      (1u << 1 )
++#define ZY_AC97_GSR_MOINT_MSK      (1u << 2 )
++#define ZY_AC97_GSR_ACOFFD_MSK     (1u << 3 )
++#define ZY_AC97_GSR_PIINT_MSK      (1u << 5 )
++#define ZY_AC97_GSR_POINT_MSK      (1u << 6 )
++#define ZY_AC97_GSR_MINT_MSK       (1u << 7 )
++#define ZY_AC97_GSR_PCRDY_MSK      (1u << 8 )
++#define ZY_AC97_GSR_SCRDY_MSK      (1u << 9 )
++#define ZY_AC97_GSR_PCRSM_MSK      (1u << 10)
++#define ZY_AC97_GSR_SCRSM_MSK      (1u << 11)
++#define ZY_AC97_GSR_SLT12_BITS_MSK (7u << 12)
++#define ZY_AC97_GSR_RCS_ERR_MSK    (1u << 15)
++#define ZY_AC97_GSR_SDONE_MSK      (1u << 18)
++#define ZY_AC97_GSR_CDONE_MSK      (1u << 19)
++
++
++// Bit mask and values for CAIP bit in car register.
++#define ZY_AC97_CAR_CAIP_MSK       (0x1<<0)
++#define ZY_AC97_CAR_CAIP_LOCKED    (0x1<<0)
++#define ZY_AC97_CAR_CAIP_CLEAR     (0<<0)
++
++/* Constants for FIFO status reporting and control */
++
++// One bit location is used to report FIFO error conditions and clear
++//  interrupts on those conditions in the various non-global status registers.
++
++// ZY_AC97_FIFOSTAT_FIFOE is used in:
++                                                // posr
++                                                // pisr
++                                                // mcsr
++                                                // mosr
++                                                // misr
++
++#define ZY_AC97_FIFOSTAT_FIFOE  (1u << 4)
++#define ZY_AC97_FIFOSTAT_EOC    (1u << 3)
++#define ZY_AC97_FIFOSTAT_FSR    (1u << 2)
++
++// A different bit location is used to enable or disable interrupts based on
++//  FIFO error conditions in the various non-global control registers.
++
++// ZY_AC97_FIFOCTRL_FEIE is used in:
++                                                // pocr
++                                                // picr
++                                                // mccr
++                                                // mocr
++                                                // micr
++
++#define ZY_AC97_FIFOCTRL_FEIE  (1u << 3)
++#define ZY_AC97_FIFOCTRL_FSRIE (1u << 1)
++
++/*
++*******************************************************************************
++    AC'97 Codec Registers Location and Bit Definition
++*******************************************************************************
++*/
++
++/* */
++
++    // Includes symbolic values for certain proprietary register asssignments
++    //   in AC'97 devices that might be used with ZY_AC97.
++
++    // Valid for subset of R 2.1 specification.
++    // Leading "e" in comment means it is an "expanded" register definition as
++    //  found in one or more of the Appendices A-D of the R 2.1 specification.
++    //  Appendix identifier will immediately follow the "e", such as "eA"
++    // R/O indicates read-only
++    // Registers not supported by the assumed controller will be commented out.
++
++#define    ZY_AC97_CR_RESET_ID             0x00  // RESET CODEC TO DEFAULT, get ID info
++#define    ZY_AC97_CR_MASTER_VOLUME        0x02  // LINE OUT VOLUME
++#define    ZY_AC97_CR_HEADPHONE_VOLUME     0x04  //
++#define    ZY_AC97_CR_MASTER_VOLUME_MONO   0x06  //
++#define    ZY_AC97_CR_MASTER_TONE_R_L      0x08  //
++#define    ZY_AC97_CR_PC_BEEP_VOLUME       0x0A  //
++#define    ZY_AC97_CR_PHONE_VOLUME         0x0C  //
++#define    ZY_AC97_CR_MIC_VOLUME           0x0E  //   micrOPHONE VOLUME/ AGC
++#define    ZY_AC97_CR_LINE_IN_VOLUME       0x10  //   LINE IN VOLUME
++#define    ZY_AC97_CR_CD_VOLUME            0x12  //
++#define    ZY_AC97_CR_VIDEO_VOLUME         0x14  //
++#define    ZY_AC97_CR_AUX_VOLUME           0x16  //
++#define    ZY_AC97_CR_PCM_OUT_VOLUME       0x18  //
++#define    ZY_AC97_CR_RECORD_SELECT        0x1A  //   SELECT LINE IN OR micrOPHONE
++#define    ZY_AC97_CR_RECORD_GAIN          0x1C  //
++#define    ZY_AC97_CR_RECORD_GAIN_MIC      0x1E  //
++#define    ZY_AC97_CR_GENERAL_PURPOSE      0x20  //
++#define    ZY_AC97_CR_CONTROL_3D           0x22  //
++#define    ZY_AC97_CR_POWERDOWN_CTRL_STAT  0x26  //   POWER MANAGEMENT
++#define    ZY_AC97_CR_E_AUDIO_ID           0x28  // eA Extended audio sprt info, R/O
++#define    ZY_AC97_CR_E_AUDIO_CTRL_STAT    0x2A  // eA Extended audio stat + control
++
++//
++// Audio Sample Rate Control Registers, 0x2C - 0x34
++//
++                                           // eA PCM Front DAC rate control
++#define    ZY_AC97_CR_E_ASR_PCM_FRNT_DAC_RT 0x2C  //  (output slots 3, 4, 6)
++#define    ZY_AC97_CR_E_ASR_PCM_LR_ADC_RT   0x32  // eA PCM L+R ADC rate control (3+4)
++#define    ZY_AC97_CR_E_ASR_MIC_ADC_RT      0x34  // eA PCM Mic ADC rate control (5)
++
++
++#define    ZY_AC97_CR_E_MDM_GPIO_PIN_STAT     0x54
++//
++// 5Ah-7Ah: Vendor Reserved
++//
++//
++// 7Ch-7Eh: Vendor ID registers.  Optional but standardized for Plug'n'Play
++//
++#define    ZY_AC97_CR_VENDOR_ID1         0x7C
++#define    ZY_AC97_CR_VENDOR_ID2         0x7E
++
++#define    ZY_AC97_CR_MAX               ZY_AC97_CR_VENDOR_ID2
++
++#define    ZY_AC97_CR_END_OF_LIST       (ZY_AC97_CR_MAX +  2)
++
++
++
++/* Other Constants */
++
++// For accessing the Codec mixer registers, each increment of one 32-bit word
++//  in processor space increments the addressed mixer register by two.
++// This does not cause any ambiguities because only even mixer register
++//  addresses are currently supported (AC '97 spec, R 2.2)
++#define ZY_AC97_CODEC_REGS_PER_WORD           2
++
++/* Default timeout and holdtime settings */
++
++// timeout in reading and writing codec registers through AC link
++#define ZY_AC97_RW_TIMEOUT_DEF                200     //unit is us
++
++// timeout in waiting for codec's ready signal during setup process
++#define ZY_AC97_SETUP_TIMEOUT_DEF             500     //unit is us
++
++// timeout in waiting for locking the link successfully
++#define ZY_AC97_LOCK_TIMEOUT_DEF              300     //unit is us
++
++// timeout in shutting down the link
++#define ZY_AC97_LINKOFF_TIMEOUT_DEF           500     //unit is us
++
++// holdtime for keeping nReset signal active(low) in AC link
++#define ZY_AC97_COLD_HOLDTIME                 100     //unit is us
++
++/*
++*******************************************************************************
++  ZY AC97 data structure used in function interface
++*******************************************************************************
++*/
++
++typedef struct
++{
++    unsigned long pocr;           // PCM Out Control Register
++    unsigned long picr;           // PCM In Control Register
++    unsigned long mccr;           // Mic In Control Register
++    unsigned long gcr;            // Global Control Register
++    unsigned long pcscr;          // PCM Surround Out Control
++    unsigned long pcclcr;         // PCM Center/LFE Out Control
++    unsigned long mocr;           // MODEM Out Control Register
++    unsigned long micr;           // MODEM In Control Register
++}zy_ac97_save_context_t;
++
++
++#define AC97_SAVE_CONTEXT_SIZE (sizeof(zy_ac97_save_context_t))
++
++static int zy_ac97_acodec_link_lock(p_zy_ac97acodec_t p_ac97_reg)
++{
++      int             status = 1;
++      volatile unsigned long  car_tmp;
++
++      car_tmp = p_ac97_reg->car;
++      if (car_tmp & ZY_AC97_CAR_CAIP_MSK)     /*  "1" in CAIP bit means lock failed. */
++      {
++              status = 0;
++      }
++      return (status);
++}
++
++
++zy_acodec_error_t zy_ac97_acodec_write (zy_acocec_context_t *p_dev_context, unsigned short offset, unsigned short data)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      int                     got_link;
++      unsigned long           time_remaining;
++      volatile unsigned long *        p_codec_reg;
++      p_zy_ac97acodec_t p_ac97_reg = (p_zy_ac97acodec_t)(p_dev_context->p_ctrl_reg);
++      unsigned long max_rw_time_out_us = (p_dev_context->u_max_read_write_time_out_ms) * 1000;
++
++
++      if(offset == ZY_AC97_CR_E_MDM_GPIO_PIN_STAT)
++      {/* it is a special register and sent out on slot 12 */
++              p_codec_reg = &(p_ac97_reg->codec_regs_primary_mdm[0]);
++              p_codec_reg += offset / ZY_AC97_CODEC_REGS_PER_WORD;
++              /*  The data will be sent out on slot 12. */
++              *p_codec_reg = (unsigned long)data;
++              goto done;
++      }
++
++      /*  Point to specified register within area mapped to target codec regs */
++      p_codec_reg = &(p_ac97_reg->codec_regs_primary_aud[0]);
++      p_codec_reg += offset / ZY_AC97_CODEC_REGS_PER_WORD;
++
++
++      /* Lock the ACLINK */
++      time_remaining = ZY_AC97_LOCK_TIMEOUT_DEF;
++      do
++      {
++              got_link = zy_ac97_acodec_link_lock(p_ac97_reg);
++              if (0 == got_link)      /*  1 usec is a long time.  Skip delay if possible. */
++              {
++                      udelay(1);
++              }
++      }               /*  Wait while time remaining and ACLINK not available */
++      while (time_remaining-- && (0 == got_link));
++
++      if (0 == got_link)      /*  Didn't get the ACLINK */
++      {
++              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++              printk(KERN_ERR "AC97 Write Link Timeout\n");
++      }
++      else    /*  We got the link. Perform the write operation and don't wait. */
++      {
++              /*  First, clear old write status indication CDONE by writing a ONE to that bit. */
++              p_ac97_reg->gsr = ZY_AC97_GSR_CDONE_MSK;
++
++              *p_codec_reg = (unsigned long)data;        /*  Now the write! */
++
++              /* Wait until write cycle is complete. There should be a way
++               * to do this speculatively at the beginning of the procedure.
++               * Need to discover it. Too inefficient to always wait.
++               */
++
++              time_remaining = max_rw_time_out_us;
++              do
++              {
++                      udelay(1);
++              }        /*  Wait while time remaining and command I/O still incomplete. */
++              while ( (time_remaining--) && !(p_ac97_reg->gsr & ZY_AC97_GSR_CDONE_MSK));
++              if (!(p_ac97_reg->gsr & ZY_AC97_GSR_CDONE_MSK))
++              {
++                      status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      p_ac97_reg->car = ZY_AC97_CAR_CAIP_CLEAR;
++              }
++      }  /*  Got AC link */
++
++done:
++      return(status);
++} /*  Ac97CtrlCodecWrite() */
++
++#define CKENA         __REG(0x4134000C)       /* A Clock Enable Register */
++#define CKENB         __REG(0x41340010)
++
++zy_acodec_error_t zy_ac97_acodec_read  (zy_acocec_context_t *p_dev_context, unsigned short offset,  unsigned short *pdata)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      int                     got_link;
++      unsigned long           time_remaining;
++      volatile unsigned long *        p_codec_reg;
++      p_zy_ac97acodec_t p_ac97_reg = (p_zy_ac97acodec_t)(p_dev_context->p_ctrl_reg);
++      unsigned long max_rw_time_out_us = (p_dev_context->u_max_read_write_time_out_ms) * 1000;
++
++      /*  Point to specified register within area mapped to target codec regs */
++      p_codec_reg = &(p_ac97_reg->codec_regs_primary_aud[0]);
++      p_codec_reg += offset / ZY_AC97_CODEC_REGS_PER_WORD;
++
++      /* Lock the ACLINK */
++      time_remaining = ZY_AC97_LOCK_TIMEOUT_DEF;
++      do
++      {
++              got_link = zy_ac97_acodec_link_lock(p_ac97_reg);
++              if (0 == got_link)      /*  1 usec is a long time.  Skip delay if possible. */
++              {
++                      udelay(1);
++              }
++      }               /*  Wait while time remaining and ACLINK not available */
++      while (time_remaining-- && (0 == got_link));
++
++      if (0 == got_link)      /*  Didn't get the ACLINK */
++      {
++              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++              printk(KERN_ERR "AC97 Read Link Timeout\n");
++      }
++      else    /*  We got the link. Perform the write operation and don't wait. */
++      {
++               /*  First, clear old read status indications. */
++              p_ac97_reg->gsr = ZY_AC97_GSR_SDONE_MSK | ZY_AC97_GSR_RCS_ERR_MSK;
++
++              *pdata = (unsigned short)(*p_codec_reg); /*  This is THE DUMMY READ. */
++
++               /*  Wait for read I/O with codec to complete before doing real read. */
++              time_remaining = max_rw_time_out_us;
++              do
++              {
++                      udelay(1);
++              }   /*  Wait while time remaining and read I/O still incomplete */
++              while( (time_remaining--) && (!(p_ac97_reg->gsr & ZY_AC97_GSR_SDONE_MSK)) );
++
++              if ((p_ac97_reg->gsr & ZY_AC97_GSR_SDONE_MSK) && (!(p_ac97_reg->gsr & ZY_AC97_GSR_RCS_ERR_MSK)) )
++              {
++                      if (p_ac97_reg->gsr & ZY_AC97_GSR_RCS_ERR_MSK)
++                      {/* timeout indicated by RCS bit */
++                              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      }
++                      /*  succeed in reading. clear status bits first. */
++                      p_ac97_reg->gsr = ZY_AC97_GSR_SDONE_MSK | ZY_AC97_GSR_RCS_ERR_MSK;
++                      *pdata = (unsigned short)(*p_codec_reg);        /*  THE REAL READ. */
++                      if (*pdata == 0xffff)
++                      {/* timeout indicated by returned value */
++                              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      }
++                      /* check later: is second waiting really needed? */
++                      time_remaining = max_rw_time_out_us;
++                      do
++                      {
++                              udelay(1);
++                      }   /*  Wait while time remaining and read I/O still incomplete */
++                      while( (time_remaining--) && (!(p_ac97_reg->gsr & ZY_AC97_GSR_SDONE_MSK)) );
++                      //printk(KERN_ERR "AC97 Read Result %d\n", (p_ac97_reg->gsr & ZY_AC97_GSR_SDONE_MSK) );
++              }
++              else    /*  failed */
++              {
++                      status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      p_ac97_reg->car = ZY_AC97_CAR_CAIP_CLEAR;
++                      //printk(KERN_ERR "AC97 Read Link Timeout2 %x %x %x\n", CKENA, OSCC, CKENB);
++              } /*  else  (OK to do real read) */
++
++      } /*  else  (We got the link.  Perform the read operations.) */
++
++      return (status);
++}
++
++
++
++zy_acodec_error_t zy_acodec_get_adc_sample(zy_acocec_context_t *p_device_context, unsigned short *p_sample_data, unsigned short adc_type, int *p_pen_down)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      unsigned short value;
++      unsigned long wait;
++
++      if (adc_type == ZY_TOUCH_SAMPLE_X)
++      {
++              value = 0x202;
++      }
++      else
++      {/* Y sample */
++              value = 0x204;
++      }
++
++      status = zy_ac97_acodec_write(p_device_context, DIGITIZER_1_WM13, value);
++
++      wait = 0;
++      do
++      {
++              status = zy_ac97_acodec_read(p_device_context, DIGITIZER_1_WM13, &value);
++              if ( !(value & 0x200 ) )
++              {
++                      break;
++              }
++      }while ( 100 > wait++ );
++
++      status = zy_ac97_acodec_read(p_device_context, DIGITIZER_READ_BACK, &value);
++      if (value & 0x8000)
++      {/* means pen down */
++              *p_pen_down = 1;
++      }
++      else
++      {
++              *p_pen_down = 0;
++      }
++      *p_sample_data = value & 0xfff;
++
++      return status;
++}
++
++
++
++/*
++ * add a touch event
++ */
++static int codec_zy_ts_evt_add(codec_zy_ts_t* ts, u16 pressure, u16 x, u16 y)
++{
++        /* add event and remove adc src bits */
++        static u16 pre_press = 0;
++
++        input_report_abs(ts->idev, ABS_X, x & 0xfff);
++        input_report_abs(ts->idev, ABS_Y, y & 0xfff);
++        if (pressure == pre_press){
++                pressure--;
++        }
++        pre_press = pressure;
++        input_report_abs(ts->idev, ABS_PRESSURE, pressure & 0xfff);
++      input_sync(ts->idev);
++#ifdef CONFIG_IPM
++      ipm_event_notify(IPM_EVENT_UI, IPM_EVENT_DEVICE_TSI, NULL, 0);
++#endif
++        return 0;
++}
++
++/*
++ * add a pen up event
++ */
++static void codec_zy_ts_evt_release(codec_zy_ts_t* ts)
++{
++      input_report_abs(ts->idev, ABS_PRESSURE, 0);
++      input_sync(ts->idev);
++
++#ifdef CONFIG_IPM
++      ipm_event_notify(IPM_EVENT_UI, IPM_EVENT_DEVICE_TSI, NULL, 0);
++#endif
++      p_zy_codec_ctxt->g_pfn_event_ack(p_zy_codec_ctxt,ZY_EVENT_TYPE_PDN);
++}
++
++/*
++ * Kill the touchscreen thread and stop
++ * the touch digitiser.
++ */
++static void codec_zy_ts_input_close(struct input_dev *idev)
++{
++      codec_zy_ts_t *ts = (codec_zy_ts_t *) &codec_zy_ts;
++
++#ifdef CONFIG_PM
++      if(touch_suspend){
++              pr_info("touch is suspended!\n");
++              return -1;
++      }
++#endif
++      dbg("close ts input!\n");
++      if (--ts->use_count == 0) {
++              del_timer(ts->timer);
++              if (ts->timer != NULL)
++                      kfree(ts->timer);
++              p_zy_codec_ctxt->g_pfn_disable_touch(p_zy_codec_ctxt);
++      }
++}
++
++/*
++ * Sample the touchscreen
++ */
++int ac97_poll_touch(codec_zy_ts_t *ts)
++{
++      unsigned short x=0, y=0;
++      int if_down= 0;
++      zy_acodec_error_t status = ZY_ACODEC_SUCCESS;
++
++#ifdef DEBUG
++        start_time = OSCR;
++#endif
++
++      /* get x value */
++      status = zy_acodec_get_adc_sample(p_zy_codec_ctxt, &x, ZY_TOUCH_SAMPLE_X, &if_down);
++      if (ZY_ACODEC_SUCCESS != status ){
++              return -EIO;
++      }
++      dbg("x:0x%x\n", x);
++
++      /* the pen is up */
++      if (1 != if_down){
++              return PEN_UP;
++      }
++
++      /* get y vaule */
++      status = zy_acodec_get_adc_sample(p_zy_codec_ctxt, &y, ZY_TOUCH_SAMPLE_Y, &if_down);
++      if (ZY_ACODEC_SUCCESS != status ){
++              return -EIO;
++      }
++      dbg("y:0x%x\n",y);
++
++      /* the pen is up */
++      if (1 != if_down){
++              return PEN_UP;
++      }
++
++      /* the pen is down, can not get the pressure value,
++       * so if pen is down, give the max pressure value
++       */
++      codec_zy_ts_evt_add(ts,0xfff, x, y);
++
++#ifdef DEBUG
++        end_time = OSCR;
++        PRINT_TIME();
++#endif
++
++      return PEN_DOWN;
++}
++
++static void touch_timer_handler(unsigned long unused)
++{
++      int event;
++      codec_zy_ts_t *ts = &codec_zy_ts;
++
++      event = ac97_poll_touch(ts);
++
++      if (event == PEN_DOWN) {
++              dbg("pen down!\n");
++              ts->timer->expires = jiffies + TS_SAMPLE_INTERVAL;
++              add_timer(ts->timer);
++      } else if(event == PEN_UP) {
++              dbg("pen up!\n");
++              codec_zy_ts_evt_release(ts);
++      } else if(event == -EIO) {
++              printk(KERN_ERR "Access touch interface error!\n");
++      }
++      return;
++}
++
++static zy_acodec_error_t  zy_ac97_acodec_cold_reset(zy_acocec_context_t * p_ac97_ctxt)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      p_zy_ac97acodec_t p_ac97 = (p_zy_ac97acodec_t)(p_ac97_ctxt->p_ctrl_reg);
++      int              pri_codec_ready;
++      unsigned long           time_remaining;
++
++      p_ac97->gcr = 0;
++      p_ac97->gcr |= ZY_AC97_GCR_CLKBPB_MSK;
++      /*  Hold reset active for a minimum time */
++      udelay(ZY_AC97_COLD_HOLDTIME);
++      p_ac97->gcr &= ~ZY_AC97_GCR_CLKBPB_MSK;
++
++      /*  Deactivate cold reset condition */
++      p_ac97->gcr |= (ZY_AC97_GCR_COLD_RESET_MSK | ZY_AC97_GCR_WARM_RESET_MSK);
++
++
++      pri_codec_ready = 0;
++      time_remaining = (p_ac97_ctxt->u_max_setup_time_out_ms) * 10;
++      do
++      {
++              udelay(1);
++              if (p_ac97->gsr & ZY_AC97_GSR_PCRDY_MSK)
++                      pri_codec_ready = 1;
++      }
++      while (time_remaining-- && (pri_codec_ready == 0));
++
++      /*  Timeout status if some of the devices weren't ready. */
++      if (pri_codec_ready == 0)
++      {
++              status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++      }
++
++      return (status);
++}
++
++
++zy_acodec_error_t  zy_ac97_acodec_init(zy_acocec_context_t *p_ac97_ctxt)
++{
++      zy_acodec_error_t       status ;
++
++      status = zy_ac97_acodec_cold_reset(p_ac97_ctxt);
++
++      return (status);
++}
++
++
++/*
++ * Start the touchscreen thread and
++ * the touch digitiser.
++ */
++static int codec_zy_ts_input_open(struct input_dev *idev)
++{
++      codec_zy_ts_t *ts = (codec_zy_ts_t *) &codec_zy_ts;
++
++#ifdef CONFIG_PM
++      if(touch_suspend){
++              pr_info("touch is suspended!\n");
++              return -1;
++      }
++#endif
++
++      if (ts->use_count++ > 0)
++              return 0;
++
++      dbg("Touch is opened. Use count: %d\n", ts->use_count);
++      ts->idev = idev;
++      ts->timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
++      if (!ts->timer) {
++              printk(KERN_ERR "Alloc memory error for timer!\n");
++              return -ENOMEM;
++      }
++
++      init_timer(ts->timer);
++      ts->timer->function = touch_timer_handler;
++      ts->timer->data = 0;
++      p_zy_codec_ctxt->g_pfn_enable_touch(p_zy_codec_ctxt);
++
++      return 0;
++}
++
++/*
++ * initilze the pxa touch screen
++ */
++static int alsa_ts_init( void )
++{
++      codec_zy_ts_t* ts = &codec_zy_ts;
++
++      memset(ts, 0, sizeof(codec_zy_ts_t));
++
++      codec_zy_ts_input = input_allocate_device();
++      if (!codec_zy_ts_input)
++              return -ENOMEM;
++
++
++      /* tell input system what we events we accept and register */
++      codec_zy_ts_input->name = "codec zy touchscreen";
++      codec_zy_ts_input->open = codec_zy_ts_input_open;
++      codec_zy_ts_input->close = codec_zy_ts_input_close;
++      __set_bit(EV_ABS, codec_zy_ts_input->evbit);
++      __set_bit(ABS_X, codec_zy_ts_input->absbit);
++      __set_bit(ABS_Y, codec_zy_ts_input->absbit);
++      __set_bit(ABS_PRESSURE, codec_zy_ts_input->absbit);
++      input_register_device(codec_zy_ts_input);
++
++      return 0;
++}
++
++static irqreturn_t pxa_touch_irq(int irq, void *dev)
++{
++      unsigned char event_type;
++
++      //printk(KERN_ERR "%s: enter codec event handler\n", __FUNCTION__);
++
++      dbg("%s: enter codec event handler\n", __FUNCTION__);
++      p_zy_codec_ctxt->g_pfn_get_event(p_zy_codec_ctxt, &event_type);
++      switch (event_type) {
++              case ZY_EVENT_TYPE_PDN:
++              {
++                      codec_zy_ts_t *ts = &codec_zy_ts;
++                      /*if the touch is not open need not acknowledge the event*/
++                      if (ts->use_count <= 0)
++                              break;
++                      ts->timer->expires = jiffies + TS_SAMPLE_INTERVAL;
++                      add_timer(ts->timer);
++                      break;
++              }
++              default:
++                      printk("unsupported codec event:0x%x\n", event_type);
++      }
++
++      return IRQ_HANDLED;
++}
++
++
++
++
++
++
++
++
++
++static mfp_cfg_t extra_cfg[] = {
++      MFP_CFG_X(GPIO17, AF3, DS03X, PULL_LOW),
++      MFP_CFG_X(GPIO25, AF0, DS01X, PULL_LOW),
++};
++
++#define ARRAY_AND_SIZE(x)     (x), ARRAY_SIZE(x)
++
++extern void dump_mfp(void);
++
++zy_acodec_error_t     zy_ac97_acodec_mfp_init(zy_acocec_context_t *p_device_context)
++{
++      unsigned short codec_id;
++
++      //mhn_mfp_set_afds(MFP_RSVD_AC97_SDATA_IN_0, MFP_AF0, MFP_DS03X);
++      //enable_ac97_pins();
++      zy_ac97_acodec_init(p_device_context);
++      if (zy_ac97_acodec_read(p_device_context, 0x0, &codec_id)){
++
++              /*
++               * there is a bug on MonahansL/MonhansPL PC card: AC97_SDATA_IN is not connected to CODEC
++               * ECO 72: Connect PWM_0(MFP_RSVD_AC97_SDATA_IN_0) to CODEC as AC97_SDATA_IN
++               */
++
++              //mhn_mfp_set_afds(MFP_RSVD_AC97_SDATA_IN_0, MFP_RSVD_AC97_SDATA_IN_0_AF, MFP_DS03X);
++              //mhn_mfp_set_afds(MFP_AC97_SDATA_IN_0, MFP_AF0, MFP_DS01X);
++
++              gpio_direction_output(mfp_to_gpio(MFP_PIN_GPIO17), 0);
++              pxa3xx_mfp_config(ARRAY_AND_SIZE(extra_cfg));
++              gpio_direction_input(mfp_to_gpio(MFP_PIN_GPIO25));
++      }
++
++
++      return ZY_ACODEC_SUCCESS;
++}
++
++#define ZY_AC97_WM9713_GPIO_PIN_PDN ( 0x1 << 13 )  /* Pen down */
++
++/*power enable bit in 3ch and 3eh */
++/*3ch */
++#define ZY_AC97_9713_PWR_PADCPD   ( 0x1 << 15 )
++#define ZY_AC97_9713_PWR_VMID     ( 0x1 << 14 )
++#define ZY_AC97_9713_PWR_TSHUT    ( 0x1 << 13 )
++#define ZY_AC97_9713_PWR_VXDAC    ( 0x1 << 12 )
++#define ZY_AC97_9713_PWR_AUXDAC   ( 0x1 << 11 )
++#define ZY_AC97_9713_PWR_MBIAS    ( 0x1 << 10 )
++#define ZY_AC97_9713_PWR_PLL      ( 0x1 << 9 )
++#define ZY_AC97_9713_PWR_DACL     ( 0x1 << 7 )
++#define ZY_AC97_9713_PWR_DACR     ( 0x1 << 6 )
++#define ZY_AC97_9713_PWR_ADCL     ( 0x1 << 5 )
++#define ZY_AC97_9713_PWR_ADCR     ( 0x1 << 4 )
++#define ZY_AC97_9713_PWR_HPLX     ( 0x1 << 3 )
++#define ZY_AC97_9713_PWR_HPRX     ( 0x1 << 2 )
++#define ZY_AC97_9713_PWR_SPKX     ( 0x1 << 1 )
++#define ZY_AC97_9713_PWR_MX       ( 0x1 << 0 )
++
++/*3EH */
++#define ZY_AC97_9713_PWR_MCD      ( 0x1 << 15 )
++#define ZY_AC97_9713_PWR_MICBIAS  ( 0x1 << 14 )
++#define ZY_AC97_9713_PWR_MONO     ( 0x1 << 13 )
++#define ZY_AC97_9713_PWR_OUT4     ( 0x1 << 12 )
++#define ZY_AC97_9713_PWR_OUT3     ( 0x1 << 11 )
++#define ZY_AC97_9713_PWR_HPL      ( 0x1 << 10 )
++#define ZY_AC97_9713_PWR_HPR      ( 0x1 << 9 )
++#define ZY_AC97_9713_PWR_SPKL     ( 0x1 << 8 )
++#define ZY_AC97_9713_PWR_SPKR     ( 0x1 << 7 )
++#define ZY_AC97_9713_PWR_LL       ( 0x1 << 6 )
++#define ZY_AC97_9713_PWR_LR       ( 0x1 << 5 )
++#define ZY_AC97_9713_PWR_MOIN     ( 0x1 << 4 )
++#define ZY_AC97_9713_PWR_MA       ( 0x1 << 3 )
++#define ZY_AC97_9713_PWR_MB       ( 0x1 << 2 )
++#define ZY_AC97_9713_PWR_MPA      ( 0x1 << 1 )
++#define ZY_AC97_9713_PWR_MPB      ( 0x1 << 0 )
++
++
++void zy_wm9713_get_event(zy_acocec_context_t *p_device_context, unsigned char * event_type)
++{
++      unsigned short event_state = 0;
++      zy_ac97_acodec_read(p_device_context, GPIO_PIN_STATUS, &event_state);
++      if(event_state & ZY_AC97_WM9713_GPIO_PIN_PDN){
++              *event_type = ZY_EVENT_TYPE_PDN;
++              return;
++      }
++      return;
++}
++
++void zy_wm9713_event_ack(zy_acocec_context_t *p_device_context, unsigned char event_type)
++{
++      unsigned short event_state = 0;
++      zy_ac97_acodec_read(p_device_context, GPIO_PIN_STATUS, &event_state);
++      if( event_type == ZY_EVENT_TYPE_PDN){
++              zy_ac97_acodec_write(p_device_context,
++                                      GPIO_PIN_STATUS,
++                                      (event_state & (~ZY_AC97_WM9713_GPIO_PIN_PDN)));
++      }
++
++      zy_ac97_acodec_read(p_device_context, GPIO_PIN_STATUS, &event_state);
++      return;
++}
++
++static void * p_saved_memory = NULL;
++static void * p_zy_scenario = NULL;
++static p_zy_acocec_context_t p_zy_ctxt = NULL;
++
++#define WM9713_SAVE_REGISTER_NO (64-11)
++typedef struct {
++    unsigned short wm9713RegisterContext [WM9713_SAVE_REGISTER_NO + 1]; /* Fixed (data misalignment error) */
++}ZY_9713_CONTEXT_SAVE_T;
++
++
++/**
++ * alsa_prepare_for_zy - create and initialize the p_zy_acocec_context_t
++ *                               open the clock of data link
++ * @p_p_zy_ctxt: return the data structure p_zy_acocec_context_t
++ * return: 0 success ; -ENOMEM
++ **/
++int alsa_prepare_for_zy(p_zy_acocec_context_t * p_p_zy_ctxt)
++{
++      if (p_zy_ctxt) {
++              p_zy_ctxt->use_count++;
++              *p_p_zy_ctxt = p_zy_ctxt;
++              return 0;
++      }
++
++      p_zy_ctxt = kzalloc(sizeof(zy_acocec_context_t), GFP_KERNEL);
++      if (!p_zy_ctxt)
++              return -ENOMEM;
++
++      /* enable CLK_POUT as CODEC clock input */
++      OSCC |= 0x800;
++
++      p_saved_memory = kzalloc(sizeof(ZY_9713_CONTEXT_SAVE_T) +
++                              sizeof(zy_ac97_save_context_t), GFP_KERNEL);
++      if (NULL == p_saved_memory) {
++              if (p_zy_ctxt)
++                      kfree(p_zy_ctxt);
++              return -ENOMEM;
++      }
++
++      p_zy_ctxt->acodec_id = (zy_acodec_device_id_t) (WM_9713_ID);
++      p_zy_ctxt->use_count++;
++      /*
++      p_zy_ctxt->pMfpRegBase = (unsigned long) (MFP_BASE);
++      p_zy_ctxt->pMfpRmDb = ZY_MFP_RM_DATABASE;
++      p_zy_ctxt->p_ost_regs = OST_BASE;
++      */
++      p_zy_ctxt->p_voice_reg = NULL;
++      p_zy_ctxt->p_hifi_reg = (void *) (&POCR);
++      p_zy_ctxt->p_ctrl_reg = (void *) (&POCR);
++      p_zy_ctxt->u_max_read_write_time_out_ms = ZY_AC97_RW_TIMEOUT_DEF;
++      p_zy_ctxt->u_max_setup_time_out_ms = ZY_AC97_SETUP_TIMEOUT_DEF;
++      p_zy_ctxt->p_save_memory = p_saved_memory;
++      p_zy_ctxt->p_zy_scenario = p_zy_scenario;
++//    pxa_set_cken(24, 1);
++      CKENA |= (1 << 24);
++      AC97_DIV = 1625<<12 | 128;
++#ifdef DEBUG_ALSA_ZY
++      debug_pac97ctxt = p_zy_ctxt;
++      misc_register(&audio_dev);
++#endif
++
++      (*p_p_zy_ctxt) = p_zy_ctxt;
++
++      return 0;
++}
++
++
++/* this is platform specific */
++/* do later: not to enable recording route and playback route in this function,
++ * leave it to driver to call other function
++ */
++zy_acodec_error_t zy_wm9713_specific_init (zy_acocec_context_t *p_device_context)
++{
++
++      unsigned short value;
++
++      /* this assumes that the aclink is initialized wait some time and then
++       * do a warm reset to enabled the ACLINK, required for wm9713
++       * (not wm9712 or ucb1400)
++       */
++
++      /* pay attention: whether the workaround is still needed? */
++      p_zy_ac97acodec_t p_ac97_reg = (p_zy_ac97acodec_t)(p_device_context->p_ctrl_reg);
++
++      p_ac97_reg->gcr |= ZY_AC97_GCR_WARM_RESET_MSK;
++
++      mdelay(5);
++
++      /* power on all the necessary unit */
++      zy_ac97_acodec_write(p_device_context,POWERDOWN_CTRL_STAT, 0x000);      /*26*/
++      /* open left headphone mixer */
++      /* open right headphone mixer */
++      /* open right/left dac */
++      /* open right/left adc */
++      /* open temperature sensor */
++      /* enable reference generator */
++      zy_ac97_acodec_write(p_device_context,POWER_DOWN_1, 0xda00);            /*3c */
++      /* open microphone bias */
++      /* open HPL output PGA */
++      /* open HPR output PGA */
++      /* open mic PGA MA */
++      /* open mic pre-amp MPA */
++      /* if here we enable SPKL and SPKR PGA, then Touch screen will doesn't work */
++      zy_ac97_acodec_write(p_device_context,POWER_DOWN_2,0xb9f5);   /*3e */
++
++      /* recording route and microphone input */
++      /* microphone selection, now fixed to MIC1 input and mic bias output */
++      /* MIC1 only, MICBIAS enable */
++      zy_ac97_acodec_write (p_device_context, MIC_BIAS, 0xC440);      /*0x22h*/
++
++      /* mic pga setting to mixer (side tone) */
++      /* comment the below code to make MICA/B play back volume gain + 0db */
++      /* zy_ac97_acodec_write (p_device_context, MIC_PGA_VOLUME, 0x0000); */  /*0x0eh*/
++
++      /* recording side tone and ADC boost, now fixed to default (14h) */
++      /* recording volume  0dB */
++      zy_ac97_acodec_write(p_device_context, REC_PGA_VOL, 0x0); /*12*/
++
++      /* hifi playback route and output mixer  */
++      /* by default, fixed to enable headphone only */
++
++      /* comment the below code to make SPEAKER default MUTE */
++      zy_ac97_acodec_write (p_device_context, SPEAKER_VOLUME, 0x0);           /*02*/
++
++      /* comment the below code to make OUT3_OUT4 default MUTE */
++      /* zy_ac97_acodec_write (p_device_context, OUT3_OUT4_VOLUME, 0x8000); */        /*06*/
++
++      /* remove all  the mute bit  volume gain + 0db  */
++      zy_ac97_acodec_write(p_device_context, HEADPHONE_VOLUME, 0x0);  /*04*/
++
++      /* DAC route */
++      /* open DAC to headphone mixer path */
++      /* left DAC gain +0db */
++      /* right DAC gain +0db */
++      zy_ac97_acodec_write(p_device_context, DAC_PGA_VOL_ROUTE,0x0808);       /*0c*/
++
++      /* out3 configure, invert to HPMIXR */
++      /* zy_ac97_acodec_write(p_device_context,DAC_3D_CTRL_INV_MUX_SEL, 0x8000); */   /*1e*/
++
++      /* output control */
++       /* select HPMIXR HPMIXL out */
++       /* other out are all VIM */
++      zy_ac97_acodec_write(p_device_context,OUTPUT_PGA_MUX, 0x9BA8);          /*1c*/
++
++      /* set sample rates */
++      /* enable variable rate conversion */
++      zy_ac97_acodec_write(p_device_context, EXTENDED_AUD_STAT_CTRL , 0x1); /*2a*/
++      /*  DAC 44kHZ */
++      zy_ac97_acodec_write(p_device_context,AUDIO_DAC_RATE,0xac44); /*2c*/
++      /*  ADC 16KHZ */
++      zy_ac97_acodec_write(p_device_context,AUDIO_ADC_RATE,0x3E80); /*32*/
++
++      /* clock scheme, use external clock, it is 24MHZ from MCLK_A */
++
++
++      zy_ac97_acodec_read(p_device_context, MCLK_PLL_CTRL_1, &value);
++      zy_ac97_acodec_write(p_device_context, MCLK_PLL_CTRL_1, value | 0x2);
++
++      return ZY_ACODEC_SUCCESS;
++}
++
++zy_acodec_error_t zy_wm9713_specific_deinit (zy_acocec_context_t *p_device_context)
++{/* do later: shut down all power */
++      unsigned short value = 0;
++
++      /* close the power of all units */
++      zy_ac97_acodec_write(p_device_context, POWER_DOWN_1, 0xffff);
++      zy_ac97_acodec_write(p_device_context, POWER_DOWN_2, 0xffff);
++      zy_ac97_acodec_read(p_device_context, POWER_DOWN_1, &value);
++      value &= ~(ZY_AC97_9713_PWR_MBIAS);
++      zy_ac97_acodec_write(p_device_context, POWER_DOWN_1, value);
++
++      return ZY_ACODEC_SUCCESS;
++}
++
++zy_acodec_error_t zy_acodec_set_pen_down_interrupt(zy_acocec_context_t *p_device_context, int enable)
++{/* disable/enable pen down interrupt in the codec. This function is not implemented for Wm9713 */
++      /* because the pen down detection could not be disabled in codec */
++      return ZY_ACODEC_SUCCESS;
++}
++
++zy_acodec_error_t zy_wm9713_enable_touch(zy_acocec_context_t *p_device_context)
++{/* enable touch functionality in the codec */
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      unsigned short value;
++
++      /* power setting */
++      status = zy_ac97_acodec_read(p_device_context, POWER_DOWN_1, &value);
++      value &= ~(ZY_AC97_9713_PWR_PADCPD);
++      status = zy_ac97_acodec_write(p_device_context, POWER_DOWN_1, value);
++
++      /* basic touch setting   */
++      status = zy_ac97_acodec_write(p_device_context, DIGITIZER_3_WM13, 0xc008);
++      status = zy_ac97_acodec_write(p_device_context, DIGITIZER_2_WM13, 0x6);
++
++
++      /* 9713 powerdown virtual gpio setting (polarity, sticky, wakeup) */
++      /* 9713 gpio 2(pin45) route to IRQ */
++      /*  Notes: Can use defaults for IRQ polarity, PENDOWN polarity in IRQ, */
++      /*   sticky for PENDOWN in IRQ and wakeup for PENDOWN.   */
++      status = zy_ac97_acodec_read(p_device_context, GPIO_PIN_CFG, &value);
++      value &= ~(0x4);
++      status = zy_ac97_acodec_write(p_device_context, GPIO_PIN_CFG, value);
++
++      status = zy_ac97_acodec_read(p_device_context, GPIO_PIN_SHARING, &value);
++      value &= ~(0x4);
++      status = zy_ac97_acodec_write(p_device_context, GPIO_PIN_SHARING, value);
++
++      status = zy_ac97_acodec_read(p_device_context, GPIO_PIN_WAKEUP, &value);
++      value |= (0x2000);
++      status = zy_ac97_acodec_write(p_device_context, GPIO_PIN_WAKEUP, value);
++
++      status = zy_ac97_acodec_read(p_device_context, GPIO_PIN_STICKY, &value);
++      value |= (0x2000);
++      status = zy_ac97_acodec_write(p_device_context, GPIO_PIN_STICKY, value);
++
++      return status;
++}
++
++zy_acodec_error_t zy_wm9713_disable_touch(zy_acocec_context_t *p_device_context)
++{/* disable touch functionality in the codec */
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      unsigned short value;
++
++      /* power setting */
++      status = zy_ac97_acodec_read(p_device_context, POWER_DOWN_1, &value);
++      value |= (ZY_AC97_9713_PWR_PADCPD);
++      status = zy_ac97_acodec_write(p_device_context, POWER_DOWN_1, value);
++
++      return status;
++}
++zy_acodec_error_t     zy_ac97_acodec_mfp_deinit(zy_acocec_context_t *p_device_context)
++{/* do later: free all MFP resources. */
++    return ZY_ACODEC_SUCCESS;
++}
++
++static zy_acodec_error_t  zy_ac97_acodec_shut_down_aclink(p_zy_ac97acodec_t p_ac97_reg, int * p_ost_regs)
++{
++      zy_acodec_error_t       status = ZY_ACODEC_SUCCESS;
++      unsigned long time_remaining = ZY_AC97_LINKOFF_TIMEOUT_DEF;
++
++      p_ac97_reg->gcr |= ZY_AC97_GCR_LINK_OFF_MSK;
++      p_ac97_reg->gcr |= ZY_AC97_GCR_CLKBPB_MSK;
++
++      while (!(p_ac97_reg->gsr & ZY_AC97_GSR_ACOFFD_MSK))
++      {
++              time_remaining --;
++              if (0 == time_remaining)
++              {
++                      status = ZY_ACODEC_CONTROLLER_INTERFACE_TIMEOUT;
++                      break;
++              }
++              udelay(1);
++      }
++      p_ac97_reg->gcr |= ZY_AC97_GCR_FRCRST_MSK;
++      /* check later: any delay needed */
++      p_ac97_reg->gcr &= ~ZY_AC97_GCR_FRCRST_MSK;
++      p_ac97_reg->gcr &= ~ZY_AC97_GCR_CLKBPB_MSK;
++
++      return(status);
++}
++
++
++zy_acodec_error_t  zy_ac97_acodec_deinit(zy_acocec_context_t * p_ac97_ctxt)
++{
++      zy_acodec_error_t       status ;
++
++      status = zy_ac97_acodec_shut_down_aclink((p_zy_ac97acodec_t)(p_ac97_ctxt->p_ctrl_reg), p_ac97_ctxt->p_ost_regs);
++
++      return (status);
++}
++
++zy_acodec_error_t zy_acodec_deinit(zy_acocec_context_t *p_device_context)
++{
++      /* power down codec by codec specific power down function */
++      if (p_device_context->g_pfn_codec_specific_dinit)
++      {
++              p_device_context->g_pfn_codec_specific_dinit(p_device_context);
++      }
++      /* call bus deinit function */
++      zy_ac97_acodec_deinit(p_device_context);
++      /* restore MFP, set GPIO to suitable value */
++      zy_ac97_acodec_mfp_deinit(p_device_context);
++
++      return ZY_ACODEC_SUCCESS;
++}
++
++void alsa_zy_codec_put(p_zy_acocec_context_t p_acodectxt)
++{
++
++      zy_acodec_deinit(p_acodectxt);
++      //pxa_set_cken(24, 0);
++      CKENA &= ~(1 << 24);
++
++      if(p_acodectxt->p_save_memory){
++              kfree(p_saved_memory);
++      }
++      if(p_acodectxt->p_zy_scenario){
++              kfree(p_zy_scenario);
++      }
++}
++
++
++zy_acodec_error_t zy_acodec_init(zy_acocec_context_t *p_device_context, int hw_init)
++{
++      /* set codec specific functions
++       * set mfp for Zylonite platform
++       * call bus init function (AC97, I2S, I2C, SSP)
++       * call specific init of codec
++       */
++      zy_acodec_error_t retval = ZY_ACODEC_SUCCESS;
++
++      if (p_device_context->acodec_id != WM_9713_ID)
++      {/* on Zylonite, it is Wolfson 9713 codec only */
++              return ZY_ACODEC_GENERAL_SW_ERR;
++      }
++
++      if (1 == hw_init)
++      {
++              zy_ac97_acodec_mfp_init(p_device_context);
++              zy_ac97_acodec_init(p_device_context);  /* codec init common to ac97 */
++      }
++
++      /* wm9713-specific functions */
++      (p_device_context->g_pfn_codec_specific_init)   = zy_wm9713_specific_init;
++      (p_device_context->g_pfn_codec_specific_dinit)  = zy_wm9713_specific_deinit;
++      (p_device_context->g_pfn_acodec_read)           = zy_ac97_acodec_read;
++      (p_device_context->g_pfn_acodec_write)          = zy_ac97_acodec_write;
++
++      (p_device_context->g_pfn_event_ack)    = zy_wm9713_event_ack;
++      (p_device_context->g_pfn_get_event)    = zy_wm9713_get_event;
++      (p_device_context->g_pfn_disable_touch)        = zy_wm9713_disable_touch;
++      (p_device_context->g_pfn_enable_touch) = zy_wm9713_enable_touch;
++
++      if (1 == hw_init)
++      {
++              retval = p_device_context->g_pfn_codec_specific_init(p_device_context);
++      }
++
++      return retval;
++}
++
++static int __devinit touch_codec_zy_probe(struct platform_device *dev)
++{
++      int ret = 0;
++      struct snd_card *card = NULL;
++      zy_acodec_error_t status;
++
++      /* will increase codec context use count */
++      ret = alsa_prepare_for_zy(&p_zy_codec_ctxt);
++      if (ret)
++              goto err;
++
++      /* codec specific initialization, audio will do it either */
++      if (1 == p_zy_codec_ctxt->use_count) {
++              status = zy_acodec_init(p_zy_codec_ctxt, 1);
++              if (ZY_ACODEC_SUCCESS != status) {
++                      printk(KERN_ERR "initialize codec error\n");
++                      ret = -EIO;
++                      goto err;
++              }
++
++      /* power down the units of the acodec, sleep the acodec, zy_acodec_init()
++       * will open all the units' power of the codec while ALSA need all the codec
++       * units power down and the codec should sleep if it can.
++       * So on the zylonite platform we call below function to power down and sleep
++       * wm9713 codec.
++       */
++      p_zy_codec_ctxt->g_pfn_codec_specific_dinit(p_zy_codec_ctxt);
++
++      }
++
++      alsa_ts_init();
++
++      //mhn_mfp_set_afds(MFP_AC97_INT_N_GPIO,0,0);
++      //mhn_gpio_set_direction(MFP_AC97_INT_N_GPIO, GPIO_DIR_IN);
++      //mhn_gpio_clear_edge_detect_status(MFP_AC97_INT_N_GPIO);
++      gpio_direction_input(mfp_to_gpio(MFP_PIN_GPIO26));
++      ret = request_irq(IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO26)),
++                      pxa_touch_irq, IRQF_TRIGGER_RISING,
++                      "wm9713 touch event interrupt", NULL);
++      if (ret) {
++              printk(KERN_ERR "Request IRQ for touch failed (%d).\n", ret);
++              goto err;
++      }
++
++      return 0;
++err:
++      if (p_zy_codec_ctxt && (!--p_zy_codec_ctxt->use_count)) {
++              zy_acodec_deinit(p_zy_codec_ctxt);
++              //pxa_set_cken(24, 0);
++              CKENA &= ~(1 << 24);
++              kfree(p_zy_codec_ctxt);
++              p_zy_codec_ctxt = NULL;
++      }
++
++      if (card)
++              snd_card_free(card);
++
++      return ret;
++}
++
++static int __devexit touch_codec_zy_remove(struct platform_device *dev)
++{
++      struct snd_card *card = platform_get_drvdata(dev);
++
++      input_unregister_device(codec_zy_ts_input);
++
++      if (p_zy_codec_ctxt && (!--p_zy_codec_ctxt->use_count)) {
++              alsa_zy_codec_put(p_zy_codec_ctxt);
++              kfree(p_zy_codec_ctxt);
++              p_zy_codec_ctxt = NULL;
++      }
++
++      if (card) {
++              snd_card_free(card);
++              platform_set_drvdata(dev, NULL);
++      }
++
++      return 0;
++}
++
++#ifdef CONFIG_PM
++static int touch_codec_zy_suspend(struct platform_device *_dev, pm_message_t state, u32 level)
++{
++      int ret=0;
++      
++      if (level == SUSPEND_DISABLE) {
++              ret = audio_codec_zy_do_suspend(NULL, SNDRV_CTL_POWER_D3cold, p_zy_codec_ctxt);
++              touch_suspend = 1;
++      }
++      return ret;
++}
++
++static int touch_codec_zy_resume(struct platform_device *_dev, u32 level)
++{
++      int ret = 0;
++      
++      if (level == RESUME_ENABLE) {
++              ret = audio_codec_zy_do_resume(NULL, SNDRV_CTL_POWER_D0, p_zy_codec_ctxt);
++              touch_suspend = 0;
++      }
++      return ret;
++}
++#else
++#define touch_codec_zy_suspend        NULL
++#define touch_codec_zy_resume NULL
++#endif
++
++static struct platform_driver touch_codec_zy_driver = {
++      .probe  =       touch_codec_zy_probe,
++      .remove =       __devexit_p(touch_codec_zy_remove),
++      .suspend=       touch_codec_zy_suspend,
++      .resume =       touch_codec_zy_resume,
++      .driver = {
++              .name   =       "pxa2xx-touch",
++      },
++};
++
++static int __init touch_codec_zy_init(void)
++{
++      return platform_driver_register(&touch_codec_zy_driver);
++}
++
++static void __exit touch_code_zy_exit(void)
++{
++      platform_driver_unregister(&touch_codec_zy_driver);
++}
++module_init(touch_codec_zy_init);
++module_exit(touch_code_zy_exit);
++
++EXPORT_SYMBOL(p_zy_codec_ctxt);
++
++MODULE_AUTHOR("bridge.wu@marvell.com");
++MODULE_DESCRIPTION("zylonite audio touch codec driver on ALSA");
++MODULE_LICENSE("GPL");
++
index b4579ce9f474b8ad158a648d8a6ff582454834d7..32564a2f6647cca6138bbe1c06d8f689c4099dad 100644 (file)
@@ -1,6 +1,6 @@
 require linux-rp.inc
 
-PR = "r31"
+PR = "r32"
 
 # Handy URLs
 # git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git;protocol=git;tag=ef7d1b244fa6c94fb76d5f787b8629df64ea4046
@@ -139,6 +139,7 @@ SRC_URI_append_zylonite ="\
        file://pxa_fb_overlay.patch;patch=1 \
        file://zylonite-boot.patch;patch=1 \
        file://zylonite_mtd-r0.patch;patch=1 \
+       file://zylonite_touch-r0.patch;patch=1 \
        "
 
 S = "${WORKDIR}/linux-2.6.23"