diff options
105 files changed, 1436 insertions, 2315 deletions
diff --git a/Documentation/sound/alsa/Audiophile-Usb.txt b/Documentation/sound/alsa/Audiophile-Usb.txt index 4692c8e..b535c2a 100644 --- a/Documentation/sound/alsa/Audiophile-Usb.txt +++ b/Documentation/sound/alsa/Audiophile-Usb.txt @@ -1,4 +1,4 @@ - Guide to using M-Audio Audiophile USB with ALSA and Jack v1.2 + Guide to using M-Audio Audiophile USB with ALSA and Jack v1.3 ======================================================== Thibault Le Meur <Thibault.LeMeur@supelec.fr> @@ -22,16 +22,16 @@ The device has 4 audio interfaces, and 2 MIDI ports: * Midi In (Mi) * Midi Out (Mo) -The internal DAC/ADC has the following caracteristics: +The internal DAC/ADC has the following characteristics: * sample depth of 16 or 24 bits * sample rate from 8kHz to 96kHz -* Two ports can't use different sample depths at the same time.Moreover, the +* Two ports can't use different sample depths at the same time. Moreover, the Audiophile USB documentation gives the following Warning: "Please exit any audio application running before switching between bit depths" Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be activated at the same time depending on the audio mode selected: - * 16-bit/48kHz ==> 4 channels in/ 4 channels out + * 16-bit/48kHz ==> 4 channels in/4 channels out - Ai+Ao+Di+Do * 24-bit/48kHz ==> 4 channels in/2 channels out, or 2 channels in/4 channels out @@ -41,8 +41,8 @@ activated at the same time depending on the audio mode selected: Important facts about the Digital interface: -------------------------------------------- - * The Do port additionnaly supports surround-encoded AC-3 and DTS passthrough, -though I haven't tested it under linux + * The Do port additionally supports surround-encoded AC-3 and DTS passthrough, +though I haven't tested it under Linux - Note that in this setup only the Do interface can be enabled * Apart from recording an audio digital stream, enabling the Di port is a way to synchronize the device to an external sample clock @@ -60,24 +60,23 @@ synchronization error (for instance sound played at an odd sample rate) The Audiophile USB MIDI ports will be automatically supported once the following modules have been loaded: * snd-usb-audio - * snd-seq * snd-seq-midi -No additionnal setting is required. +No additional setting is required. 2.2 - Audio ports ----------------- Audio functions of the Audiophile USB device are handled by the snd-usb-audio module. This module can work in a default mode (without any device-specific -parameter), or in an advanced mode with the device-specific parameter called +parameter), or in an "advanced" mode with the device-specific parameter called "device_setup". 2.2.1 - Default Alsa driver mode -The default behaviour of the snd-usb-audio driver is to parse the device +The default behavior of the snd-usb-audio driver is to parse the device capabilities at startup and enable all functions inside the device (including -all ports at any sample rates and any sample depths supported). This approach +all ports at any supported sample rates and sample depths). This approach has the advantage to let the driver easily switch from sample rates/depths automatically according to the need of the application claiming the device. @@ -114,9 +113,9 @@ gain). For people having this problem, the snd-usb-audio module has a new module parameter called "device_setup". -2.2.2.1 - Initializing the working mode of the Audiohile USB +2.2.2.1 - Initializing the working mode of the Audiophile USB -As far as the Audiohile USB device is concerned, this value let the user +As far as the Audiophile USB device is concerned, this value let the user specify: * the sample depth * the sample rate @@ -174,20 +173,20 @@ The parameter can be given: IMPORTANT NOTE WHEN SWITCHING CONFIGURATION: ------------------------------------------- - * You may need to _first_ intialize the module with the correct device_setup + * You may need to _first_ initialize the module with the correct device_setup parameter and _only_after_ turn on the Audiophile USB device * This is especially true when switching the sample depth: - - first trun off the device - - de-register the snd-usb-audio module - - change the device_setup parameter (by either manually reprobing the module - or changing modprobe.conf) + - first turn off the device + - de-register the snd-usb-audio module (modprobe -r) + - change the device_setup parameter by changing the device_setup + option in /etc/modprobe.conf - turn on the device 2.2.2.3 - Audiophile USB's device_setup structure If you want to understand the device_setup magic numbers for the Audiophile USB, you need some very basic understanding of binary computation. However, -this is not required to use the parameter and you may skip thi section. +this is not required to use the parameter and you may skip this section. The device_setup is one byte long and its structure is the following: @@ -231,11 +230,11 @@ Caution: 2.2.3 - USB implementation details for this device -You may safely skip this section if you're not interrested in driver +You may safely skip this section if you're not interested in driver development. -This section describes some internals aspect of the device and summarize the -data I got by usb-snooping the windows and linux drivers. +This section describes some internal aspects of the device and summarize the +data I got by usb-snooping the windows and Linux drivers. The M-Audio Audiophile USB has 7 USB Interfaces: a "USB interface": @@ -277,9 +276,9 @@ Here is a short description of the AltSettings capabilities: - 16-bit depth, 8-48kHz sample mode - Synch playback (Do), audio format type III IEC1937_AC-3 -In order to ensure a correct intialization of the device, the driver +In order to ensure a correct initialization of the device, the driver _must_know_ how the device will be used: - * if DTS is choosen, only Interface 2 with AltSet nb.6 must be + * if DTS is chosen, only Interface 2 with AltSet nb.6 must be registered * if 96KHz only AltSets nb.1 of each interface must be selected * if samples are using 24bits/48KHz then AltSet 2 must me used if @@ -290,7 +289,7 @@ _must_know_ how the device will be used: is not connected When device_setup is given as a parameter to the snd-usb-audio module, the -parse_audio_enpoint function uses a quirk called +parse_audio_endpoints function uses a quirk called "audiophile_skip_setting_quirk" in order to prevent AltSettings not corresponding to device_setup from being registered in the driver. @@ -317,9 +316,8 @@ However you may see the following warning message: using the "default" ALSA device. This is less efficient than it could be. Consider using a hardware device instead rather than using the plug layer." - 3.2 - Patching alsa to use direct pcm device -------------------------------------------- +-------------------------------------------- A patch for Jack by Andreas Steinmetz adds support for Big Endian devices. However it has not been included in the CVS tree. @@ -331,3 +329,32 @@ After having applied the patch you can run jackd with the following command line: % jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1 +3.2 - Getting 2 input and/or output interfaces in Jack +------------------------------------------------------ + +As you can see, starting the Jack server this way will only enable 1 stereo +input (Di or Ai) and 1 stereo output (Ao or Do). + +This is due to the following restrictions: +* Jack can only open one capture device and one playback device at a time +* The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1 + (and optionally hw:1,2) +If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to +combine the Alsa devices into one logical "complex" device. + +If you want to give it a try, I recommend reading the information from +this page: http://www.sound-man.co.uk/linuxaudio/ice1712multi.html +It is related to another device (ice1712) but can be adapted to suit +the Audiophile USB. + +Enabling multiple Audiophile USB interfaces for Jackd will certainly require: +* patching Jack with the previously mentioned "Big Endian" patch +* patching Jackd with the MMAP_COMPLEX patch (see the ice1712 page) +* patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page) +* define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc + file +* start jackd with this device + +I had no success in testing this for now, but this may be due to my OS +configuration. If you have any success with this kind of setup, please +drop me an email. diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 68eeebc..1faf763 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -1172,7 +1172,7 @@ } /* PCI IDs */ - static struct pci_device_id snd_mychip_ids[] = { + static struct pci_device_id snd_mychip_ids[] __devinitdata = { { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, .... @@ -1565,7 +1565,7 @@ <informalexample> <programlisting> <![CDATA[ - static struct pci_device_id snd_mychip_ids[] = { + static struct pci_device_id snd_mychip_ids[] __devinitdata = { { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, .... diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index fe22e54..dbe421d 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y @@ -55,6 +56,7 @@ CONFIG_SYSCTL=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set @@ -69,10 +71,6 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 @@ -84,7 +82,6 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y @@ -93,6 +90,7 @@ CONFIG_STOP_MACHINE=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -126,6 +124,7 @@ CONFIG_RTAS_FLASH=y CONFIG_MMIO_NVRAM=y CONFIG_CELL_IIC=y # CONFIG_PPC_MPC106 is not set +# CONFIG_PPC_970_NAP is not set # CONFIG_CPU_FREQ is not set # CONFIG_WANT_EARLY_SERIAL is not set @@ -167,7 +166,6 @@ CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_EXTREME=y # CONFIG_MEMORY_HOTPLUG is not set CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_MIGRATION=y # CONFIG_PPC_64K_PAGES is not set CONFIG_SCHED_SMT=y CONFIG_PROC_DEVICETREE=y @@ -184,7 +182,6 @@ CONFIG_GENERIC_ISA_DMA=y # CONFIG_PPC_INDIRECT_PCI is not set CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_PCI_LEGACY_PROC=y # CONFIG_PCI_DEBUG is not set # @@ -226,6 +223,7 @@ CONFIG_SYN_COOKIES=y # 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=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y @@ -242,6 +240,7 @@ CONFIG_IPV6=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m CONFIG_INET6_TUNNEL=m CONFIG_IPV6_TUNNEL=m CONFIG_NETFILTER=y @@ -632,6 +631,7 @@ CONFIG_SERIAL_NONSTANDARD=y # 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 @@ -717,7 +717,6 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -736,9 +735,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -766,10 +763,6 @@ CONFIG_I2C_ALGOBIT=y # # -# Multimedia Capabilities Port drivers -# - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -818,6 +811,19 @@ CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_MMC is not set # +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# # InfiniBand support # CONFIG_INFINIBAND=y @@ -834,6 +840,11 @@ CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y # # +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# # File systems # CONFIG_EXT2_FS=y @@ -889,7 +900,6 @@ CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 39e348a..3f7182d 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -57,6 +57,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) +#define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\ + PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ PPC_FEATURE_BOOKE) @@ -263,6 +265,20 @@ struct cpu_spec cpu_specs[] = { .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power5+", }, + { /* Power6 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x003e0000, + .cpu_name = "POWER6", + .cpu_features = CPU_FTRS_POWER6, + .cpu_user_features = COMMON_USER_POWER6, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_power4, + .oprofile_cpu_type = "ppc64/power6", + .oprofile_type = PPC_OPROFILE_POWER4, + .platform = "power6", + }, { /* Cell Broadband Engine */ .pvr_mask = 0xffff0000, .pvr_value = 0x00700000, diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 928b858..ba34001 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -191,11 +191,19 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr, (void *)hdr + sechdrs[sechdrs[i].sh_link].sh_offset); } - if (!me->arch.stubs_section || !me->arch.toc_section) { - printk("%s: doesn't contain .toc or .stubs.\n", me->name); + + if (!me->arch.stubs_section) { + printk("%s: doesn't contain .stubs.\n", me->name); return -ENOEXEC; } + /* If we don't have a .toc, just use .stubs. We need to set r2 + to some reasonable value in case the module calls out to + other functions via a stub, or if a function pointer escapes + the module by some means. */ + if (!me->arch.toc_section) + me->arch.toc_section = me->arch.stubs_section; + /* Override the stubs size */ sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs); return 0; @@ -342,7 +350,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, break; case R_PPC64_TOC16: - /* Subtact TOC pointer */ + /* Subtract TOC pointer */ value -= my_r2(sechdrs, me); if (value + 0x8000 > 0xffff) { printk("%s: bad TOC16 relocation (%lu)\n", @@ -355,7 +363,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, break; case R_PPC64_TOC16_DS: - /* Subtact TOC pointer */ + /* Subtract TOC pointer */ value -= my_r2(sechdrs, me); if ((value & 3) != 0 || value + 0x8000 > 0xffff) { printk("%s: bad TOC16_DS relocation (%lu)\n", diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 7e4d548..078fb55 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -636,10 +636,96 @@ static void __init early_cmdline_parse(void) #ifdef CONFIG_PPC_PSERIES /* - * To tell the firmware what our capabilities are, we have to pass - * it a fake 32-bit ELF header containing a couple of PT_NOTE sections - * that contain structures that contain the actual values. + * There are two methods for telling firmware what our capabilities are. + * Newer machines have an "ibm,client-architecture-support" method on the + * root node. For older machines, we have to call the "process-elf-header" + * method in the /packages/elf-loader node, passing it a fake 32-bit + * ELF header containing a couple of PT_NOTE sections that contain + * structures that contain various information. */ + +/* + * New method - extensible architecture description vector. + * + * Because the description vector contains a mix of byte and word + * values, we declare it as an unsigned char array, and use this + * macro to put word values in. + */ +#define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \ + ((x) >> 8) & 0xff, (x) & 0xff + +/* Option vector bits - generic bits in byte 1 */ +#define OV_IGNORE 0x80 /* ignore this vector */ +#define OV_CESSATION_POLICY 0x40 /* halt if unsupported option present*/ + +/* Option vector 1: processor architectures supported */ +#define OV1_PPC_2_00 0x80 /* set if we support PowerPC 2.00 */ +#define OV1_PPC_2_01 0x40 /* set if we support PowerPC 2.01 */ +#define OV1_PPC_2_02 0x20 /* set if we support PowerPC 2.02 */ +#define OV1_PPC_2_03 0x10 /* set if we support PowerPC 2.03 */ +#define OV1_PPC_2_04 0x08 /* set if we support PowerPC 2.04 */ +#define OV1_PPC_2_05 0x04 /* set if we support PowerPC 2.05 */ + +/* Option vector 2: Open Firmware options supported */ +#define OV2_REAL_MODE 0x20 /* set if we want OF in real mode */ + +/* Option vector 3: processor options supported */ +#define OV3_FP 0x80 /* floating point */ +#define OV3_VMX 0x40 /* VMX/Altivec */ + +/* Option vector 5: PAPR/OF options supported */ +#define OV5_LPAR 0x80 /* logical partitioning supported */ +#define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */ +/* ibm,dynamic-reconfiguration-memory property supported */ +#define OV5_DRCONF_MEMORY 0x20 +#define OV5_LARGE_PAGES 0x10 /* large pages supported */ + +/* + * The architecture vector has an array of PVR mask/value pairs, + * followed by # option vectors - 1, followed by the option vectors. + */ +static unsigned char ibm_architecture_vec[] = { + W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */ + W(0xffff0000), W(0x003e0000), /* POWER6 */ + W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */ + 5 - 1, /* 5 option vectors */ + + /* option vector 1: processor architectures supported */ + 3 - 1, /* length */ + 0, /* don't ignore, don't halt */ + OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 | + OV1_PPC_2_04 | OV1_PPC_2_05, + + /* option vector 2: Open Firmware options supported */ + 34 - 1, /* length */ + OV2_REAL_MODE, + 0, 0, + W(0xffffffff), /* real_base */ + W(0xffffffff), /* real_size */ + W(0xffffffff), /* virt_base */ + W(0xffffffff), /* virt_size */ + W(0xffffffff), /* load_base */ + W(64), /* 128MB min RMA */ + W(0xffffffff), /* full client load */ + 0, /* min RMA percentage of total RAM */ + 48, /* max log_2(hash table size) */ + + /* option vector 3: processor options supported */ + 3 - 1, /* length */ + 0, /* don't ignore, don't halt */ + OV3_FP | OV3_VMX, + + /* option vector 4: IBM PAPR implementation */ + 2 - 1, /* length */ + 0, /* don't halt */ + + /* option vector 5: PAPR/OF options */ + 3 - 1, /* length */ + 0, /* don't ignore, don't halt */ + OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES, +}; + +/* Old method - ELF header with PT_NOTE sections */ static struct fake_elf { Elf32_Ehdr elfhdr; Elf32_Phdr phdr[2]; @@ -728,8 +814,26 @@ static struct fake_elf { static void __init prom_send_capabilities(void) { - ihandle elfloader; + ihandle elfloader, root; + prom_arg_t ret; + + root = call_prom("open", 1, 1, ADDR("/")); + if (root != 0) { + /* try calling the ibm,client-architecture-support method */ + if (call_prom_ret("call-method", 3, 2, &ret, + ADDR("ibm,client-architecture-support"), + ADDR(ibm_architecture_vec)) == 0) { + /* the call exists... */ + if (ret) + prom_printf("WARNING: ibm,client-architecture" + "-support call FAILED!\n"); + call_prom("close", 1, 0, root); + return; + } + call_prom("close", 1, 0, root); + } + /* no ibm,client-architecture-support call, try the old way */ elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); if (elfloader == 0) { prom_printf("couldn't open /packages/elf-loader\n"); diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 1d93e73..684ab1d 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -516,3 +516,11 @@ void probe_machine(void) printk(KERN_INFO "Using %s machine description\n", ppc_md.name); } + +int check_legacy_ioport(unsigned long base_port) +{ + if (ppc_md.check_legacy_ioport == NULL) + return 0; + return ppc_md.check_legacy_ioport(base_port); +} +EXPORT_SYMBOL(check_legacy_ioport); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 13e91c4..4467c49 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -594,14 +594,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg) printk("[terminate]%04x %s\n", src, msg); } -int check_legacy_ioport(unsigned long base_port) -{ - if (ppc_md.check_legacy_ioport == NULL) - return 0; - return ppc_md.check_legacy_ioport(base_port); -} -EXPORT_SYMBOL(check_legacy_ioport); - void cpu_die(void) { if (ppc_md.cpu_die) diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 0b98eea..cf56a1d 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -325,6 +325,19 @@ SYSCALL(unshare) SYSCALL(splice) SYSCALL(tee) SYSCALL(vmsplice) +COMPAT_SYS(openat) +SYSCALL(mkdirat) +SYSCALL(mknodat) +SYSCALL(fchownat) +COMPAT_SYS(futimesat) +SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64) +SYSCALL(unlinkat) +SYSCALL(renameat) +SYSCALL(linkat) +SYSCALL(symlinkat) +SYSCALL(readlinkat) +SYSCALL(fchmodat) +SYSCALL(faccessat) /* * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 7370f9f..266b8b2 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -30,13 +30,66 @@ #define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT) #define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT) +#ifdef CONFIG_PPC_64K_PAGES +#define HUGEPTE_INDEX_SIZE (PMD_SHIFT-HPAGE_SHIFT) +#else +#define HUGEPTE_INDEX_SIZE (PUD_SHIFT-HPAGE_SHIFT) +#endif +#define PTRS_PER_HUGEPTE (1 << HUGEPTE_INDEX_SIZE) +#define HUGEPTE_TABLE_SIZE (sizeof(pte_t) << HUGEPTE_INDEX_SIZE) + +#define HUGEPD_SHIFT (HPAGE_SHIFT + HUGEPTE_INDEX_SIZE) +#define HUGEPD_SIZE (1UL << HUGEPD_SHIFT) +#define HUGEPD_MASK (~(HUGEPD_SIZE-1)) + +#define huge_pgtable_cache (pgtable_cache[HUGEPTE_CACHE_NUM]) + +/* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad() + * will choke on pointers to hugepte tables, which is handy for + * catching screwups early. */ +#define HUGEPD_OK 0x1 + +typedef struct { unsigned long pd; } hugepd_t; + +#define hugepd_none(hpd) ((hpd).pd == 0) + +static inline pte_t *hugepd_page(hugepd_t hpd) +{ + BUG_ON(!(hpd.pd & HUGEPD_OK)); + return (pte_t *)(hpd.pd & ~HUGEPD_OK); +} + +static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr) +{ + unsigned long idx = ((addr >> HPAGE_SHIFT) & (PTRS_PER_HUGEPTE-1)); + pte_t *dir = hugepd_page(*hpdp); + + return dir + idx; +} + +static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, + unsigned long address) +{ + pte_t *new = kmem_cache_alloc(huge_pgtable_cache, + GFP_KERNEL|__GFP_REPEAT); + + if (! new) + return -ENOMEM; + + spin_lock(&mm->page_table_lock); + if (!hugepd_none(*hpdp)) + kmem_cache_free(huge_pgtable_cache, new); + else + hpdp->pd = (unsigned long)new | HUGEPD_OK; + spin_unlock(&mm->page_table_lock); + return 0; +} + /* Modelled after find_linux_pte() */ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) { pgd_t *pg; pud_t *pu; - pmd_t *pm; - pte_t *pt; BUG_ON(! in_hugepage_area(mm->context, addr)); @@ -46,26 +99,14 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) if (!pgd_none(*pg)) { pu = pud_offset(pg, addr); if (!pud_none(*pu)) { - pm = pmd_offset(pu, addr); #ifdef CONFIG_PPC_64K_PAGES - /* Currently, we use the normal PTE offset within full - * size PTE pages, thus our huge PTEs are scattered in - * the PTE page and we do waste some. We may change - * that in the future, but the current mecanism keeps - * things much simpler - */ - if (!pmd_none(*pm)) { - /* Note: pte_offset_* are all equivalent on - * ppc64 as we don't have HIGHMEM - */ - pt = pte_offset_kernel(pm, addr); - return pt; - } -#else /* CONFIG_PPC_64K_PAGES */ - /* On 4k pages, we put huge PTEs in the PMD page */ - pt = (pte_t *)pm; - return pt; -#endif /* CONFIG_PPC_64K_PAGES */ + pmd_t *pm; + pm = pmd_offset(pu, addr); + if (!pmd_none(*pm)) + return hugepte_offset((hugepd_t *)pm, addr); +#else + return hugepte_offset((hugepd_t *)pu, addr); +#endif } } @@ -76,8 +117,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) { pgd_t *pg; pud_t *pu; - pmd_t *pm; - pte_t *pt; + hugepd_t *hpdp = NULL; BUG_ON(! in_hugepage_area(mm->context, addr)); @@ -87,23 +127,182 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) pu = pud_alloc(mm, pg, addr); if (pu) { +#ifdef CONFIG_PPC_64K_PAGES + pmd_t *pm; pm = pmd_alloc(mm, pu, addr); - if (pm) { + if (pm) + hpdp = (hugepd_t *)pm; +#else + hpdp = (hugepd_t *)pu; +#endif + } + + if (! hpdp) + return NULL; + + if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr)) + return NULL; + + return hugepte_offset(hpdp, addr); +} + +static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp) +{ + pte_t *hugepte = hugepd_page(*hpdp); + + hpdp->pd = 0; + tlb->need_flush = 1; + pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, HUGEPTE_CACHE_NUM, + HUGEPTE_TABLE_SIZE-1)); +} + #ifdef CONFIG_PPC_64K_PAGES - /* See comment in huge_pte_offset. Note that if we ever - * want to put the page size in the PMD, we would have - * to open code our own pte_alloc* function in order - * to populate and set the size atomically - */ - pt = pte_alloc_map(mm, pm, addr); -#else /* CONFIG_PPC_64K_PAGES */ - pt = (pte_t *)pm; -#endif /* CONFIG_PPC_64K_PAGES */ - return pt; - } +static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, + unsigned long addr, unsigned long end, + unsigned long floor, unsigned long ceiling) +{ + pmd_t *pmd; + unsigned long next; + unsigned long start; + + start = addr; + pmd = pmd_offset(pud, addr); + do { + next = pmd_addr_end(addr, end); + if (pmd_none(*pmd)) + continue; + free_hugepte_range(tlb, (hugepd_t *)pmd); + } while (pmd++, addr = next, addr != end); + + start &= PUD_MASK; + if (start < floor) + return; + if (ceiling) { + ceiling &= PUD_MASK; + if (!ceiling) + return; } + if (end - 1 > ceiling - 1) + return; - return NULL; + pmd = pmd_offset(pud, start); + pud_clear(pud); + pmd_free_tlb(tlb, pmd); +} +#endif + +static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, + unsigned long addr, unsigned long end, + unsigned long floor, unsigned long ceiling) +{ + pud_t *pud; + unsigned long next; + unsigned long start; + + start = addr; + pud = pud_offset(pgd, addr); + do { + next = pud_addr_end(addr, end); +#ifdef CONFIG_PPC_64K_PAGES + if (pud_none_or_clear_bad(pud)) + continue; + hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling); +#else + if (pud_none(*pud)) + continue; + free_hugepte_range(tlb, (hugepd_t *)pud); +#endif + } while (pud++, addr = next, addr != end); + + start &= PGDIR_MASK; + if (start < floor) + return; + if (ceiling) { + ceiling &= PGDIR_MASK; + if (!ceiling) + return; + } + if (end - 1 > ceiling - 1) + return; + + pud = pud_offset(pgd, start); + pgd_clear(pgd); + pud_free_tlb(tlb, pud); +} + +/* + * This function frees user-level page tables of a process. + * + * Must be called with pagetable lock held. + */ +void hugetlb_free_pgd_range(struct mmu_gather **tlb, + unsigned long addr, unsigned long end, + unsigned long floor, unsigned long ceiling) +{ + pgd_t *pgd; + unsigned long next; + unsigned long start; + + /* + * Comments below take from the normal free_pgd_range(). They + * apply here too. The tests against HUGEPD_MASK below are + * essential, because we *don't* test for this at the bottom + * level. Without them we'll attempt to free a hugepte table + * when we unmap just part of it, even if there are other + * active mappings using it. + * + * The next few lines have given us lots of grief... + * + * Why are we testing HUGEPD* at this top level? Because + * often there will be no work to do at all, and we'd prefer + * not to go all the way down to the bottom just to discover + * that. + * + * Why all these "- 1"s? Because 0 represents both the bottom + * of the address space and the top of it (using -1 for the + * top wouldn't help much: the masks would do the wrong thing). + * The rule is that addr 0 and floor 0 refer to the bottom of + * the address space, but end 0 and ceiling 0 refer to the top + * Comparisons need to use "end - 1" and "ceiling - 1" (though + * that end 0 case should be mythical). + * + * Wherever addr is brought up or ceiling brought down, we + * must be careful to reject "the opposite 0" before it + * confuses the subsequent tests. But what about where end is + * brought down by HUGEPD_SIZE below? no, end can't go down to + * 0 there. + * + * Whereas we round start (addr) and ceiling down, by different + * masks at different levels, in order to test whether a table + * now has no other vmas using it, so can be freed, we don't + * bother to round floor or end up - the tests don't need that. + */ + + addr &= HUGEPD_MASK; + if (addr < floor) { + addr += HUGEPD_SIZE; + if (!addr) + return; + } + if (ceiling) { + ceiling &= HUGEPD_MASK; + if (!ceiling) + return; + } + if (end - 1 > ceiling - 1) + end -= HUGEPD_SIZE; + if (addr > end - 1) + return; + + start = addr; + pgd = pgd_offset((*tlb)->mm, addr); + do { + BUG_ON(! in_hugepage_area((*tlb)->mm->context, addr)); + next = pgd_addr_end(addr, end); + if (pgd_none_or_clear_bad(pgd)) + continue; + hugetlb_free_pud_range(*tlb, pgd, addr, next, floor, ceiling); + } while (pgd++, addr = next, addr != end); } void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, @@ -841,3 +1040,27 @@ repeat: out: return err; } + +static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) +{ + memset(addr, 0, kmem_cache_size(cache)); +} + +static int __init hugetlbpage_init(void) +{ + if (!cpu_has_feature(CPU_FTR_16M_PAGE)) + return -ENODEV; + + huge_pgtable_cache = kmem_cache_create("hugepte_cache", + HUGEPTE_TABLE_SIZE, + HUGEPTE_TABLE_SIZE, + SLAB_HWCACHE_ALIGN | + SLAB_MUST_HWCACHE_ALIGN, + zero_ctor, NULL); + if (! huge_pgtable_cache) + panic("hugetlbpage_init(): could not create hugepte cache\n"); + + return 0; +} + +module_init(hugetlbpage_init); diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index babebd1..9e30f96 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -162,7 +162,14 @@ static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { }; #endif /* CONFIG_PPC_64K_PAGES */ +#ifdef CONFIG_HUGETLB_PAGE +/* Hugepages need one extra cache, initialized in hugetlbpage.c. We + * can't put into the tables above, because HPAGE_SHIFT is not compile + * time constant. */ +kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1]; +#else kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; +#endif void pgtable_cache_init(void) { diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 269dda4..ef47a62 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -306,19 +306,19 @@ spu_request_irqs(struct spu *spu) snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number); ret = request_irq(irq_base + spu->isrc, - spu_irq_class_0, 0, spu->irq_c0, spu); + spu_irq_class_0, SA_INTERRUPT, spu->irq_c0, spu); if (ret) goto out; snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number); ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, - spu_irq_class_1, 0, spu->irq_c1, spu); + spu_irq_class_1, SA_INTERRUPT, spu->irq_c1, spu); if (ret) goto out1; snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number); ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc, - spu_irq_class_2, 0, spu->irq_c2, spu); + spu_irq_class_2, SA_INTERRUPT, spu->irq_c2, spu); if (ret) goto out2; goto out; @@ -487,10 +487,14 @@ int spu_irq_class_1_bottom(struct spu *spu) ea = spu->dar; dsisr = spu->dsisr; if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) { + u64 flags; + access = (_PAGE_PRESENT | _PAGE_USER); access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; + local_irq_save(flags); if (hash_page(ea, access, 0x300) != 0) error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; + local_irq_restore(flags); } if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) { if ((ret = spu_handle_mm_fault(spu)) != 0) diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index b283380..95b3643 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -319,6 +319,19 @@ void *spu_syscall_table[] = { [__NR_splice] sys_splice, [__NR_tee] sys_tee, [__NR_vmsplice] sys_vmsplice, + [__NR_openat] sys_openat, + [__NR_mkdirat] sys_mkdirat, + [__NR_mknodat] sys_mknodat, + [__NR_fchownat] sys_fchownat, + [__NR_futimesat] sys_futimesat, + [__NR_newfstatat] sys_newfstatat, + [__NR_unlinkat] sys_unlinkat, + [__NR_renameat] sys_renameat, + [__NR_linkat] sys_linkat, + [__NR_symlinkat] sys_symlinkat, + [__NR_readlinkat] sys_readlinkat, + [__NR_fchmodat] sys_fchmodat, + [__NR_faccessat] sys_faccessat, }; long spu_sys_callback(struct spu_syscall_block *s) diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index f841972..554776d 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -331,7 +331,7 @@ static void __init ocotea_init(void) void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - ibm44x_platform_init(r3, r4, r5, r6, r7); + ibm440gx_platform_init(r3, r4, r5, r6, r7); ppc_md.setup_arch = ocotea_setup_arch; ppc_md.show_cpuinfo = ocotea_show_cpuinfo; diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c index bc9b94f..e62b757 100644 --- a/arch/ppc/platforms/mpc8272ads_setup.c +++ b/arch/ppc/platforms/mpc8272ads_setup.c @@ -26,11 +26,35 @@ #include <asm/irq.h> #include <asm/ppc_sys.h> #include <asm/ppcboot.h> +#include <linux/fs_uart_pd.h> #include "pq2ads_pd.h" static void init_fcc1_ioports(void); static void init_fcc2_ioports(void); +static void init_scc1_uart_ioports(void); +static void init_scc4_uart_ioports(void); + +static struct fs_uart_platform_info mpc8272_uart_pdata[] = { + [fsid_scc1_uart] = { + .init_ioports = init_scc1_uart_ioports, + .fs_no = fsid_scc1_uart, + .brg = 1, + .tx_num_fifo = 4, + .tx_buf_size = 32, + .rx_num_fifo = 4, + .rx_buf_size = 32, + }, + [fsid_scc4_uart] = { + .init_ioports = init_scc4_uart_ioports, + .fs_no = fsid_scc4_uart, + .brg = 4, + .tx_num_fifo = 4, + .tx_buf_size = 32, + .rx_num_fifo = 4, + .rx_buf_size = 32, + }, +}; static struct fs_mii_bus_info mii_bus_info = { .method = fsmii_bitbang, @@ -201,6 +225,55 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev, } } +static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev, + int idx) +{ + bd_t *bd = (bd_t *) __res; + struct fs_uart_platform_info *pinfo; + int num = ARRAY_SIZE(mpc8272_uart_pdata); + int id = fs_uart_id_scc2fsid(idx); + + /* no need to alter anything if console */ + if ((id <= num) && (!pdev->dev.platform_data)) { + pinfo = &mpc8272_uart_pdata[id]; + pinfo->uart_clk = bd->bi_intfreq; + pdev->dev.platform_data = pinfo; + } +} + +static void init_scc1_uart_ioports(void) +{ + cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t)); + + /* SCC1 is only on port D */ + setbits32(&immap->im_ioport.iop_ppard,0x00000003); + clrbits32(&immap->im_ioport.iop_psord,0x00000001); + setbits32(&immap->im_ioport.iop_psord,0x00000002); + clrbits32(&immap->im_ioport.iop_pdird,0x00000001); + setbits32(&immap->im_ioport.iop_pdird,0x00000002); + + /* Wire BRG1 to SCC1 */ + clrbits32(&immap->im_cpmux.cmx_scr,0x00ffffff); + + iounmap(immap); +} + +static void init_scc4_uart_ioports(void) +{ + cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t)); + + setbits32(&immap->im_ioport.iop_ppard,0x00000600); + clrbits32(&immap->im_ioport.iop_psord,0x00000600); + clrbits32(&immap->im_ioport.iop_pdird,0x00000200); + setbits32(&immap->im_ioport.iop_pdird,0x00000400); + + /* Wire BRG4 to SCC4 */ + clrbits32(&immap->im_cpmux.cmx_scr,0x000000ff); + setbits32(&immap->im_cpmux.cmx_scr,0x0000001b); + + iounmap(immap); +} + static int mpc8272ads_platform_notify(struct device *dev) { static const struct platform_notify_dev_map dev_map[] = { @@ -209,6 +282,10 @@ static int mpc8272ads_platform_notify(struct device *dev) .rtn = mpc8272ads_fixup_enet_pdata }, { + .bus_id = "fsl-cpm-scc:uart", + .rtn = mpc + }, + { .bus_id = NULL } }; @@ -230,7 +307,44 @@ int __init mpc8272ads_init(void) ppc_sys_device_enable(MPC82xx_CPM_FCC1); ppc_sys_device_enable(MPC82xx_CPM_FCC2); + /* to be ready for console, let's attach pdata here */ +#ifdef CONFIG_SERIAL_CPM_SCC1 + ppc_sys_device_setfunc(MPC82xx_CPM_SCC1, PPC_SYS_FUNC_UART); + ppc_sys_device_enable(MPC82xx_CPM_SCC1); + +#endif + +#ifdef CONFIG_SERIAL_CPM_SCC4 + ppc_sys_device_setfunc(MPC82xx_CPM_SCC4, PPC_SYS_FUNC_UART); + ppc_sys_device_enable(MPC82xx_CPM_SCC4); +#endif + + return 0; } +/* + To prevent confusion, console selection is gross: + by 0 assumed SCC1 and by 1 assumed SCC4 + */ +struct platform_device* early_uart_get_pdev(int index) +{ + bd_t *bd = (bd_t *) __res; + struct fs_uart_platform_info *pinfo; + + struct platform_device* pdev = NULL; + if(index) { /*assume SCC4 here*/ + pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC4]; + pinfo = &mpc8272<F12>_uart_pdata[1]; + } else { /*over SCC1*/ + pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1]; + pinfo = &mpc8272_uart_pdata[0]; + } + + pinfo->uart_clk = bd->bi_intfreq; + pdev->dev.platform_data = pinfo; + ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR); + return NULL; +} + arch_initcall(mpc8272ads_init); diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c index ac8fcc6..6ce3b84 100644 --- a/arch/ppc/platforms/mpc866ads_setup.c +++ b/arch/ppc/platforms/mpc866ads_setup.c @@ -20,6 +20,7 @@ #include <linux/device.h> #include <linux/fs_enet_pd.h> +#include <linux/fs_uart_pd.h> #include <linux/mii.h> #include <asm/delay.h> @@ -37,6 +38,11 @@ extern unsigned char __res[]; +static void setup_fec1_ioports(void); +static void setup_scc1_ioports(void); +static void setup_smc1_ioports(void); +static void setup_smc2_ioports(void); + static struct fs_mii_bus_info fec_mii_bus_info = { .method = fsmii_fec, .id = 0, @@ -79,6 +85,28 @@ static struct fs_platform_info mpc8xx_scc_pdata = { .phy_irq = -1, .bus_info = &scc_mii_bus_info, + +}; + +static struct fs_uart_platform_info mpc866_uart_pdata[] = { + [fsid_smc1_uart] = { + .brg = 1, + .fs_no = fsid_smc1_uart, + .init_ioports = setup_smc1_ioports, + .tx_num_fifo = 4, + .tx_buf_size = 32, + .rx_num_fifo = 4, + .rx_buf_size = 32, + }, + [fsid_smc2_uart] = { + .brg = 2, + .fs_no = fsid_smc2_uart, + .init_ioports = setup_smc2_ioports, + .tx_num_fifo = 4, + .tx_buf_size = 32, + .rx_num_fifo = 4, + .rx_buf_size = 32, + }, }; void __init board_init(void) @@ -92,9 +120,12 @@ void __init board_init(void) printk(KERN_CRIT "Could not remap BCSR1\n"); return; } + #ifdef CONFIG_SERIAL_CPM_SMC1 cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */ clrbits32(bcsr_io,(0x80000000 >> 7)); + cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX); + cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); #else setbits32(bcsr_io,(0x80000000 >> 7)); @@ -108,6 +139,8 @@ void __init board_init(void) cp->cp_simode &= ~(0xe0000000 >> 1); cp->cp_simode |= (0x20000000 >> 1); /* brg2 */ clrbits32(bcsr_io,(0x80000000 >> 13)); + cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX); + cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); #else clrbits32(bcsr_io,(0x80000000 >> 13)); cp->cp_pbpar &= ~(0x00000c00); @@ -232,6 +265,74 @@ static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev, mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1); } +static void setup_smc1_ioports(void) +{ + immap_t *immap = (immap_t *) IMAP_ADDR; + unsigned *bcsr_io; + unsigned int iobits = 0x000000c0; + + bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); + + if (bcsr_io == NULL) { + printk(KERN_CRIT "Could not remap BCSR1\n"); + return; + } + + clrbits32(bcsr_io,BCSR1_RS232EN_1); + iounmap(bcsr_io); + + setbits32(&immap->im_cpm.cp_pbpar, iobits); + clrbits32(&immap->im_cpm.cp_pbdir, iobits); + clrbits16(&immap->im_cpm.cp_pbodr, iobits); + +} + +static void setup_smc2_ioports(void) +{ + immap_t *immap = (immap_t *) IMAP_ADDR; + unsigned *bcsr_io; + unsigned int iobits = 0x00000c00; + + bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); + + if (bcsr_io == NULL) { + printk(KERN_CRIT "Could not remap BCSR1\n"); + return; + } + + clrbits32(bcsr_io,BCSR1_RS232EN_2); + + iounmap(bcsr_io); + +#ifndef CONFIG_SERIAL_CPM_ALT_SMC2 + setbits32(&immap->im_cpm.cp_pbpar, iobits); + clrbits32(&immap->im_cpm.cp_pbdir, iobits); + clrbits16(&immap->im_cpm.cp_pbodr, iobits); +#else + setbits16(&immap->im_ioport.iop_papar, iobits); + clrbits16(&immap->im_ioport.iop_padir, iobits); + clrbits16(&immap->im_ioport.iop_paodr, iobits); +#endif + +} + +static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev, + int idx) +{ + bd_t *bd = (bd_t *) __res; + struct fs_uart_platform_info *pinfo; + int num = ARRAY_SIZE(mpc866_uart_pdata); + + int id = fs_uart_id_smc2fsid(idx); + + /* no need to alter anything if console */ + if ((id <= num) && (!pdev->dev.platform_data)) { + pinfo = &mpc866_uart_pdata[id]; + pinfo->uart_clk = bd->bi_intfreq; + pdev->dev.platform_data = pinfo; + } +} + static int mpc866ads_platform_notify(struct device *dev) { static const struct platform_notify_dev_map dev_map[] = { @@ -244,6 +345,10 @@ static int mpc866ads_platform_notify(struct device *dev) .rtn = mpc866ads_fixup_scc_enet_pdata, }, { + .bus_id = "fsl-cpm-smc:uart", + .rtn = mpc866ads_fixup_uart_pdata + }, + { .bus_id = NULL } }; @@ -267,7 +372,42 @@ int __init mpc866ads_init(void) #endif ppc_sys_device_enable(MPC8xx_CPM_FEC1); +/* Since either of the uarts could be used as console, they need to ready */ +#ifdef CONFIG_SERIAL_CPM_SMC1 + ppc_sys_device_enable(MPC8xx_CPM_SMC1); + ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART); +#endif + +#ifdef CONFIG_SERIAL_CPM_SMCer + ppc_sys_device_enable(MPC8xx_CPM_SMC2); + ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART); +#endif + return 0; } +/* + To prevent confusion, console selection is gross: + by 0 assumed SMC1 and by 1 assumed SMC2 + */ +struct platform_device* early_uart_get_pdev(int index) +{ + bd_t *bd = (bd_t *) __res; + struct fs_uart_platform_info *pinfo; + + struct platform_device* pdev = NULL; + if(index) { /*assume SMC2 here*/ + pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2]; + pinfo = &mpc866_uart_pdata[1]; + } else { /*over SMC1*/ + pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1]; + pinfo = &mpc866_uart_pdata[0]; + } + + pinfo->uart_clk = bd->bi_intfreq; + pdev->dev.platform_data = pinfo; + ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR); + return NULL; +} + arch_initcall(mpc866ads_init); diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c index 50a99e5..4b88679 100644 --- a/arch/ppc/platforms/mpc885ads_setup.c +++ b/arch/ppc/platforms/mpc885ads_setup.c @@ -20,6 +20,7 @@ #include <linux/device.h> #include <linux/fs_enet_pd.h> +#include <linux/fs_uart_pd.h> #include <linux/mii.h> #include <asm/delay.h> @@ -35,9 +36,32 @@ #include <asm/ppc_sys.h> extern unsigned char __res[]; +static void setup_smc1_ioports(void); +static void setup_smc2_ioports(void); static void __init mpc885ads_scc_phy_init(char); +static struct fs_uart_platform_info mpc885_uart_pdata[] = { + [fsid_smc1_uart] = { + .brg = 1, + .fs_no = fsid_smc1_uart, + .init_ioports = setup_smc1_ioports, + .tx_num_fifo = 4, + .tx_buf_size = 32, + .rx_num_fifo = 4, + .rx_buf_size = 32, + }, + [fsid_smc2_uart] = { + .brg = 2, + .fs_no = fsid_smc2_uart, + .init_ioports = setup_smc2_ioports, + .tx_num_fifo = 4, + .tx_buf_size = 32, + .rx_num_fifo = 4, + .rx_buf_size = 32, + }, +}; + static struct fs_mii_bus_info fec_mii_bus_info = { .method = fsmii_fec, .id = 0, @@ -116,6 +140,8 @@ void __init board_init(void) #ifdef CONFIG_SERIAL_CPM_SMC1 cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */ clrbits32(bcsr_io, BCSR1_RS232EN_1); + cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX); + cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); #else setbits32(bcsr_io,BCSR1_RS232EN_1); cp->cp_smc[0].smc_smcmr = 0; @@ -126,6 +152,8 @@ void __init board_init(void) cp->cp_simode &= ~(0xe0000000 >> 1); cp->cp_simode |= (0x20000000 >> 1); /* brg2 */ clrbits32(bcsr_io,BCSR1_RS232EN_2); + cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX); + cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); #else setbits32(bcsr_io,BCSR1_RS232EN_2); cp->cp_smc[1].smc_smcmr = 0; @@ -343,6 +371,70 @@ static void mpc885ads_scc_phy_init(char phy_addr) out_be32(&fecp->fec_mii_speed, 0); } +static void setup_smc1_ioports(void) +{ + immap_t *immap = (immap_t *) IMAP_ADDR; + unsigned *bcsr_io; + unsigned int iobits = 0x000000c0; + + bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); + + if (bcsr_io == NULL) { + printk(KERN_CRIT "Could not remap BCSR1\n"); + return; + } + clrbits32(bcsr_io,BCSR1_RS232EN_1); + iounmap(bcsr_io); + + setbits32(&immap->im_cpm.cp_pbpar, iobits); + clrbits32(&immap->im_cpm.cp_pbdir, iobits); + clrbits16(&immap->im_cpm.cp_pbodr, iobits); +} + +static void setup_smc2_ioports(void) +{ + immap_t *immap = (immap_t *) IMAP_ADDR; + unsigned *bcsr_io; + unsigned int iobits = 0x00000c00; + + bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); + + if (bcsr_io == NULL) { + printk(KERN_CRIT "Could not remap BCSR1\n"); + return; + } + clrbits32(bcsr_io,BCSR1_RS232EN_2); + iounmap(bcsr_io); + +#ifndef CONFIG_SERIAL_CPM_ALT_SMC2 + setbits32(&immap->im_cpm.cp_pbpar, iobits); + clrbits32(&immap->im_cpm.cp_pbdir, iobits); + clrbits16(&immap->im_cpm.cp_pbodr, iobits); +#else + setbits16(&immap->im_ioport.iop_papar, iobits); + clrbits16(&immap->im_ioport.iop_padir, iobits); + clrbits16(&immap->im_ioport.iop_paodr, iobits); +#endif +} + +static void __init mpc885ads_fixup_uart_pdata(struct platform_device *pdev, + int idx) +{ + bd_t *bd = (bd_t *) __res; + struct fs_uart_platform_info *pinfo; + int num = ARRAY_SIZE(mpc885_uart_pdata); + + int id = fs_uart_id_smc2fsid(idx); + + /* no need to alter anything if console */ + if ((id <= num) && (!pdev->dev.platform_data)) { + pinfo = &mpc885_uart_pdata[id]; + pinfo->uart_clk = bd->bi_intfreq; + pdev->dev.platform_data = pinfo; + } +} + + static int mpc885ads_platform_notify(struct device *dev) { @@ -356,12 +448,17 @@ static int mpc885ads_platform_notify(struct device *dev) .rtn = mpc885ads_fixup_scc_enet_pdata, }, { + .bus_id = "fsl-cpm-smc:uart", + .rtn = mpc885ads_fixup_uart_pdata + }, + { .bus_id = NULL } }; platform_notify_map(dev_map,dev); + return 0; } int __init mpc885ads_init(void) @@ -383,7 +480,41 @@ int __init mpc885ads_init(void) ppc_sys_device_enable(MPC8xx_CPM_FEC2); #endif +#ifdef CONFIG_SERIAL_CPM_SMC1 + ppc_sys_device_enable(MPC8xx_CPM_SMC1); + ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART); +#endif + +#ifdef CONFIG_SERIAL_CPM_SMC2 + ppc_sys_device_enable(MPC8xx_CPM_SMC2); + ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART); +#endif return 0; } arch_initcall(mpc885ads_init); + +/* + To prevent confusion, console selection is gross: + by 0 assumed SMC1 and by 1 assumed SMC2 + */ +struct platform_device* early_uart_get_pdev(int index) +{ + bd_t *bd = (bd_t *) __res; + struct fs_uart_platform_info *pinfo; + + struct platform_device* pdev = NULL; + if(index) { /*assume SMC2 here*/ + pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2]; + pinfo = &mpc885_uart_pdata[1]; + } else { /*over SMC1*/ + pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1]; + pinfo = &mpc885_uart_pdata[0]; + } + + pinfo->uart_clk = bd->bi_intfreq; + pdev->dev.platform_data = pinfo; + ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR); + return NULL; +} + diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c index 3365fd7..7fc2e02 100644 --- a/arch/ppc/platforms/pq2ads.c +++ b/arch/ppc/platforms/pq2ads.c @@ -14,11 +14,40 @@ #include <linux/init.h> +#include <asm/io.h> #include <asm/mpc8260.h> +#include <asm/cpm2.h> +#include <asm/immap_cpm2.h> void __init m82xx_board_setup(void) { + cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t)); + u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32)); + /* Enable the 2nd UART port */ - *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2; + clrbits32(bcsr, BCSR1_RS232_EN2); + +#ifdef CONFIG_SERIAL_CPM_SCC1 + clrbits32((u32*)&immap->im_scc[0].scc_sccm, UART_SCCM_TX | UART_SCCM_RX); + clrbits32((u32*)&immap->im_scc[0].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#endif + +#ifdef CONFIG_SERIAL_CPM_SCC2 + clrbits32((u32*)&immap->im_scc[1].scc_sccm, UART_SCCM_TX | UART_SCCM_RX); + clrbits32((u32*)&immap->im_scc[1].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#endif + +#ifdef CONFIG_SERIAL_CPM_SCC3 + clrbits32((u32*)&immap->im_scc[2].scc_sccm, UART_SCCM_TX | UART_SCCM_RX); + clrbits32((u32*)&immap->im_scc[2].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#endif + +#ifdef CONFIG_SERIAL_CPM_SCC4 + clrbits32((u32*)&immap->im_scc[3].scc_sccm, UART_SCCM_TX | UART_SCCM_RX); + clrbits32((u32*)&immap->im_scc[3].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#endif + + iounmap(bcsr); + iounmap(immap); } diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c index a7dd55f..f6cc168 100644 --- a/arch/ppc/syslib/ibm440gx_common.c +++ b/arch/ppc/syslib/ibm440gx_common.c @@ -2,7 +2,7 @@ * PPC440GX system library * * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> - * Copyright (c) 2003, 2004 Zultys Technologies + * Copyright (c) 2003 - 2006 Zultys Technologies * * 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 @@ -282,3 +282,14 @@ int ibm440gx_show_cpuinfo(struct seq_file *m){ return 0; } +void __init ibm440gx_platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, + unsigned long r7) +{ + /* Erratum 440_43 workaround, disable L1 cache parity checking */ + if (!strcmp(cur_cpu_spec->cpu_name, "440GX Rev. C") || + !strcmp(cur_cpu_spec->cpu_name, "440GX Rev. F")) + mtspr(SPRN_CCR1, mfspr(SPRN_CCR1) | CCR1_DPC); + + ibm44x_platform_init(r3, r4, r5, r6, r7); +} diff --git a/arch/ppc/syslib/ibm440gx_common.h b/arch/ppc/syslib/ibm440gx_common.h index a2ab9fa..a03ec60 100644 --- a/arch/ppc/syslib/ibm440gx_common.h +++ b/arch/ppc/syslib/ibm440gx_common.h @@ -29,6 +29,10 @@ void ibm440gx_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk, unsigned int ser_clk) __init; +/* common 440GX platform init */ +void ibm440gx_platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) __init; + /* Enable L2 cache */ void ibm440gx_l2c_enable(void) __init; diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c index bd41ed8..6f53638 100644 --- a/arch/ppc/syslib/mpc8xx_devices.c +++ b/arch/ppc/syslib/mpc8xx_devices.c @@ -170,12 +170,18 @@ struct platform_device ppc_sys_platform_devices[] = { [MPC8xx_CPM_SMC1] = { .name = "fsl-cpm-smc", .id = 1, - .num_resources = 2, + .num_resources = 3, .resource = (struct resource[]) { { .name = "regs", - .start = 0xa82, - .end = 0xa91, + .start = 0xa80, + .end = 0xa8f, + .flags = IORESOURCE_MEM, + }, + { + .name = "pram", + .start = 0x3e80, + .end = 0x3ebf, .flags = IORESOURCE_MEM, }, { @@ -189,15 +195,22 @@ struct platform_device ppc_sys_platform_devices[] = { [MPC8xx_CPM_SMC2] = { .name = "fsl-cpm-smc", .id = 2, - .num_resources = 2, + .num_resources = 3, .resource = (struct resource[]) { { .name = "regs", - .start = 0xa92, - .end = 0xaa1, + .start = 0xa90, + .end = 0xa9f, .flags = IORESOURCE_MEM, }, { + .name = "pram", + .start = 0x3f80, + .end = 0x3fbf, + .flags = IORESOURCE_MEM, + + }, + { .name = "interrupt", .start = MPC8xx_INT_SMC2, .end = MPC8xx_INT_SMC2, diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index 7662c4e..2d48018 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c @@ -109,9 +109,11 @@ ppc_sys_fixup_mem_resource(struct platform_device *pdev, phys_addr_t paddr) int i; for (i = 0; i < pdev->num_resources; i++) { struct resource *r = &pdev->resource[i]; - if ((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) { + if (((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) && + ((r->flags & PPC_SYS_IORESOURCE_FIXUPPED) != PPC_SYS_IORESOURCE_FIXUPPED)) { r->start += paddr; r->end += paddr; + r->flags |= PPC_SYS_IORESOURCE_FIXUPPED; } } } diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c index 75e64f1..433b0fa 100644 --- a/arch/ppc/syslib/pq2_sys.c +++ b/arch/ppc/syslib/pq2_sys.c @@ -113,13 +113,13 @@ struct ppc_sys_spec ppc_sys_specs[] = { .ppc_sys_name = "8248", .mask = 0x0000ff00, .value = 0x00000c00, - .num_devices = 11, + .num_devices = 12, .device_list = (enum ppc_sys_devices[]) { MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1, - MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SMC1, - MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C, - MPC82xx_CPM_USB, MPC82xx_SEC1, + MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4, + MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, + MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1, }, }, { diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index bedb689..dff1e67 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4301,7 +4301,7 @@ static int __init floppy_init(void) } use_virtual_dma = can_use_virtual_dma & 1; -#if defined(CONFIG_PPC64) +#if defined(CONFIG_PPC_MERGE) if (check_legacy_ioport(FDC1)) { del_timer(&fd_timeout); err = -ENODEV; diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h index 9a92216..cc21914 100644 --- a/drivers/input/serio/i8042-io.h +++ b/drivers/input/serio/i8042-io.h @@ -67,14 +67,14 @@ static inline int i8042_platform_init(void) * On some platforms touching the i8042 data register region can do really * bad things. Because of this the region is always reserved on such boxes. */ -#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64) +#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC_MERGE) if (!request_region(I8042_DATA_REG, 16, "i8042")) return -EBUSY; #endif i8042_reset = 1; -#if defined(CONFIG_PPC64) +#if defined(CONFIG_PPC_MERGE) if (check_legacy_ioport(I8042_DATA_REG)) return -EBUSY; if (!request_region(I8042_DATA_REG, 16, "i8042")) diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index f9d87b8..320b3d9 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -616,7 +616,7 @@ static struct snd_kcontrol_new snd_cx88_capture_volume = { * Only boards with eeprom and byte 1 at eeprom=1 have it */ -static struct pci_device_id cx88_audio_pci_tbl[] = { +static struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = { {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0, } diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3e73026..a480a37 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -446,7 +446,9 @@ config SCSI_DPT_I2O config SCSI_ADVANSYS tristate "AdvanSys SCSI support" - depends on (ISA || EISA || PCI) && SCSI && BROKEN + depends on SCSI + depends on ISA || EISA || PCI + depends on BROKEN || X86_32 help This is a driver for all SCSI host adapters manufactured by AdvanSys. It is documented in the kernel source in diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 28b9305..2a41963 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -2051,7 +2051,7 @@ STATIC ASC_DCNT AscGetMaxDmaCount(ushort); #define ADV_VADDR_TO_U32 virt_to_bus #define ADV_U32_TO_VADDR bus_to_virt -#define AdvPortAddr ulong /* Virtual memory address size */ +#define AdvPortAddr void __iomem * /* Virtual memory address size */ /* * Define Adv Library required memory access macros. diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 73c8a08..aa5eb7d 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h @@ -10,6 +10,8 @@ #define CPM_UART_H #include <linux/config.h> +#include <linux/platform_device.h> +#include <linux/fs_uart_pd.h> #if defined(CONFIG_CPM2) #include "cpm_uart_cpm2.h" @@ -26,14 +28,14 @@ #define FLAG_SMC 0x00000002 #define FLAG_CONSOLE 0x00000001 -#define UART_SMC1 0 -#define UART_SMC2 1 -#define UART_SCC1 2 -#define UART_SCC2 3 -#define UART_SCC3 4 -#define UART_SCC4 5 +#define UART_SMC1 fsid_smc1_uart +#define UART_SMC2 fsid_smc2_uart +#define UART_SCC1 fsid_scc1_uart +#define UART_SCC2 fsid_scc2_uart +#define UART_SCC3 fsid_scc3_uart +#define UART_SCC4 fsid_scc4_uart -#define UART_NR 6 +#define UART_NR fs_uart_nr #define RX_NUM_FIFO 4 #define RX_BUF_SIZE 32 @@ -64,6 +66,7 @@ struct uart_cpm_port { uint dp_addr; void *mem_addr; dma_addr_t dma_addr; + u32 mem_size; /* helpers */ int baud; int bits; @@ -90,4 +93,36 @@ void scc2_lineif(struct uart_cpm_port *pinfo); void scc3_lineif(struct uart_cpm_port *pinfo); void scc4_lineif(struct uart_cpm_port *pinfo); +/* + virtual to phys transtalion +*/ +static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo) +{ + int offset; + u32 val = (u32)addr; + /* sane check */ + if ((val >= (u32)pinfo->mem_addr) && + (val<((u32)pinfo->mem_addr + pinfo->mem_size))) { + offset = val - (u32)pinfo->mem_addr; + return pinfo->dma_addr+offset; + } + printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val); + return 0; +} + +static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo) +{ + int offset; + u32 val = addr; + /* sane check */ + if ((val >= pinfo->dma_addr) && + (val<(pinfo->dma_addr + pinfo->mem_size))) { + offset = val - (u32)pinfo->dma_addr; + return (void*)(pinfo->mem_addr+offset); + } + printk("%s(): address %x to translate out of range!\n", __FUNCTION__, val); + return 0; +} + + #endif /* CPM_UART_H */ diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index b7bf4c6..ced193b 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -41,6 +41,7 @@ #include <linux/device.h> #include <linux/bootmem.h> #include <linux/dma-mapping.h> +#include <linux/fs_uart_pd.h> #include <asm/io.h> #include <asm/irq.h> @@ -60,7 +61,7 @@ /* Track which ports are configured as uarts */ int cpm_uart_port_map[UART_NR]; /* How many ports did we config as uarts */ -int cpm_uart_nr; +int cpm_uart_nr = 0; /**************************************************************/ @@ -71,18 +72,36 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); /**************************************************************/ -static inline unsigned long cpu2cpm_addr(void *addr) + +/* Place-holder for board-specific stuff */ +struct platform_device* __attribute__ ((weak)) __init +early_uart_get_pdev(int index) { - if ((unsigned long)addr >= CPM_ADDR) - return (unsigned long)addr; - return virt_to_bus(addr); + return NULL; } -static inline void *cpm2cpu_addr(unsigned long addr) + +void cpm_uart_count(void) { - if (addr >= CPM_ADDR) - return (void *)addr; - return bus_to_virt(addr); + cpm_uart_nr = 0; +#ifdef CONFIG_SERIAL_CPM_SMC1 + cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1; +#endif +#ifdef CONFIG_SERIAL_CPM_SMC2 + cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2; +#endif +#ifdef CONFIG_SERIAL_CPM_SCC1 + cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1; +#endif +#ifdef CONFIG_SERIAL_CPM_SCC2 + cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2; +#endif +#ifdef CONFIG_SERIAL_CPM_SCC3 + cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3; +#endif +#ifdef CONFIG_SERIAL_CPM_SCC4 + cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4; +#endif } /* @@ -258,7 +277,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) } /* get pointer */ - cp = cpm2cpu_addr(bdp->cbd_bufaddr); + cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); /* loop through the buffer */ while (i-- > 0) { @@ -601,7 +620,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) /* Pick next descriptor and fill from buffer */ bdp = pinfo->tx_cur; - p = cpm2cpu_addr(bdp->cbd_bufaddr); + p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); *p++ = port->x_char; bdp->cbd_datlen = 1; @@ -628,7 +647,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { count = 0; - p = cpm2cpu_addr(bdp->cbd_bufaddr); + p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); while (count < pinfo->tx_fifosize) { *p++ = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -677,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) mem_addr = pinfo->mem_addr; bdp = pinfo->rx_cur = pinfo->rx_bd_base; for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; mem_addr += pinfo->rx_fifosize; } - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; /* Set the physical address of the host memory @@ -692,12 +711,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); bdp = pinfo->tx_cur = pinfo->tx_bd_base; for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); bdp->cbd_sc = BD_SC_INTRPT; mem_addr += pinfo->tx_fifosize; } - bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo); bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; } @@ -829,14 +848,6 @@ static int cpm_uart_request_port(struct uart_port *port) if (pinfo->flags & FLAG_CONSOLE) return 0; - /* - * Setup any port IO, connect any baud rate generators, - * etc. This is expected to be handled by board - * dependant code - */ - if (pinfo->set_lineif) - pinfo->set_lineif(pinfo); - if (IS_SMC(pinfo)) { pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); @@ -988,6 +999,54 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, }; +int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con) +{ + struct resource *r; + struct fs_uart_platform_info *pdata = pdev->dev.platform_data; + int idx = pdata->fs_no; /* It is UART_SMCx or UART_SCCx index */ + struct uart_cpm_port *pinfo; + int line; + u32 mem, pram; + + for (line=0; line<UART_NR && cpm_uart_port_map[line]!=pdata->fs_no; line++); + + pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx]; + + pinfo->brg = pdata->brg; + + if (!is_con) { + pinfo->port.line = line; + pinfo->port.flags = UPF_BOOT_AUTOCONF; + } + + if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"))) + return -EINVAL; + mem = r->start; + + if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram"))) + return -EINVAL; + pram = r->start; + + if(idx > fsid_smc2_uart) { + pinfo->sccp = (scc_t *)mem; + pinfo->sccup = (scc_uart_t *)pram; + } else { + pinfo->smcp = (smc_t *)mem; + pinfo->smcup = (smc_uart_t *)pram; + } + pinfo->tx_nrfifos = pdata->tx_num_fifo; + pinfo->tx_fifosize = pdata->tx_buf_size; + + pinfo->rx_nrfifos = pdata->rx_num_fifo; + pinfo->rx_fifosize = pdata->rx_buf_size; + + pinfo->port.uartclk = pdata->uart_clk; + pinfo->port.mapbase = (unsigned long)mem; + pinfo->port.irq = platform_get_irq(pdev, 0); + + return 0; +} + #ifdef CONFIG_SERIAL_CPM_CONSOLE /* * Print a string to the serial port trying not to disturb @@ -1027,7 +1086,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, * If the buffer address is in the CPM DPRAM, don't * convert it. */ - cp = cpm2cpu_addr(bdp->cbd_bufaddr); + cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); *cp = *s; @@ -1044,7 +1103,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, while ((bdp->cbd_sc & BD_SC_READY) != 0) ; - cp = cpm2cpu_addr(bdp->cbd_bufaddr); + cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); *cp = 13; bdp->cbd_datlen = 1; @@ -1067,9 +1126,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, pinfo->tx_cur = (volatile cbd_t *) bdp; } -/* - * Setup console. Be careful is called early ! - */ + static int __init cpm_uart_console_setup(struct console *co, char *options) { struct uart_port *port; @@ -1080,9 +1137,27 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) int flow = 'n'; int ret; + struct fs_uart_platform_info *pdata; + struct platform_device* pdev = early_uart_get_pdev(co->index); + port = (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; pinfo = (struct uart_cpm_port *)port; + if (!pdev) { + pr_info("cpm_uart: console: compat mode\n"); + /* compatibility - will be cleaned up */ + cpm_uart_init_portdesc(); + + if (pinfo->set_lineif) + pinfo->set_lineif(pinfo); + } else { + pdata = pdev->dev.platform_data; + if (pdata) + if (pdata->init_ioports) + pdata->init_ioports(); + + cpm_uart_drv_get_platform_data(pdev, 1); + } pinfo->flags |= FLAG_CONSOLE; @@ -1097,14 +1172,6 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) baud = 9600; } - /* - * Setup any port IO, connect any baud rate generators, - * etc. This is expected to be handled by board - * dependant code - */ - if (pinfo->set_lineif) - pinfo->set_lineif(pinfo); - if (IS_SMC(pinfo)) { pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); @@ -1143,11 +1210,8 @@ static struct console cpm_scc_uart_console = { int __init cpm_uart_console_init(void) { - int ret = cpm_uart_init_portdesc(); - - if (!ret) - register_console(&cpm_scc_uart_console); - return ret; + register_console(&cpm_scc_uart_console); + return 0; } console_initcall(cpm_uart_console_init); @@ -1165,44 +1229,130 @@ static struct uart_driver cpm_reg = { .minor = SERIAL_CPM_MINOR, .cons = CPM_UART_CONSOLE, }; - -static int __init cpm_uart_init(void) +static int cpm_uart_drv_probe(struct device *dev) { - int ret, i; - - printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n"); + struct platform_device *pdev = to_platform_device(dev); + struct fs_uart_platform_info *pdata; + int ret = -ENODEV; -#ifndef CONFIG_SERIAL_CPM_CONSOLE - ret = cpm_uart_init_portdesc(); - if (ret) + if(!pdev) { + printk(KERN_ERR"CPM UART: platform data missing!\n"); return ret; -#endif + } - cpm_reg.nr = cpm_uart_nr; - ret = uart_register_driver(&cpm_reg); + pdata = pdev->dev.platform_data; + pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", + cpm_uart_port_map[pdata->fs_no]); - if (ret) + if ((ret = cpm_uart_drv_get_platform_data(pdev, 0))) return ret; - for (i = 0; i < cpm_uart_nr; i++) { - int con = cpm_uart_port_map[i]; - cpm_uart_ports[con].port.line = i; - cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF; - uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port); - } + if (pdata->init_ioports) + pdata->init_ioports(); - return ret; + ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port); + + return ret; } -static void __exit cpm_uart_exit(void) +static int cpm_uart_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct fs_uart_platform_info *pdata = pdev->dev.platform_data; + + pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n", + cpm_uart_port_map[pdata->fs_no]); + + uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port); + return 0; +} + +static struct device_driver cpm_smc_uart_driver = { + .name = "fsl-cpm-smc:uart", + .bus = &platform_bus_type, + .probe = cpm_uart_drv_probe, + .remove = cpm_uart_drv_remove, +}; + +static struct device_driver cpm_scc_uart_driver = { + .name = "fsl-cpm-scc:uart", + .bus = &platform_bus_type, + .probe = cpm_uart_drv_probe, + .remove = cpm_uart_drv_remove, +}; + +/* + This is supposed to match uart devices on platform bus, + */ +static int match_is_uart (struct device* dev, void* data) { + struct platform_device* pdev = container_of(dev, struct platform_device, dev); + int ret = 0; + /* this was setfunc as uart */ + if(strstr(pdev->name,":uart")) { + ret = 1; + } + return ret; +} + + +static int cpm_uart_init(void) { + + int ret; int i; + struct device *dev; + printk(KERN_INFO "Serial: CPM driver $Revision: 0.02 $\n"); + + /* lookup the bus for uart devices */ + dev = bus_find_device(&platform_bus_type, NULL, 0, match_is_uart); + + /* There are devices on the bus - all should be OK */ + if (dev) { + cpm_uart_count(); + cpm_reg.nr = cpm_uart_nr; + + if (!(ret = uart_register_driver(&cpm_reg))) { + if ((ret = driver_register(&cpm_smc_uart_driver))) { + uart_unregister_driver(&cpm_reg); + return ret; + } + if ((ret = driver_register(&cpm_scc_uart_driver))) { + driver_unregister(&cpm_scc_uart_driver); + uart_unregister_driver(&cpm_reg); + } + } + } else { + /* No capable platform devices found - falling back to legacy mode */ + pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n"); + pr_info( + "cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n"); +#ifndef CONFIG_SERIAL_CPM_CONSOLE + ret = cpm_uart_init_portdesc(); + if (ret) + return ret; +#endif + + cpm_reg.nr = cpm_uart_nr; + ret = uart_register_driver(&cpm_reg); + + if (ret) + return ret; + + for (i = 0; i < cpm_uart_nr; i++) { + int con = cpm_uart_port_map[i]; + cpm_uart_ports[con].port.line = i; + cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF; + uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port); + } - for (i = 0; i < cpm_uart_nr; i++) { - int con = cpm_uart_port_map[i]; - uart_remove_one_port(&cpm_reg, &cpm_uart_ports[con].port); } + return ret; +} +static void __exit cpm_uart_exit(void) +{ + driver_unregister(&cpm_scc_uart_driver); + driver_unregister(&cpm_smc_uart_driver); uart_unregister_driver(&cpm_reg); } diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index d789ee5..a5a3062 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c @@ -81,58 +81,11 @@ void cpm_line_cr_cmd(int line, int cmd) void smc1_lineif(struct uart_cpm_port *pinfo) { - volatile cpm8xx_t *cp = cpmp; - - (void)cp; /* fix warning */ -#if defined (CONFIG_MPC885ADS) - /* Enable SMC1 transceivers */ - { - cp->cp_pepar |= 0x000000c0; - cp->cp_pedir &= ~0x000000c0; - cp->cp_peso &= ~0x00000040; - cp->cp_peso |= 0x00000080; - } -#elif defined (CONFIG_MPC86XADS) - unsigned int iobits = 0x000000c0; - - if (!pinfo->is_portb) { - cp->cp_pbpar |= iobits; - cp->cp_pbdir &= ~iobits; - cp->cp_pbodr &= ~iobits; - } else { - ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits; - ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; - ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; - } -#endif pinfo->brg = 1; } void smc2_lineif(struct uart_cpm_port *pinfo) { - volatile cpm8xx_t *cp = cpmp; - - (void)cp; /* fix warning */ -#if defined (CONFIG_MPC885ADS) - cp->cp_pepar |= 0x00000c00; - cp->cp_pedir &= ~0x00000c00; - cp->cp_peso &= ~0x00000400; - cp->cp_peso |= 0x00000800; -#elif defined (CONFIG_MPC86XADS) - unsigned int iobits = 0x00000c00; - - if (!pinfo->is_portb) { - cp->cp_pbpar |= iobits; - cp->cp_pbdir &= ~iobits; - cp->cp_pbodr &= ~iobits; - } else { - ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits; - ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; - ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; - } - -#endif - pinfo->brg = 2; } @@ -191,7 +144,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) /* was hostalloc but changed cause it blows away the */ /* large tlb mapping when pinning the kernel area */ mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); - dma_addr = 0; + dma_addr = (u32)mem_addr; } else mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, GFP_KERNEL); @@ -204,8 +157,9 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) } pinfo->dp_addr = dp_offset; - pinfo->mem_addr = mem_addr; - pinfo->dma_addr = dma_addr; + pinfo->mem_addr = mem_addr; /* virtual address*/ + pinfo->dma_addr = dma_addr; /* physical address*/ + pinfo->mem_size = memsz; pinfo->rx_buf = mem_addr; pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index fd9e53e..7c6b07a 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c @@ -142,14 +142,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo) * be supported in a sane fashion. */ #ifndef CONFIG_STX_GP3 -#ifdef CONFIG_MPC8560_ADS - volatile iop_cpm2_t *io = &cpm2_immr->im_ioport; - io->iop_ppard |= 0x00000018; - io->iop_psord &= ~0x00000008; /* Rx */ - io->iop_psord &= ~0x00000010; /* Tx */ - io->iop_pdird &= ~0x00000008; /* Rx */ - io->iop_pdird |= 0x00000010; /* Tx */ -#else volatile iop_cpm2_t *io = &cpm2_immr->im_ioport; io->iop_pparb |= 0x008b0000; io->iop_pdirb |= 0x00880000; @@ -157,7 +149,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo) io->iop_pdirb &= ~0x00030000; io->iop_psorb &= ~0x00030000; #endif -#endif cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff; cpm2_immr->im_cpmux.cmx_scr |= 0x00090000; pinfo->brg = 2; @@ -218,8 +209,10 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); - if (is_con) + if (is_con) { mem_addr = alloc_bootmem(memsz); + dma_addr = mem_addr; + } else mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr, GFP_KERNEL); @@ -234,6 +227,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) pinfo->dp_addr = dp_offset; pinfo->mem_addr = mem_addr; pinfo->dma_addr = dma_addr; + pinfo->mem_size = memsz; pinfo->rx_buf = mem_addr; pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index b367de3..600d3e0 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1920,1925 +1920,3 @@ module_exit(au1200fb_cleanup); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -/* - * BRIEF MODULE DESCRIPTION - * Au1200 LCD Driver. - * - * Copyright 2004-2005 AMD - * Author: AMD - * - * Based on: - * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device - * Created 28 Dec 1997 by Geert Uytterhoeven - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/ctype.h> -#include <linux/dma-mapping.h> - -#include <asm/mach-au1x00/au1000.h> -#include "au1200fb.h" - -#ifdef CONFIG_PM -#include <asm/mach-au1x00/au1xxx_pm.h> -#endif - -#ifndef CONFIG_FB_AU1200_DEVS -#define CONFIG_FB_AU1200_DEVS 4 -#endif - -#define DRIVER_NAME "au1200fb" -#define DRIVER_DESC "LCD controller driver for AU1200 processors" - -#define DEBUG 1 - -#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) -#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) -#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) - -#if DEBUG -#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg) -#else -#define print_dbg(f, arg...) do {} while (0) -#endif - - -#define AU1200_LCD_FB_IOCTL 0x46FF - -#define AU1200_LCD_SET_SCREEN 1 -#define AU1200_LCD_GET_SCREEN 2 -#define AU1200_LCD_SET_WINDOW 3 -#define AU1200_LCD_GET_WINDOW 4 -#define AU1200_LCD_SET_PANEL 5 -#define AU1200_LCD_GET_PANEL 6 - -#define SCREEN_SIZE (1<< 1) -#define SCREEN_BACKCOLOR (1<< 2) -#define SCREEN_BRIGHTNESS (1<< 3) -#define SCREEN_COLORKEY (1<< 4) -#define SCREEN_MASK (1<< 5) - -struct au1200_lcd_global_regs_t { - unsigned int flags; - unsigned int xsize; - unsigned int ysize; - unsigned int backcolor; - unsigned int brightness; - unsigned int colorkey; - unsigned int mask; - unsigned int panel_choice; - char panel_desc[80]; - -}; - -#define WIN_POSITION (1<< 0) -#define WIN_ALPHA_COLOR (1<< 1) -#define WIN_ALPHA_MODE (1<< 2) -#define WIN_PRIORITY (1<< 3) -#define WIN_CHANNEL (1<< 4) -#define WIN_BUFFER_FORMAT (1<< 5) -#define WIN_COLOR_ORDER (1<< 6) -#define WIN_PIXEL_ORDER (1<< 7) -#define WIN_SIZE (1<< 8) -#define WIN_COLORKEY_MODE (1<< 9) -#define WIN_DOUBLE_BUFFER_MODE (1<< 10) -#define WIN_RAM_ARRAY_MODE (1<< 11) -#define WIN_BUFFER_SCALE (1<< 12) -#define WIN_ENABLE (1<< 13) - -struct au1200_lcd_window_regs_t { - unsigned int flags; - unsigned int xpos; - unsigned int ypos; - unsigned int alpha_color; - unsigned int alpha_mode; - unsigned int priority; - unsigned int channel; - unsigned int buffer_format; - unsigned int color_order; - unsigned int pixel_order; - unsigned int xsize; - unsigned int ysize; - unsigned int colorkey_mode; - unsigned int double_buffer_mode; - unsigned int ram_array_mode; - unsigned int xscale; - unsigned int yscale; - unsigned int enable; -}; - - -struct au1200_lcd_iodata_t { - unsigned int subcmd; - struct au1200_lcd_global_regs_t global; - struct au1200_lcd_window_regs_t window; -}; - -#if defined(__BIG_ENDIAN) -#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 -#else -#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 -#endif -#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 - -/* Private, per-framebuffer management information (independent of the panel itself) */ -struct au1200fb_device { - struct fb_info fb_info; /* FB driver info record */ - - int plane; - unsigned char* fb_mem; /* FrameBuffer memory map */ - unsigned int fb_len; - dma_addr_t fb_phys; -}; - -static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; -/********************************************************************/ - -/* LCD controller restrictions */ -#define AU1200_LCD_MAX_XRES 1280 -#define AU1200_LCD_MAX_YRES 1024 -#define AU1200_LCD_MAX_BPP 32 -#define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */ -#define AU1200_LCD_NBR_PALETTE_ENTRIES 256 - -/* Default number of visible screen buffer to allocate */ -#define AU1200FB_NBR_VIDEO_BUFFERS 1 - -/********************************************************************/ - -static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; -static int window_index = 2; /* default is zero */ -static int panel_index = 2; /* default is zero */ -static struct window_settings *win; -static struct panel_settings *panel; -static int noblanking = 1; -static int nohwcursor = 0; - -struct window_settings { - unsigned char name[64]; - uint32 mode_backcolor; - uint32 mode_colorkey; - uint32 mode_colorkeymsk; - struct { - int xres; - int yres; - int xpos; - int ypos; - uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */ - uint32 mode_winenable; - } w[4]; -}; - -#if defined(__BIG_ENDIAN) -#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00 -#else -#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01 -#endif - -extern int board_au1200fb_panel_init (void); -extern int board_au1200fb_panel_shutdown (void); - -#ifdef CONFIG_PM -int au1200fb_pm_callback(au1xxx_power_dev_t *dev, - au1xxx_request_t request, void *data); -au1xxx_power_dev_t *LCD_pm_dev; -#endif - -/* - * Default window configurations - */ -static struct window_settings windows[] = { - { /* Index 0 */ - "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", - /* mode_backcolor */ 0x006600ff, - /* mode_colorkey,msk*/ 0, 0, - { - { - /* xres, yres, xpos, ypos */ 0, 0, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | - LCD_WINCTRL1_PO_16BPP, - /* mode_winenable*/ LCD_WINENABLE_WEN0, - }, - { - /* xres, yres, xpos, ypos */ 100, 100, 100, 100, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | - LCD_WINCTRL1_PO_16BPP | - LCD_WINCTRL1_PIPE, - /* mode_winenable*/ LCD_WINENABLE_WEN1, - }, - { - /* xres, yres, xpos, ypos */ 0, 0, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | - LCD_WINCTRL1_PO_16BPP, - /* mode_winenable*/ 0, - }, - { - /* xres, yres, xpos, ypos */ 0, 0, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | - LCD_WINCTRL1_PO_16BPP | - LCD_WINCTRL1_PIPE, - /* mode_winenable*/ 0, - }, - }, - }, - - { /* Index 1 */ - "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", - /* mode_backcolor */ 0x006600ff, - /* mode_colorkey,msk*/ 0, 0, - { - { - /* xres, yres, xpos, ypos */ 320, 240, 5, 5, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP | - LCD_WINCTRL1_PO_00, - /* mode_winenable*/ LCD_WINENABLE_WEN0, - }, - { - /* xres, yres, xpos, ypos */ 0, 0, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 - | LCD_WINCTRL1_PO_16BPP, - /* mode_winenable*/ 0, - }, - { - /* xres, yres, xpos, ypos */ 100, 100, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | - LCD_WINCTRL1_PO_16BPP | - LCD_WINCTRL1_PIPE, - /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, - }, - { - /* xres, yres, xpos, ypos */ 200, 25, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | - LCD_WINCTRL1_PO_16BPP | - LCD_WINCTRL1_PIPE, - /* mode_winenable*/ 0, - }, - }, - }, - { /* Index 2 */ - "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", - /* mode_backcolor */ 0x006600ff, - /* mode_colorkey,msk*/ 0, 0, - { - { - /* xres, yres, xpos, ypos */ 0, 0, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | - LCD_WINCTRL1_PO_16BPP, - /* mode_winenable*/ LCD_WINENABLE_WEN0, - }, - { - /* xres, yres, xpos, ypos */ 0, 0, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | - LCD_WINCTRL1_PO_16BPP, - /* mode_winenable*/ 0, - }, - { - /* xres, yres, xpos, ypos */ 0, 0, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP | - LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE, - /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, - }, - { - /* xres, yres, xpos, ypos */ 0, 0, 0, 0, - /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | - LCD_WINCTRL1_PO_16BPP | - LCD_WINCTRL1_PIPE, - /* mode_winenable*/ 0, - }, - }, - }, - /* Need VGA 640 @ 24bpp, @ 32bpp */ - /* Need VGA 800 @ 24bpp, @ 32bpp */ - /* Need VGA 1024 @ 24bpp, @ 32bpp */ -}; - -/* - * Controller configurations for various panels. - */ - -struct panel_settings -{ - const char name[25]; /* Full name <vendor>_<model> */ - - struct fb_monspecs monspecs; /* FB monitor specs */ - - /* panel timings */ - uint32 mode_screen; - uint32 mode_horztiming; - uint32 mode_verttiming; - uint32 mode_clkcontrol; - uint32 mode_pwmdiv; - uint32 mode_pwmhi; - uint32 mode_outmask; - uint32 mode_fifoctrl; - uint32 mode_toyclksrc; - uint32 mode_backlight; - uint32 mode_auxpll; - int (*device_init)(void); - int (*device_shutdown)(void); -#define Xres min_xres -#define Yres min_yres - u32 min_xres; /* Minimum horizontal resolution */ - u32 max_xres; /* Maximum horizontal resolution */ - u32 min_yres; /* Minimum vertical resolution */ - u32 max_yres; /* Maximum vertical resolution */ -}; - -/********************************************************************/ -/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */ - -/* List of panels known to work with the AU1200 LCD controller. - * To add a new panel, enter the same specifications as the - * Generic_TFT one, and MAKE SURE that it doesn't conflicts - * with the controller restrictions. Restrictions are: - * - * STN color panels: max_bpp <= 12 - * STN mono panels: max_bpp <= 4 - * TFT panels: max_bpp <= 16 - * max_xres <= 800 - * max_yres <= 600 - */ -static struct panel_settings known_lcd_panels[] = -{ - [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */ - .name = "QVGA_320x240", - .monspecs = { - .modedb = NULL, - .modedb_len = 0, - .hfmin = 30000, - .hfmax = 70000, - .vfmin = 60, - .vfmax = 60, - .dclkmin = 6000000, - .dclkmax = 28000000, - .input = FB_DISP_RGB, - }, - .mode_screen = LCD_SCREEN_SX_N(320) | - LCD_SCREEN_SY_N(240), - .mode_horztiming = 0x00c4623b, - .mode_verttiming = 0x00502814, - .mode_clkcontrol = 0x00020002, /* /4=24Mhz */ - .mode_pwmdiv = 0x00000000, - .mode_pwmhi = 0x00000000, - .mode_outmask = 0x00FFFFFF, - .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ - .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ - .device_init = NULL, - .device_shutdown = NULL, - 320, 320, - 240, 240, - }, - - [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */ - .name = "VGA_640x480", - .monspecs = { - .modedb = NULL, - .modedb_len = 0, - .hfmin = 30000, - .hfmax = 70000, - .vfmin = 60, - .vfmax = 60, - .dclkmin = 6000000, - .dclkmax = 28000000, - .input = FB_DISP_RGB, - }, - .mode_screen = 0x13f9df80, - .mode_horztiming = 0x003c5859, - .mode_verttiming = 0x00741201, - .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ - .mode_pwmdiv = 0x00000000, - .mode_pwmhi = 0x00000000, - .mode_outmask = 0x00FFFFFF, - .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ - .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ - .device_init = NULL, - .device_shutdown = NULL, - 640, 480, - 640, 480, - }, - - [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */ - .name = "SVGA_800x600", - .monspecs = { - .modedb = NULL, - .modedb_len = 0, - .hfmin = 30000, - .hfmax = 70000, - .vfmin = 60, - .vfmax = 60, - .dclkmin = 6000000, - .dclkmax = 28000000, - .input = FB_DISP_RGB, - }, - .mode_screen = 0x18fa5780, - .mode_horztiming = 0x00dc7e77, - .mode_verttiming = 0x00584805, - .mode_clkcontrol = 0x00020000, /* /2=48Mhz */ - .mode_pwmdiv = 0x00000000, - .mode_pwmhi = 0x00000000, - .mode_outmask = 0x00FFFFFF, - .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ - .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ - .device_init = NULL, - .device_shutdown = NULL, - 800, 800, - 600, 600, - }, - - [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */ - .name = "XVGA_1024x768", - .monspecs = { - .modedb = NULL, - .modedb_len = 0, - .hfmin = 30000, - .hfmax = 70000, - .vfmin = 60, - .vfmax = 60, - .dclkmin = 6000000, - .dclkmax = 28000000, - .input = FB_DISP_RGB, - }, - .mode_screen = 0x1ffaff80, - .mode_horztiming = 0x007d0e57, - .mode_verttiming = 0x00740a01, - .mode_clkcontrol = 0x000A0000, /* /1 */ - .mode_pwmdiv = 0x00000000, - .mode_pwmhi = 0x00000000, - .mode_outmask = 0x00FFFFFF, - .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ - .mode_backlight = 0x00000000, - .mode_auxpll = 6, /* 72MHz AUXPLL */ - .device_init = NULL, - .device_shutdown = NULL, - 1024, 1024, - 768, 768, - }, - - [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */ - .name = "XVGA_1280x1024", - .monspecs = { - .modedb = NULL, - .modedb_len = 0, - .hfmin = 30000, - .hfmax = 70000, - .vfmin = 60, - .vfmax = 60, - .dclkmin = 6000000, - .dclkmax = 28000000, - .input = FB_DISP_RGB, - }, - .mode_screen = 0x27fbff80, - .mode_horztiming = 0x00cdb2c7, - .mode_verttiming = 0x00600002, - .mode_clkcontrol = 0x000A0000, /* /1 */ - .mode_pwmdiv = 0x00000000, - .mode_pwmhi = 0x00000000, - .mode_outmask = 0x00FFFFFF, - .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ - .mode_backlight = 0x00000000, - .mode_auxpll = 10, /* 120MHz AUXPLL */ - .device_init = NULL, - .device_shutdown = NULL, - 1280, 1280, - 1024, 1024, - }, - - [5] = { /* Samsung 1024x768 TFT */ - .name = "Samsung_1024x768_TFT", - .monspecs = { - .modedb = NULL, - .modedb_len = 0, - .hfmin = 30000, - .hfmax = 70000, - .vfmin = 60, - .vfmax = 60, - .dclkmin = 6000000, - .dclkmax = 28000000, - .input = FB_DISP_RGB, - }, - .mode_screen = 0x1ffaff80, - .mode_horztiming = 0x018cc677, - .mode_verttiming = 0x00241217, - .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */ - .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */ - .mode_pwmhi = 0x03400000, /* SCB 0x0 */ - .mode_outmask = 0x00FFFFFF, - .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ - .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ - .device_init = board_au1200fb_panel_init, - .device_shutdown = board_au1200fb_panel_shutdown, - 1024, 1024, - 768, 768, - }, - - [6] = { /* Toshiba 640x480 TFT */ - .name = "Toshiba_640x480_TFT", - .monspecs = { - .modedb = NULL, - .modedb_len = 0, - .hfmin = 30000, - .hfmax = 70000, - .vfmin = 60, - .vfmax = 60, - .dclkmin = 6000000, - .dclkmax = 28000000, - .input = FB_DISP_RGB, - }, - .mode_screen = LCD_SCREEN_SX_N(640) | - LCD_SCREEN_SY_N(480), - .mode_horztiming = LCD_HORZTIMING_HPW_N(96) | - LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51), - .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | - LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32), - .mode_clkcontrol = 0x00000000, /* /4=24Mhz */ - .mode_pwmdiv = 0x8000063f, - .mode_pwmhi = 0x03400000, - .mode_outmask = 0x00fcfcfc, - .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ - .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ - .device_init = board_au1200fb_panel_init, - .device_shutdown = board_au1200fb_panel_shutdown, - 640, 480, - 640, 480, - }, - - [7] = { /* Sharp 320x240 TFT */ - .name = "Sharp_320x240_TFT", - .monspecs = { - .modedb = NULL, - .modedb_len = 0, - .hfmin = 12500, - .hfmax = 20000, - .vfmin = 38, - .vfmax = 81, - .dclkmin = 4500000, - .dclkmax = 6800000, - .input = FB_DISP_RGB, - }, - .mode_screen = LCD_SCREEN_SX_N(320) | - LCD_SCREEN_SY_N(240), - .mode_horztiming = LCD_HORZTIMING_HPW_N(60) | - LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2), - .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | - LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5), - .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/ - .mode_pwmdiv = 0x8000063f, - .mode_pwmhi = 0x03400000, - .mode_outmask = 0x00fcfcfc, - .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ - .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ - .device_init = board_au1200fb_panel_init, - .device_shutdown = board_au1200fb_panel_shutdown, - 320, 320, - 240, 240, - }, - - [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */ - .name = "Toppoly_TD070WGCB2", - .monspecs = { - .modedb = NULL, - .modedb_len = 0, - .hfmin = 30000, - .hfmax = 70000, - .vfmin = 60, - .vfmax = 60, - .dclkmin = 6000000, - .dclkmax = 28000000, - .input = FB_DISP_RGB, - }, - .mode_screen = LCD_SCREEN_SX_N(856) | - LCD_SCREEN_SY_N(480), - .mode_horztiming = LCD_HORZTIMING_HND2_N(43) | - LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114), - .mode_verttiming = LCD_VERTTIMING_VND2_N(20) | - LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4), - .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ - .mode_pwmdiv = 0x8000063f, - .mode_pwmhi = 0x03400000, - .mode_outmask = 0x00fcfcfc, - .mode_fifoctrl = 0x2f2f2f2f, - .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ - .mode_backlight = 0x00000000, - .mode_auxpll = 8, /* 96MHz AUXPLL */ - .device_init = board_au1200fb_panel_init, - .device_shutdown = board_au1200fb_panel_shutdown, - 856, 856, - 480, 480, - }, -}; - -#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels)) - -/********************************************************************/ - -#ifdef CONFIG_PM -static int set_brightness(unsigned int brightness) -{ - unsigned int hi1, divider; - - /* limit brightness pwm duty to >= 30/1600 */ - if (brightness < 30) { - brightness = 30; - } - divider = (lcd->pwmdiv & 0x3FFFF) + 1; - hi1 = (lcd->pwmhi >> 16) + 1; - hi1 = (((brightness & 0xFF) + 1) * divider >> 8); - lcd->pwmhi &= 0xFFFF; - lcd->pwmhi |= (hi1 << 16); - - return brightness; -} -#endif /* CONFIG_PM */ - -static int winbpp (unsigned int winctrl1) -{ - int bits = 0; - - /* how many bits are needed for each pixel format */ - switch (winctrl1 & LCD_WINCTRL1_FRM) { - case LCD_WINCTRL1_FRM_1BPP: - bits = 1; - break; - case LCD_WINCTRL1_FRM_2BPP: - bits = 2; - break; - case LCD_WINCTRL1_FRM_4BPP: - bits = 4; - break; - case LCD_WINCTRL1_FRM_8BPP: - bits = 8; - break; - case LCD_WINCTRL1_FRM_12BPP: - case LCD_WINCTRL1_FRM_16BPP655: - case LCD_WINCTRL1_FRM_16BPP565: - case LCD_WINCTRL1_FRM_16BPP556: - case LCD_WINCTRL1_FRM_16BPPI1555: - case LCD_WINCTRL1_FRM_16BPPI5551: - case LCD_WINCTRL1_FRM_16BPPA1555: - case LCD_WINCTRL1_FRM_16BPPA5551: - bits = 16; - break; - case LCD_WINCTRL1_FRM_24BPP: - case LCD_WINCTRL1_FRM_32BPP: - bits = 32; - break; - } - - return bits; -} - -static int fbinfo2index (struct fb_info *fb_info) -{ - int i; - - for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { - if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) - return i; - } - printk("au1200fb: ERROR: fbinfo2index failed!\n"); - return -1; -} - -static int au1200_setlocation (struct au1200fb_device *fbdev, int plane, - int xpos, int ypos) -{ - uint32 winctrl0, winctrl1, winenable, fb_offset = 0; - int xsz, ysz; - - /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */ - - winctrl0 = lcd->window[plane].winctrl0; - winctrl1 = lcd->window[plane].winctrl1; - winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN); - winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); - - /* Check for off-screen adjustments */ - xsz = win->w[plane].xres; - ysz = win->w[plane].yres; - if ((xpos + win->w[plane].xres) > panel->Xres) { - /* Off-screen to the right */ - xsz = panel->Xres - xpos; /* off by 1 ??? */ - /*printk("off screen right\n");*/ - } - - if ((ypos + win->w[plane].yres) > panel->Yres) { - /* Off-screen to the bottom */ - ysz = panel->Yres - ypos; /* off by 1 ??? */ - /*printk("off screen bottom\n");*/ - } - - if (xpos < 0) { - /* Off-screen to the left */ - xsz = win->w[plane].xres + xpos; - fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8); - xpos = 0; - /*printk("off screen left\n");*/ - } - - if (ypos < 0) { - /* Off-screen to the top */ - ysz = win->w[plane].yres + ypos; - /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */ - ypos = 0; - /*printk("off screen top\n");*/ - } - - /* record settings */ - win->w[plane].xpos = xpos; - win->w[plane].ypos = ypos; - - xsz -= 1; - ysz -= 1; - winctrl0 |= (xpos << 21); - winctrl0 |= (ypos << 10); - winctrl1 |= (xsz << 11); - winctrl1 |= (ysz << 0); - - /* Disable the window while making changes, then restore WINEN */ - winenable = lcd->winenable & (1 << plane); - au_sync(); - lcd->winenable &= ~(1 << plane); - lcd->window[plane].winctrl0 = winctrl0; - lcd->window[plane].winctrl1 = winctrl1; - lcd->window[plane].winbuf0 = - lcd->window[plane].winbuf1 = fbdev->fb_phys; - lcd->window[plane].winbufctrl = 0; /* select winbuf0 */ - lcd->winenable |= winenable; - au_sync(); - - return 0; -} - -static void au1200_setpanel (struct panel_settings *newpanel) -{ - /* - * Perform global setup/init of LCD controller - */ - uint32 winenable; - - /* Make sure all windows disabled */ - winenable = lcd->winenable; - lcd->winenable = 0; - au_sync(); - /* - * Ensure everything is disabled before reconfiguring - */ - if (lcd->screen & LCD_SCREEN_SEN) { - /* Wait for vertical sync period */ - lcd->intstatus = LCD_INT_SS; - while ((lcd->intstatus & LCD_INT_SS) == 0) { - au_sync(); - } - - lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/ - - do { - lcd->intstatus = lcd->intstatus; /*clear interrupts*/ - au_sync(); - /*wait for controller to shut down*/ - } while ((lcd->intstatus & LCD_INT_SD) == 0); - - /* Call shutdown of current panel (if up) */ - /* this must occur last, because if an external clock is driving - the controller, the clock cannot be turned off before first - shutting down the controller. - */ - if (panel->device_shutdown != NULL) - panel->device_shutdown(); - } - - /* Newpanel == NULL indicates a shutdown operation only */ - if (newpanel == NULL) - return; - - panel = newpanel; - - printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres); - - /* - * Setup clocking if internal LCD clock source (assumes sys_auxpll valid) - */ - if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) - { - uint32 sys_clksrc; - au_writel(panel->mode_auxpll, SYS_AUXPLL); - sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; - sys_clksrc |= panel->mode_toyclksrc; - au_writel(sys_clksrc, SYS_CLKSRC); - } - - /* - * Configure panel timings - */ - lcd->screen = panel->mode_screen; - lcd->horztiming = panel->mode_horztiming; - lcd->verttiming = panel->mode_verttiming; - lcd->clkcontrol = panel->mode_clkcontrol; - lcd->pwmdiv = panel->mode_pwmdiv; - lcd->pwmhi = panel->mode_pwmhi; - lcd->outmask = panel->mode_outmask; - lcd->fifoctrl = panel->mode_fifoctrl; - au_sync(); - - /* fixme: Check window settings to make sure still valid - * for new geometry */ -#if 0 - au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos); - au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos); - au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos); - au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos); -#endif - lcd->winenable = winenable; - - /* - * Re-enable screen now that it is configured - */ - lcd->screen |= LCD_SCREEN_SEN; - au_sync(); - - /* Call init of panel */ - if (panel->device_init != NULL) panel->device_init(); - - /* FIX!!!! not appropriate on panel change!!! Global setup/init */ - lcd->intenable = 0; - lcd->intstatus = ~0; - lcd->backcolor = win->mode_backcolor; - - /* Setup Color Key - FIX!!! */ - lcd->colorkey = win->mode_colorkey; - lcd->colorkeymsk = win->mode_colorkeymsk; - - /* Setup HWCursor - FIX!!! Need to support this eventually */ - lcd->hwc.cursorctrl = 0; - lcd->hwc.cursorpos = 0; - lcd->hwc.cursorcolor0 = 0; - lcd->hwc.cursorcolor1 = 0; - lcd->hwc.cursorcolor2 = 0; - lcd->hwc.cursorcolor3 = 0; - - -#if 0 -#define D(X) printk("%25s: %08X\n", #X, X) - D(lcd->screen); - D(lcd->horztiming); - D(lcd->verttiming); - D(lcd->clkcontrol); - D(lcd->pwmdiv); - D(lcd->pwmhi); - D(lcd->outmask); - D(lcd->fifoctrl); - D(lcd->window[0].winctrl0); - D(lcd->window[0].winctrl1); - D(lcd->window[0].winctrl2); - D(lcd->window[0].winbuf0); - D(lcd->window[0].winbuf1); - D(lcd->window[0].winbufctrl); - D(lcd->window[1].winctrl0); - D(lcd->window[1].winctrl1); - D(lcd->window[1].winctrl2); - D(lcd->window[1].winbuf0); - D(lcd->window[1].winbuf1); - D(lcd->window[1].winbufctrl); - D(lcd->window[2].winctrl0); - D(lcd->window[2].winctrl1); - D(lcd->window[2].winctrl2); - D(lcd->window[2].winbuf0); - D(lcd->window[2].winbuf1); - D(lcd->window[2].winbufctrl); - D(lcd->window[3].winctrl0); - D(lcd->window[3].winctrl1); - D(lcd->window[3].winctrl2); - D(lcd->window[3].winbuf0); - D(lcd->window[3].winbuf1); - D(lcd->window[3].winbufctrl); - D(lcd->winenable); - D(lcd->intenable); - D(lcd->intstatus); - D(lcd->backcolor); - D(lcd->winenable); - D(lcd->colorkey); - D(lcd->colorkeymsk); - D(lcd->hwc.cursorctrl); - D(lcd->hwc.cursorpos); - D(lcd->hwc.cursorcolor0); - D(lcd->hwc.cursorcolor1); - D(lcd->hwc.cursorcolor2); - D(lcd->hwc.cursorcolor3); -#endif -} - -static void au1200_setmode(struct au1200fb_device *fbdev) -{ - int plane = fbdev->plane; - /* Window/plane setup */ - lcd->window[plane].winctrl1 = ( 0 - | LCD_WINCTRL1_PRI_N(plane) - | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */ - ) ; - - au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos); - - lcd->window[plane].winctrl2 = ( 0 - | LCD_WINCTRL2_CKMODE_00 - | LCD_WINCTRL2_DBM - | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) - | LCD_WINCTRL2_SCX_1 - | LCD_WINCTRL2_SCY_1 - ) ; - lcd->winenable |= win->w[plane].mode_winenable; - au_sync(); -} - - -/* Inline helpers */ - -/*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ -/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ - -#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN) - -/* Bitfields format supported by the controller. */ -static struct fb_bitfield rgb_bitfields[][4] = { - /* Red, Green, Blue, Transp */ - [LCD_WINCTRL1_FRM_16BPP655 >> 25] = - { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, - - [LCD_WINCTRL1_FRM_16BPP565 >> 25] = - { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, - - [LCD_WINCTRL1_FRM_16BPP556 >> 25] = - { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, - - [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] = - { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, - - [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] = - { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } }, - - [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] = - { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, - - [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] = - { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, - - [LCD_WINCTRL1_FRM_24BPP >> 25] = - { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } }, - - [LCD_WINCTRL1_FRM_32BPP >> 25] = - { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } }, -}; - -/*-------------------------------------------------------------------------*/ - -/* Helpers */ - -static void au1200fb_update_fbinfo(struct fb_info *fbi) -{ - /* FIX!!!! This also needs to take the window pixel format into account!!! */ - - /* Update var-dependent FB info */ - if (panel_is_color(panel)) { - if (fbi->var.bits_per_pixel <= 8) { - /* palettized */ - fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR; - fbi->fix.line_length = fbi->var.xres_virtual / - (8/fbi->var.bits_per_pixel); - } else { - /* non-palettized */ - fbi->fix.visual = FB_VISUAL_TRUECOLOR; - fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8); - } - } else { - /* mono FIX!!! mono 8 and 4 bits */ - fbi->fix.visual = FB_VISUAL_MONO10; - fbi->fix.line_length = fbi->var.xres_virtual / 8; - } - - fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual; - print_dbg("line length: %d\n", fbi->fix.line_length); - print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel); -} - -/*-------------------------------------------------------------------------*/ - -/* AU1200 framebuffer driver */ - -/* fb_check_var - * Validate var settings with hardware restrictions and modify it if necessary - */ -static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *fbi) -{ - struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; - u32 pixclock; - int screen_size, plane; - - plane = fbdev->plane; - - /* Make sure that the mode respect all LCD controller and - * panel restrictions. */ - var->xres = win->w[plane].xres; - var->yres = win->w[plane].yres; - - /* No need for virtual resolution support */ - var->xres_virtual = var->xres; - var->yres_virtual = var->yres; - - var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1); - - screen_size = var->xres_virtual * var->yres_virtual; - if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8); - else screen_size /= (8/var->bits_per_pixel); - - if (fbdev->fb_len < screen_size) - return -EINVAL; /* Virtual screen is to big, abort */ - - /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */ - /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel - * clock can only be obtain by dividing this value by an even integer. - * Fallback to a slower pixel clock if necessary. */ - pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); - pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); - - if (AU1200_LCD_MAX_CLK % pixclock) { - int diff = AU1200_LCD_MAX_CLK % pixclock; - pixclock -= diff; - } - - var->pixclock = KHZ2PICOS(pixclock/1000); -#if 0 - if (!panel_is_active(panel)) { - int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1; - - if (!panel_is_color(panel) - && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) { - /* STN 8bit mono panel support is up to 6MHz pixclock */ - var->pixclock = KHZ2PICOS(6000); - } else if (!pcd) { - /* Other STN panel support is up to 12MHz */ - var->pixclock = KHZ2PICOS(12000); - } - } -#endif - /* Set bitfield accordingly */ - switch (var->bits_per_pixel) { - case 16: - { - /* 16bpp True color. - * These must be set to MATCH WINCTRL[FORM] */ - int idx; - idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; - var->red = rgb_bitfields[idx][0]; - var->green = rgb_bitfields[idx][1]; - var->blue = rgb_bitfields[idx][2]; - var->transp = rgb_bitfields[idx][3]; - break; - } - - case 32: - { - /* 32bpp True color. - * These must be set to MATCH WINCTRL[FORM] */ - int idx; - idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; - var->red = rgb_bitfields[idx][0]; - var->green = rgb_bitfields[idx][1]; - var->blue = rgb_bitfields[idx][2]; - var->transp = rgb_bitfields[idx][3]; - break; - } - default: - print_dbg("Unsupported depth %dbpp", var->bits_per_pixel); - return -EINVAL; - } - - return 0; -} - -/* fb_set_par - * Set hardware with var settings. This will enable the controller with a - * specific mode, normally validated with the fb_check_var method - */ -static int au1200fb_fb_set_par(struct fb_info *fbi) -{ - struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; - - au1200fb_update_fbinfo(fbi); - au1200_setmode(fbdev); - - return 0; -} - -/* fb_setcolreg - * Set color in LCD palette. - */ -static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, struct fb_info *fbi) -{ - volatile u32 *palette = lcd->palette; - u32 value; - - if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1)) - return -EINVAL; - - if (fbi->var.grayscale) { - /* Convert color to grayscale */ - red = green = blue = - (19595 * red + 38470 * green + 7471 * blue) >> 16; - } - - if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { - /* Place color in the pseudopalette */ - if (regno > 16) - return -EINVAL; - - palette = (u32*) fbi->pseudo_palette; - - red >>= (16 - fbi->var.red.length); - green >>= (16 - fbi->var.green.length); - blue >>= (16 - fbi->var.blue.length); - - value = (red << fbi->var.red.offset) | - (green << fbi->var.green.offset)| - (blue << fbi->var.blue.offset); - value &= 0xFFFF; - - } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) { - /* COLOR TFT PALLETTIZED (use RGB 565) */ - value = (red & 0xF800)|((green >> 5) & - 0x07E0)|((blue >> 11) & 0x001F); - value &= 0xFFFF; - - } else if (0 /*panel_is_color(fbdev->panel)*/) { - /* COLOR STN MODE */ - value = 0x1234; - value &= 0xFFF; - } else { - /* MONOCHROME MODE */ - value = (green >> 12) & 0x000F; - value &= 0xF; - } - - palette[regno] = value; - - return 0; -} - -/* fb_blank - * Blank the screen. Depending on the mode, the screen will be - * activated with the backlight color, or desactivated - */ -static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi) -{ - /* Short-circuit screen blanking */ - if (noblanking) - return 0; - - switch (blank_mode) { - - case FB_BLANK_UNBLANK: - case FB_BLANK_NORMAL: - /* printk("turn on panel\n"); */ - au1200_setpanel(panel); - break; - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - /* printk("turn off panel\n"); */ - au1200_setpanel(NULL); - break; - default: - break; - - } - - /* FB_BLANK_NORMAL is a soft blank */ - return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0; -} - -/* fb_mmap - * Map video memory in user space. We don't use the generic fb_mmap - * method mainly to allow the use of the TLB streaming flag (CCA=6) - */ -static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) - -{ - unsigned int len; - unsigned long start=0, off; - struct au1200fb_device *fbdev = (struct au1200fb_device *) info; - -#ifdef CONFIG_PM - au1xxx_pm_access(LCD_pm_dev); -#endif - - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { - return -EINVAL; - } - - start = fbdev->fb_phys & PAGE_MASK; - len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); - - off = vma->vm_pgoff << PAGE_SHIFT; - - if ((vma->vm_end - vma->vm_start + off) > len) { - return -EINVAL; - } - - off += start; - vma->vm_pgoff = off >> PAGE_SHIFT; - - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ - - vma->vm_flags |= VM_IO; - - return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - - return 0; -} - -static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) -{ - - unsigned int hi1, divider; - - /* SCREEN_SIZE: user cannot reset size, must switch panel choice */ - - if (pdata->flags & SCREEN_BACKCOLOR) - lcd->backcolor = pdata->backcolor; - - if (pdata->flags & SCREEN_BRIGHTNESS) { - - // limit brightness pwm duty to >= 30/1600 - if (pdata->brightness < 30) { - pdata->brightness = 30; - } - divider = (lcd->pwmdiv & 0x3FFFF) + 1; - hi1 = (lcd->pwmhi >> 16) + 1; - hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8); - lcd->pwmhi &= 0xFFFF; - lcd->pwmhi |= (hi1 << 16); - } - - if (pdata->flags & SCREEN_COLORKEY) - lcd->colorkey = pdata->colorkey; - - if (pdata->flags & SCREEN_MASK) - lcd->colorkeymsk = pdata->mask; - au_sync(); -} - -static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) -{ - unsigned int hi1, divider; - - pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1; - pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1; - - pdata->backcolor = lcd->backcolor; - pdata->colorkey = lcd->colorkey; - pdata->mask = lcd->colorkeymsk; - - // brightness - hi1 = (lcd->pwmhi >> 16) + 1; - divider = (lcd->pwmdiv & 0x3FFFF) + 1; - pdata->brightness = ((hi1 << 8) / divider) - 1; - au_sync(); -} - -static void set_window(unsigned int plane, - struct au1200_lcd_window_regs_t *pdata) -{ - unsigned int val, bpp; - - /* Window control register 0 */ - if (pdata->flags & WIN_POSITION) { - val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX | - LCD_WINCTRL0_OY); - val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX); - val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY); - lcd->window[plane].winctrl0 = val; - } - if (pdata->flags & WIN_ALPHA_COLOR) { - val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A); - val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A); - lcd->window[plane].winctrl0 = val; - } - if (pdata->flags & WIN_ALPHA_MODE) { - val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN); - val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN); - lcd->window[plane].winctrl0 = val; - } - - /* Window control register 1 */ - if (pdata->flags & WIN_PRIORITY) { - val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI); - val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI); - lcd->window[plane].winctrl1 = val; - } - if (pdata->flags & WIN_CHANNEL) { - val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE); - val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE); - lcd->window[plane].winctrl1 = val; - } - if (pdata->flags & WIN_BUFFER_FORMAT) { - val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM); - val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM); - lcd->window[plane].winctrl1 = val; - } - if (pdata->flags & WIN_COLOR_ORDER) { - val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO); - val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO); - lcd->window[plane].winctrl1 = val; - } - if (pdata->flags & WIN_PIXEL_ORDER) { - val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO); - val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO); - lcd->window[plane].winctrl1 = val; - } - if (pdata->flags & WIN_SIZE) { - val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX | - LCD_WINCTRL1_SZY); - val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX); - val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY); - lcd->window[plane].winctrl1 = val; - /* program buffer line width */ - bpp = winbpp(val) / 8; - val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX); - val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX); - lcd->window[plane].winctrl2 = val; - } - - /* Window control register 2 */ - if (pdata->flags & WIN_COLORKEY_MODE) { - val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE); - val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE); - lcd->window[plane].winctrl2 = val; - } - if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) { - val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM); - val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM); - lcd->window[plane].winctrl2 = val; - } - if (pdata->flags & WIN_RAM_ARRAY_MODE) { - val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM); - val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM); - lcd->window[plane].winctrl2 = val; - } - - /* Buffer line width programmed with WIN_SIZE */ - - if (pdata->flags & WIN_BUFFER_SCALE) { - val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX | - LCD_WINCTRL2_SCY); - val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX); - val |= ((pdata->ysize) & LCD_WINCTRL2_SCY); - lcd->window[plane].winctrl2 = val; - } - - if (pdata->flags & WIN_ENABLE) { - val = lcd->winenable; - val &= ~(1<<plane); - val |= (pdata->enable & 1) << plane; - lcd->winenable = val; - } - au_sync(); -} - -static void get_window(unsigned int plane, - struct au1200_lcd_window_regs_t *pdata) -{ - /* Window control register 0 */ - pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21; - pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10; - pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2; - pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1; - - /* Window control register 1 */ - pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30; - pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29; - pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25; - pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24; - pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22; - pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1; - pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1; - - /* Window control register 2 */ - pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24; - pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23; - pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21; - - pdata->enable = (lcd->winenable >> plane) & 1; - au_sync(); -} - -static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) -{ - int plane; - int val; - -#ifdef CONFIG_PM - au1xxx_pm_access(LCD_pm_dev); -#endif - - plane = fbinfo2index(info); - print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); - - if (cmd == AU1200_LCD_FB_IOCTL) { - struct au1200_lcd_iodata_t iodata; - - if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata))) - return -EFAULT; - - print_dbg("FB IOCTL called\n"); - - switch (iodata.subcmd) { - case AU1200_LCD_SET_SCREEN: - print_dbg("AU1200_LCD_SET_SCREEN\n"); - set_global(cmd, &iodata.global); - break; - - case AU1200_LCD_GET_SCREEN: - print_dbg("AU1200_LCD_GET_SCREEN\n"); - get_global(cmd, &iodata.global); - break; - - case AU1200_LCD_SET_WINDOW: - print_dbg("AU1200_LCD_SET_WINDOW\n"); - set_window(plane, &iodata.window); - break; - - case AU1200_LCD_GET_WINDOW: - print_dbg("AU1200_LCD_GET_WINDOW\n"); - get_window(plane, &iodata.window); - break; - - case AU1200_LCD_SET_PANEL: - print_dbg("AU1200_LCD_SET_PANEL\n"); - if ((iodata.global.panel_choice >= 0) && - (iodata.global.panel_choice < - NUM_PANELS)) - { - struct panel_settings *newpanel; - panel_index = iodata.global.panel_choice; - newpanel = &known_lcd_panels[panel_index]; - au1200_setpanel(newpanel); - } - break; - - case AU1200_LCD_GET_PANEL: - print_dbg("AU1200_LCD_GET_PANEL\n"); - iodata.global.panel_choice = panel_index; - break; - - default: - return -EINVAL; - } - - val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata)); - if (val) { - print_dbg("error: could not copy %d bytes\n", val); - return -EFAULT; - } - } - - return 0; -} - - -static struct fb_ops au1200fb_fb_ops = { - .owner = THIS_MODULE, - .fb_check_var = au1200fb_fb_check_var, - .fb_set_par = au1200fb_fb_set_par, - .fb_setcolreg = au1200fb_fb_setcolreg, - .fb_blank = au1200fb_fb_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_sync = NULL, - .fb_ioctl = au1200fb_ioctl, - .fb_mmap = au1200fb_fb_mmap, -}; - -/*-------------------------------------------------------------------------*/ - -static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs) -{ - /* Nothing to do for now, just clear any pending interrupt */ - lcd->intstatus = lcd->intstatus; - au_sync(); - - return IRQ_HANDLED; -} - -/*-------------------------------------------------------------------------*/ - -/* AU1200 LCD device probe helpers */ - -static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) -{ - struct fb_info *fbi = &fbdev->fb_info; - int bpp; - - memset(fbi, 0, sizeof(struct fb_info)); - fbi->fbops = &au1200fb_fb_ops; - - bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); - - /* Copy monitor specs from panel data */ - /* fixme: we're setting up LCD controller windows, so these dont give a - damn as to what the monitor specs are (the panel itself does, but that - isnt done here...so maybe need a generic catchall monitor setting??? */ - memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs)); - - /* We first try the user mode passed in argument. If that failed, - * or if no one has been specified, we default to the first mode of the - * panel list. Note that after this call, var data will be set */ - if (!fb_find_mode(&fbi->var, - fbi, - NULL, /* drv_info.opt_mode, */ - fbi->monspecs.modedb, - fbi->monspecs.modedb_len, - fbi->monspecs.modedb, - bpp)) { - - print_err("Cannot find valid mode for panel %s", panel->name); - return -EFAULT; - } - - fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); - if (!fbi->pseudo_palette) { - return -ENOMEM; - } - memset(fbi->pseudo_palette, 0, sizeof(u32) * 16); - - if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { - print_err("Fail to allocate colormap (%d entries)", - AU1200_LCD_NBR_PALETTE_ENTRIES); - kfree(fbi->pseudo_palette); - return -EFAULT; - } - - strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id)); - fbi->fix.smem_start = fbdev->fb_phys; - fbi->fix.smem_len = fbdev->fb_len; - fbi->fix.type = FB_TYPE_PACKED_PIXELS; - fbi->fix.xpanstep = 0; - fbi->fix.ypanstep = 0; - fbi->fix.mmio_start = 0; - fbi->fix.mmio_len = 0; - fbi->fix.accel = FB_ACCEL_NONE; - - fbi->screen_base = (char __iomem *) fbdev->fb_mem; - - au1200fb_update_fbinfo(fbi); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* AU1200 LCD controller device driver */ - -static int au1200fb_drv_probe(struct device *dev) -{ - struct au1200fb_device *fbdev; - unsigned long page; - int bpp, plane, ret; - - if (!dev) - return -EINVAL; - - for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { - bpp = winbpp(win->w[plane].mode_winctrl1); - if (win->w[plane].xres == 0) - win->w[plane].xres = panel->Xres; - if (win->w[plane].yres == 0) - win->w[plane].yres = panel->Yres; - - fbdev = &_au1200fb_devices[plane]; - memset(fbdev, 0, sizeof(struct au1200fb_device)); - fbdev->plane = plane; - - /* Allocate the framebuffer to the maximum screen size */ - fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; - - fbdev->fb_mem = dma_alloc_noncoherent(dev, - PAGE_ALIGN(fbdev->fb_len), - &fbdev->fb_phys, GFP_KERNEL); - if (!fbdev->fb_mem) { - print_err("fail to allocate frambuffer (size: %dK))", - fbdev->fb_len / 1024); - return -ENOMEM; - } - - /* - * Set page reserved so that mmap will work. This is necessary - * since we'll be remapping normal memory. - */ - for (page = (unsigned long)fbdev->fb_phys; - page < PAGE_ALIGN((unsigned long)fbdev->fb_phys + - fbdev->fb_len); - page += PAGE_SIZE) { - SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */ - } - print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); - print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); - - /* Init FB data */ - if ((ret = au1200fb_init_fbinfo(fbdev)) < 0) - goto failed; - - /* Register new framebuffer */ - if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { - print_err("cannot register new framebuffer"); - goto failed; - } - - au1200fb_fb_set_par(&fbdev->fb_info); - -#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) - if (plane == 0) - if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { - /* Start display and show logo on boot */ - fb_set_cmap(&fbdev->fb_info.cmap, - &fbdev->fb_info); - - fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); - } -#endif - } - - /* Now hook interrupt too */ - if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, - SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) { - print_err("fail to request interrupt line %d (err: %d)", - AU1200_LCD_INT, ret); - goto failed; - } - - return 0; - -failed: - /* NOTE: This only does the current plane/window that failed; others are still active */ - if (fbdev->fb_mem) - dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), - fbdev->fb_mem, fbdev->fb_phys); - if (fbdev->fb_info.cmap.len != 0) - fb_dealloc_cmap(&fbdev->fb_info.cmap); - if (fbdev->fb_info.pseudo_palette) - kfree(fbdev->fb_info.pseudo_palette); - if (plane == 0) - free_irq(AU1200_LCD_INT, (void*)dev); - return ret; -} - -static int au1200fb_drv_remove(struct device *dev) -{ - struct au1200fb_device *fbdev; - int plane; - - if (!dev) - return -ENODEV; - - /* Turn off the panel */ - au1200_setpanel(NULL); - - for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) - { - fbdev = &_au1200fb_devices[plane]; - - /* Clean up all probe data */ - unregister_framebuffer(&fbdev->fb_info); - if (fbdev->fb_mem) - dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), - fbdev->fb_mem, fbdev->fb_phys); - if (fbdev->fb_info.cmap.len != 0) - fb_dealloc_cmap(&fbdev->fb_info.cmap); - if (fbdev->fb_info.pseudo_palette) - kfree(fbdev->fb_info.pseudo_palette); - } - - free_irq(AU1200_LCD_INT, (void *)dev); - - return 0; -} - -#ifdef CONFIG_PM -static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level) -{ - /* TODO */ - return 0; -} - -static int au1200fb_drv_resume(struct device *dev, u32 level) -{ - /* TODO */ - return 0; -} -#endif /* CONFIG_PM */ - -static struct device_driver au1200fb_driver = { - .name = "au1200-lcd", - .bus = &platform_bus_type, - .probe = au1200fb_drv_probe, - .remove = au1200fb_drv_remove, -#ifdef CONFIG_PM - .suspend = au1200fb_drv_suspend, - .resume = au1200fb_drv_resume, -#endif -}; - -/*-------------------------------------------------------------------------*/ - -/* Kernel driver */ - -static void au1200fb_setup(void) -{ - char* options = NULL; - char* this_opt; - int num_panels = ARRAY_SIZE(known_lcd_panels); - int panel_idx = -1; - - fb_get_options(DRIVER_NAME, &options); - - if (options) { - while ((this_opt = strsep(&options,",")) != NULL) { - /* Panel option - can be panel name, - * "bs" for board-switch, or number/index */ - if (!strncmp(this_opt, "panel:", 6)) { - int i; - long int li; - char *endptr; - this_opt += 6; - /* First check for index, which allows - * to short circuit this mess */ - li = simple_strtol(this_opt, &endptr, 0); - if (*endptr == '\0') { - panel_idx = (int)li; - } - else if (strcmp(this_opt, "bs") == 0) { - extern int board_au1200fb_panel(void); - panel_idx = board_au1200fb_panel(); - } - - else - for (i = 0; i < num_panels; i++) { - if (!strcmp(this_opt, known_lcd_panels[i].name)) { - panel_idx = i; - break; - } - } - - if ((panel_idx < 0) || (panel_idx >= num_panels)) { - print_warn("Panel %s not supported!", this_opt); - } - else - panel_index = panel_idx; - } - - else if (strncmp(this_opt, "nohwcursor", 10) == 0) { - nohwcursor = 1; - } - - /* Unsupported option */ - else { - print_warn("Unsupported option \"%s\"", this_opt); - } - } - } -} - -#ifdef CONFIG_PM -static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, - au1xxx_request_t request, void *data) { - int retval = -1; - unsigned int d = 0; - unsigned int brightness = 0; - - if (request == AU1XXX_PM_SLEEP) { - board_au1200fb_panel_shutdown(); - } - else if (request == AU1XXX_PM_WAKEUP) { - if(dev->prev_state == SLEEP_STATE) - { - int plane; - au1200_setpanel(panel); - for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { - struct au1200fb_device *fbdev; - fbdev = &_au1200fb_devices[plane]; - au1200fb_fb_set_par(&fbdev->fb_info); - } - } - - d = *((unsigned int*)data); - if(d <=10) brightness = 26; - else if(d<=20) brightness = 51; - else if(d<=30) brightness = 77; - else if(d<=40) brightness = 102; - else if(d<=50) brightness = 128; - else if(d<=60) brightness = 153; - else if(d<=70) brightness = 179; - else if(d<=80) brightness = 204; - else if(d<=90) brightness = 230; - else brightness = 255; - set_brightness(brightness); - } else if (request == AU1XXX_PM_GETSTATUS) { - return dev->cur_state; - } else if (request == AU1XXX_PM_ACCESS) { - if (dev->cur_state != SLEEP_STATE) - return retval; - else { - au1200_setpanel(panel); - } - } else if (request == AU1XXX_PM_IDLE) { - } else if (request == AU1XXX_PM_CLEANUP) { - } - - return retval; -} -#endif - -static int __init au1200fb_init(void) -{ - print_info("" DRIVER_DESC ""); - - /* Setup driver with options */ - au1200fb_setup(); - - /* Point to the panel selected */ - panel = &known_lcd_panels[panel_index]; - win = &windows[window_index]; - - printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); - printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); - - /* Kickstart the panel, the framebuffers/windows come soon enough */ - au1200_setpanel(panel); - - #ifdef CONFIG_PM - LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); - if ( LCD_pm_dev == NULL) - printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); - else - printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); - #endif - - return driver_register(&au1200fb_driver); -} - -static void __exit au1200fb_cleanup(void) -{ - driver_unregister(&au1200fb_driver); -} - -module_init(au1200fb_init); -module_exit(au1200fb_cleanup); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); @@ -261,7 +261,7 @@ asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf) return error; } -#ifndef __ARCH_WANT_STAT64 +#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT) asmlinkage long sys_newfstatat(int dfd, char __user *filename, struct stat __user *statbuf, int flag) { diff --git a/include/asm-i386/i387.h b/include/asm-i386/i387.h index 7b1f011..bc1d6ed 100644 --- a/include/asm-i386/i387.h +++ b/include/asm-i386/i387.h @@ -58,13 +58,13 @@ static inline void __save_init_fpu( struct task_struct *tsk ) alternative_input( "fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4, "fxsave %[fx]\n" - "bt $7,%[fsw] ; jc 1f ; fnclex\n1:", + "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:", X86_FEATURE_FXSR, [fx] "m" (tsk->thread.i387.fxsave), [fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory"); /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is pending. Clear the x87 state here by setting it to fixed - values. __per_cpu_offset[0] is a random variable that should be in L1 */ + values. safe_address is a random variable that should be in L1 */ alternative_input( GENERIC_NOP8 GENERIC_NOP2, "emms\n\t" /* clear stack tags */ diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 4321483..9fcf016 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -22,6 +22,7 @@ #define PPC_FEATURE_BOOKE 0x00008000 #define PPC_FEATURE_SMT 0x00004000 #define PPC_FEATURE_ICACHE_SNOOP 0x00002000 +#define PPC_FEATURE_ARCH_2_05 0x00001000 #ifdef __KERNEL__ #ifndef __ASSEMBLY__ @@ -320,6 +321,11 @@ extern void do_cpu_ftr_fixups(unsigned long offset); CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR) +#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ + CPU_FTR_MMCRA | CPU_FTR_SMT | \ + CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ + CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE) #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ @@ -331,8 +337,8 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #ifdef __powerpc64__ #define CPU_FTRS_POSSIBLE \ (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \ - CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL | \ - CPU_FTR_CI_LARGE_PAGE) + CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \ + CPU_FTRS_CELL | CPU_FTR_CI_LARGE_PAGE) #else enum { CPU_FTRS_POSSIBLE = @@ -376,8 +382,8 @@ enum { #ifdef __powerpc64__ #define CPU_FTRS_ALWAYS \ (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \ - CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL & \ - CPU_FTRS_POSSIBLE) + CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 & \ + CPU_FTRS_CELL & CPU_FTRS_POSSIBLE) #else enum { CPU_FTRS_ALWAYS = diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index 68efbea..f1c2469 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -9,6 +9,9 @@ * 2 of the License, or (at your option) any later version. */ +/* Check of existence of legacy devices */ +extern int check_legacy_ioport(unsigned long base_port); + #ifndef CONFIG_PPC64 #include <asm-ppc/io.h> #else @@ -437,9 +440,6 @@ out: #define dma_cache_wback(_start,_size) do { } while (0) #define dma_cache_wback_inv(_start,_size) do { } while (0) -/* Check of existence of legacy devices */ -extern int check_legacy_ioport(unsigned long base_port); - /* * Convert a physical pointer to a virtual kernel pointer for /dev/mem diff --git a/include/asm-powerpc/page_64.h b/include/asm-powerpc/page_64.h index 3fb061b..eab779c 100644 --- a/include/asm-powerpc/page_64.h +++ b/include/asm-powerpc/page_64.h @@ -101,6 +101,7 @@ extern unsigned int HPAGE_SHIFT; - (1U << GET_HTLB_AREA(addr))) & 0xffff) #define ARCH_HAS_HUGEPAGE_ONLY_RANGE +#define ARCH_HAS_HUGETLB_FREE_PGD_RANGE #define ARCH_HAS_PREPARE_HUGEPAGE_RANGE #define ARCH_HAS_SETCLEAR_HUGE_PTE diff --git a/include/asm-powerpc/pgalloc.h b/include/asm-powerpc/pgalloc.h index a00ee00..9f0917c 100644 --- a/include/asm-powerpc/pgalloc.h +++ b/include/asm-powerpc/pgalloc.h @@ -17,11 +17,13 @@ extern kmem_cache_t *pgtable_cache[]; #define PTE_CACHE_NUM 0 #define PMD_CACHE_NUM 1 #define PGD_CACHE_NUM 2 +#define HUGEPTE_CACHE_NUM 3 #else #define PTE_CACHE_NUM 0 #define PMD_CACHE_NUM 1 #define PUD_CACHE_NUM 1 #define PGD_CACHE_NUM 0 +#define HUGEPTE_CACHE_NUM 2 #endif /* diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 34325e2..908acb4 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -304,8 +304,25 @@ #define __NR_splice 283 #define __NR_tee 284 #define __NR_vmsplice 285 +#define __NR_openat 286 +#define __NR_mkdirat 287 +#define __NR_mknodat 288 +#define __NR_fchownat 289 +#define __NR_futimesat 290 +#ifdef __powerpc64__ +#define __NR_newfstatat 291 +#else +#define __NR_fstatat64 291 +#endif +#define __NR_unlinkat 292 +#define __NR_renameat 293 +#define __NR_linkat 294 +#define __NR_symlinkat 295 +#define __NR_readlinkat 296 +#define __NR_fchmodat 297 +#define __NR_faccessat 298 -#define __NR_syscalls 286 +#define __NR_syscalls 299 #ifdef __KERNEL__ #define __NR__exit __NR_exit @@ -458,6 +475,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 #ifdef CONFIG_PPC64 #define __ARCH_WANT_COMPAT_SYS_TIME #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_SYS_NEWFSTATAT #endif /* diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index 4b94f70..40f197a 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h @@ -39,6 +39,8 @@ #error "need definition of ppc_sys_devices" #endif +#define PPC_SYS_IORESOURCE_FIXUPPED 0x00000001 + struct ppc_sys_spec { /* PPC sys is matched via (ID & mask) == value, id could be * PVR, SVR, IMMR, * etc. */ diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h index 00ad9c7..4944c0f 100644 --- a/include/asm-ppc/reg_booke.h +++ b/include/asm-ppc/reg_booke.h @@ -237,6 +237,7 @@ do { \ #endif /* Bit definitions for CCR1. */ +#define CCR1_DPC 0x00000100 /* Disable L1 I-Cache/D-Cache parity checking */ #define CCR1_TCS 0x00000080 /* Timer Clock Select */ /* Bit definitions for the MCSR. */ diff --git a/include/sound/pcm.h b/include/sound/pcm.h index df70e75..3734258 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -374,12 +374,14 @@ struct snd_pcm_substream { /* -- OSS things -- */ struct snd_pcm_oss_substream oss; #endif +#ifdef CONFIG_SND_VERBOSE_PROCFS struct snd_info_entry *proc_root; struct snd_info_entry *proc_info_entry; struct snd_info_entry *proc_hw_params_entry; struct snd_info_entry *proc_sw_params_entry; struct snd_info_entry *proc_status_entry; struct snd_info_entry *proc_prealloc_entry; +#endif /* misc flags */ unsigned int no_mmap_ctrl: 1; unsigned int hw_opened: 1; @@ -400,12 +402,14 @@ struct snd_pcm_str { struct snd_pcm_oss_stream oss; #endif struct snd_pcm_file *files; +#ifdef CONFIG_SND_VERBOSE_PROCFS struct snd_info_entry *proc_root; struct snd_info_entry *proc_info_entry; -#ifdef CONFIG_SND_DEBUG +#ifdef CONFIG_SND_PCM_XRUN_DEBUG unsigned int xrun_debug; /* 0 = disabled, 1 = verbose, 2 = stacktrace */ struct snd_info_entry *proc_xrun_debug_entry; #endif +#endif }; struct snd_pcm { diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h index 39df2ba..c854647 100644 --- a/include/sound/pcm_oss.h +++ b/include/sound/pcm_oss.h @@ -75,7 +75,9 @@ struct snd_pcm_oss_substream { struct snd_pcm_oss_stream { struct snd_pcm_oss_setup *setup_list; /* setup list */ struct mutex setup_mutex; +#ifdef CONFIG_SND_VERBOSE_PROCFS struct snd_info_entry *proc_entry; +#endif }; struct snd_pcm_oss { diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 8efc1b1..4262a1c 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -142,7 +142,7 @@ config SND_SUPPORT_OLD_API config SND_VERBOSE_PROCFS bool "Verbose procfs contents" - depends on SND + depends on SND && PROC_FS default y help Say Y here to include code for verbose procfs contents (provides @@ -171,3 +171,13 @@ config SND_DEBUG_DETECT help Say Y here to enable extra-verbose log messages printed when detecting devices. + +config SND_PCM_XRUN_DEBUG + bool "Enable PCM ring buffer overrun/underrun debugging" + default n + depends on SND_DEBUG && SND_VERBOSE_PROCFS + help + Say Y to enable the PCM ring buffer overrun/underrun debugging. + It is usually not required, but if you have trouble with + sound clicking when system is loaded, it may help to determine + the process or driver which causes the scheduling gaps. diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index c5978d6..ac990bf 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1242,6 +1242,8 @@ static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int for if (format != AFMT_QUERY) { formats = snd_pcm_oss_get_formats(pcm_oss_file); + if (formats < 0) + return formats; if (!(formats & format)) format = AFMT_U8; for (idx = 1; idx >= 0; --idx) { @@ -2212,7 +2214,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) return 0; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SND_VERBOSE_PROCFS /* * /proc interface */ @@ -2366,10 +2368,10 @@ static void snd_pcm_oss_proc_done(struct snd_pcm *pcm) } } } -#else /* !CONFIG_PROC_FS */ +#else /* !CONFIG_SND_VERBOSE_PROCFS */ #define snd_pcm_oss_proc_init(pcm) #define snd_pcm_oss_proc_done(pcm) -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_SND_VERBOSE_PROCFS */ /* * ENTRY functions diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 122e10a..84b0003 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -142,7 +142,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, return -ENOIOCTLCMD; } -#if defined(CONFIG_PROC_FS) && defined(CONFIG_SND_VERBOSE_PROCFS) +#ifdef CONFIG_SND_VERBOSE_PROCFS #define STATE(v) [SNDRV_PCM_STATE_##v] = #v #define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v @@ -436,7 +436,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr); } -#ifdef CONFIG_SND_DEBUG +#ifdef CONFIG_SND_PCM_XRUN_DEBUG static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { @@ -480,7 +480,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) } pstr->proc_info_entry = entry; -#ifdef CONFIG_SND_DEBUG +#ifdef CONFIG_SND_PCM_XRUN_DEBUG if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug", pstr->proc_root)) != NULL) { entry->c.text.read_size = 64; @@ -501,7 +501,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { -#ifdef CONFIG_SND_DEBUG +#ifdef CONFIG_SND_PCM_XRUN_DEBUG if (pstr->proc_xrun_debug_entry) { snd_info_unregister(pstr->proc_xrun_debug_entry); pstr->proc_xrun_debug_entry = NULL; @@ -599,12 +599,12 @@ static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) } return 0; } -#else /* !CONFIG_PROC_FS */ +#else /* !CONFIG_SND_VERBOSE_PROCFS */ static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; } static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; } static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; } static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; } -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_SND_VERBOSE_PROCFS */ /** * snd_pcm_new_stream - create a new PCM stream diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 230a940..eedc6cb 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -130,7 +130,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram static void xrun(struct snd_pcm_substream *substream) { snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); -#ifdef CONFIG_SND_DEBUG +#ifdef CONFIG_SND_PCM_XRUN_DEBUG if (substream->pstr->xrun_debug) { snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n", substream->pcm->card->number, @@ -204,7 +204,7 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs delta = hw_ptr_interrupt - new_hw_ptr; if (delta > 0) { if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { -#ifdef CONFIG_SND_DEBUG +#ifdef CONFIG_SND_PCM_XRUN_DEBUG if (runtime->periods > 1 && substream->pstr->xrun_debug) { snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2); if (substream->pstr->xrun_debug > 1) @@ -249,7 +249,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) delta = old_hw_ptr - new_hw_ptr; if (delta > 0) { if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) { -#ifdef CONFIG_SND_DEBUG +#ifdef CONFIG_SND_PCM_XRUN_DEBUG if (runtime->periods > 2 && substream->pstr->xrun_debug) { snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2); if (substream->pstr->xrun_debug > 1) diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index a0119ae..428f8c1 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -100,8 +100,10 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream) { snd_pcm_lib_preallocate_dma_free(substream); +#ifdef CONFIG_SND_VERBOSE_PROCFS snd_info_unregister(substream->proc_prealloc_entry); substream->proc_prealloc_entry = NULL; +#endif return 0; } @@ -124,7 +126,7 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm) return 0; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_SND_VERBOSE_PROCFS /* * read callback for prealloc proc file * @@ -203,9 +205,9 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream) substream->proc_prealloc_entry = entry; } -#else /* !CONFIG_PROC_FS */ +#else /* !CONFIG_SND_VERBOSE_PROCFS */ #define preallocate_info_init(s) -#endif +#endif /* CONFIG_SND_VERBOSE_PROCFS */ /* * pre-allocate the buffer and create a proc file for the substream diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index e35fd57..ae0df54 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -675,10 +675,8 @@ static int __init alsa_card_dummy_init(void) continue; device = platform_device_register_simple(SND_DUMMY_DRIVER, i, NULL, 0); - if (IS_ERR(device)) { - err = PTR_ERR(device); - goto errout; - } + if (IS_ERR(device)) + continue; devices[i] = device; cards++; } @@ -686,14 +684,10 @@ static int __init alsa_card_dummy_init(void) #ifdef MODULE printk(KERN_ERR "Dummy soundcard not found or device busy\n"); #endif - err = -ENODEV; - goto errout; + snd_dummy_unregister_all(); + return -ENODEV; } return 0; - - errout: - snd_dummy_unregister_all(); - return err; } static void __exit alsa_card_dummy_exit(void) diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 9ea3059..da7ef26 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -251,10 +251,8 @@ static int __init alsa_card_mpu401_init(void) #endif device = platform_device_register_simple(SND_MPU401_DRIVER, i, NULL, 0); - if (IS_ERR(device)) { - err = PTR_ERR(device); - goto errout; - } + if (IS_ERR(device)) + continue; platform_devices[i] = device; snd_mpu401_devices++; } @@ -266,14 +264,10 @@ static int __init alsa_card_mpu401_init(void) #ifdef MODULE printk(KERN_ERR "MPU-401 device not found or device busy\n"); #endif - err = -ENODEV; - goto errout; + snd_mpu401_unregister_all(); + return -ENODEV; } return 0; - - errout: - snd_mpu401_unregister_all(); - return err; } static void __exit alsa_card_mpu401_exit(void) diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 1a7fbef..c01b4c5 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -996,10 +996,8 @@ static int __init alsa_card_serial_init(void) continue; device = platform_device_register_simple(SND_SERIAL_DRIVER, i, NULL, 0); - if (IS_ERR(device)) { - err = PTR_ERR(device); - goto errout; - } + if (IS_ERR(device)) + continue; devices[i] = device; cards++; } @@ -1007,14 +1005,10 @@ static int __init alsa_card_serial_init(void) #ifdef MODULE printk(KERN_ERR "serial midi soundcard not found or device busy\n"); #endif - err = -ENODEV; - goto errout; + snd_serial_unregister_all(); + return -ENODEV; } return 0; - - errout: - snd_serial_unregister_all(); - return err; } static void __exit alsa_card_serial_exit(void) diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index a3ee306..26eb249 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c @@ -169,10 +169,8 @@ static int __init alsa_card_virmidi_init(void) continue; device = platform_device_register_simple(SND_VIRMIDI_DRIVER, i, NULL, 0); - if (IS_ERR(device)) { - err = PTR_ERR(device); - goto errout; - } + if (IS_ERR(device)) + continue; devices[i] = device; cards++; } @@ -180,14 +178,10 @@ static int __init alsa_card_virmidi_init(void) #ifdef MODULE printk(KERN_ERR "Card-VirMIDI soundcard not found or device busy\n"); #endif - err = -ENODEV; - goto errout; + snd_virmidi_unregister_all(); + return -ENODEV; } return 0; - - errout: - snd_virmidi_unregister_all(); - return err; } static void __exit alsa_card_virmidi_exit(void) diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 83d64bc..e6bfcf7 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1179,20 +1179,17 @@ static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_mir /* force ACI into a known state */ for (i = 0; i < 3; i++) if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) { - snd_card_free(card); snd_printk(KERN_ERR "can't force aci into known state.\n"); return -ENXIO; } if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 || (miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) { - snd_card_free(card); snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port); return -ENXIO; } if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) { - snd_card_free(card); snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", miro->aci_port); return -ENXIO; diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index c6c8333..eece1c7 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -39,7 +39,6 @@ #include <linux/interrupt.h> #include <linux/compiler.h> #include <linux/delay.h> -#include <linux/dma-mapping.h> #include <sound/driver.h> #include <sound/core.h> @@ -1052,7 +1051,7 @@ snd_ad1889_remove(struct pci_dev *pci) pci_set_drvdata(pci, NULL); } -static struct pci_device_id snd_ad1889_ids[] = { +static struct pci_device_id snd_ad1889_ids[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) }, { 0, }, }; diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index fc92b68..e2dbc21 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -279,7 +279,7 @@ struct snd_ali { #endif }; -static struct pci_device_id snd_ali_ids[] = { +static struct pci_device_id snd_ali_ids[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0}, {0, } }; diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 91899f8..901b08a 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -146,7 +146,7 @@ struct snd_als300_substream_data { int block_counter_register; }; -static struct pci_device_id snd_als300_ids[] = { +static struct pci_device_id snd_als300_ids[] __devinitdata = { { 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 }, { 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS }, { 0, } diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 100d812..60423b1 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -116,7 +116,7 @@ struct snd_card_als4000 { #endif }; -static struct pci_device_id snd_als4000_ids[] = { +static struct pci_device_id snd_als4000_ids[] __devinitdata = { { 0x4005, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ALS4000 */ { 0, } }; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 12e6188..d0f759d 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -284,7 +284,7 @@ struct atiixp { /* */ -static struct pci_device_id snd_atiixp_ids[] = { +static struct pci_device_id snd_atiixp_ids[] __devinitdata = { { 0x1002, 0x4341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */ { 0x1002, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB300 */ { 0x1002, 0x4370, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */ diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 1d37660..12a34c3 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -262,7 +262,7 @@ struct atiixp_modem { /* */ -static struct pci_device_id snd_atiixp_ids[] = { +static struct pci_device_id snd_atiixp_ids[] __devinitdata = { { 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */ { 0x1002, 0x4378, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */ { 0, } diff --git a/sound/pci/au88x0/au8810.c b/sound/pci/au88x0/au8810.c index fce22c7..bd33529 100644 --- a/sound/pci/au88x0/au8810.c +++ b/sound/pci/au88x0/au8810.c @@ -1,6 +1,6 @@ #include "au8810.h" #include "au88x0.h" -static struct pci_device_id snd_vortex_ids[] = { +static struct pci_device_id snd_vortex_ids[] __devinitdata = { {PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1,}, {0,} diff --git a/sound/pci/au88x0/au8820.c b/sound/pci/au88x0/au8820.c index d1fbcce..7e3fd83 100644 --- a/sound/pci/au88x0/au8820.c +++ b/sound/pci/au88x0/au8820.c @@ -1,6 +1,6 @@ #include "au8820.h" #include "au88x0.h" -static struct pci_device_id snd_vortex_ids[] = { +static struct pci_device_id snd_vortex_ids[] __devinitdata = { {PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, {0,} diff --git a/sound/pci/au88x0/au8830.c b/sound/pci/au88x0/au8830.c index d4f2717..b840f66 100644 --- a/sound/pci/au88x0/au8830.c +++ b/sound/pci/au88x0/au8830.c @@ -1,6 +1,6 @@ #include "au8830.h" #include "au88x0.h" -static struct pci_device_id snd_vortex_ids[] = { +static struct pci_device_id snd_vortex_ids[] __devinitdata = { {PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, {0,} diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 680077e..52a3645 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -216,7 +216,7 @@ struct snd_azf3328 { int irq; }; -static const struct pci_device_id snd_azf3328_ids[] = { +static const struct pci_device_id snd_azf3328_ids[] __devinitdata = { { 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */ { 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */ { 0, } diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 7b44a8d..9ee07d4 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -774,7 +774,7 @@ static int __devinit snd_bt87x_create(struct snd_card *card, .driver_data = rate } /* driver_data is the default digital_rate value for that device */ -static struct pci_device_id snd_bt87x_ids[] = { +static struct pci_device_id snd_bt87x_ids[] __devinitdata = { /* Hauppauge WinTV series */ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000), /* Hauppauge WinTV series */ @@ -911,7 +911,7 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci) /* default entries for all Bt87x cards - it's not exported */ /* driver_data is set to 0 to call detection */ -static struct pci_device_id snd_bt87x_default_ids[] = { +static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = { BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0), BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0), { } diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 9477838..fd8bfeb 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1561,7 +1561,7 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci) } // PCI IDs -static struct pci_device_id snd_ca0106_ids[] = { +static struct pci_device_id snd_ca0106_ids[] __devinitdata = { { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */ { 0, } }; diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 2ecbddb..e5ce2da 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2609,7 +2609,7 @@ static inline void snd_cmipci_proc_init(struct cmipci *cm) {} #endif -static struct pci_device_id snd_cmipci_ids[] = { +static struct pci_device_id snd_cmipci_ids[] __devinitdata = { {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index ac4e73f..b3c94d8 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -494,7 +494,7 @@ struct cs4281 { static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static struct pci_device_id snd_cs4281_ids[] = { +static struct pci_device_id snd_cs4281_ids[] __devinitdata = { { 0x1013, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4281 */ { 0, } }; diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index c590602..848d772 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c @@ -65,7 +65,7 @@ MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control."); module_param_array(mmap_valid, bool, NULL, 0444); MODULE_PARM_DESC(mmap_valid, "Support OSS mmap."); -static struct pci_device_id snd_cs46xx_ids[] = { +static struct pci_device_id snd_cs46xx_ids[] __devinitdata = { { 0x1013, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4280 */ { 0x1013, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4612 */ { 0x1013, 0x6004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4615 */ diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 9fc7f38..2c1213a 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -45,7 +45,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static struct pci_device_id snd_cs5535audio_ids[] = { +static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = { { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO, diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 2dfa932..42b11ba 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -77,7 +77,7 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model."); /* * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 */ -static struct pci_device_id snd_emu10k1_ids[] = { +static struct pci_device_id snd_emu10k1_ids[] __devinitdata = { { 0x1102, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* EMU10K1 */ { 0x1102, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy */ { 0x1102, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy 2 Value SB0400 */ diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 3e332f3..d51290c 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -36,7 +36,6 @@ #include <linux/dma-mapping.h> #include <linux/slab.h> #include <linux/moduleparam.h> -#include <linux/dma-mapping.h> #include <sound/core.h> #include <sound/initval.h> #include <sound/pcm.h> @@ -1596,7 +1595,7 @@ static void __devexit snd_emu10k1x_remove(struct pci_dev *pci) } // PCI IDs -static struct pci_device_id snd_emu10k1x_ids[] = { +static struct pci_device_id snd_emu10k1x_ids[] __devinitdata = { { 0x1102, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Dell OEM version (EMU10K1) */ { 0, } }; diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index a5533c8..ca9e34e 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -446,7 +446,7 @@ struct ensoniq { static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static struct pci_device_id snd_audiopci_ids[] = { +static struct pci_device_id snd_audiopci_ids[] __devinitdata = { #ifdef CHIP1370 { 0x1274, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ES1370 */ #endif diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 4d62fe4..6f9094c 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -242,7 +242,7 @@ struct es1938 { static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static struct pci_device_id snd_es1938_ids[] = { +static struct pci_device_id snd_es1938_ids[] __devinitdata = { { 0x125d, 0x1969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Solo-1 */ { 0, } }; diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index e3ad17f..5ff4175 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -104,7 +104,6 @@ #include <linux/slab.h> #include <linux/gameport.h> #include <linux/moduleparam.h> -#include <linux/dma-mapping.h> #include <linux/mutex.h> #include <sound/core.h> @@ -593,7 +592,7 @@ struct es1968 { static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static struct pci_device_id snd_es1968_ids[] = { +static struct pci_device_id snd_es1968_ids[] __devinitdata = { /* Maestro 1 */ { 0x1285, 0x0100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO }, /* Maestro 2 */ diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 6ab4aef..d72fc28 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -199,7 +199,7 @@ struct fm801 { #endif }; -static struct pci_device_id snd_fm801_ids[] = { +static struct pci_device_id snd_fm801_ids[] __devinitdata = { { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */ { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */ { 0, } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 0ad60ae..e821d65 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1614,7 +1614,7 @@ static void __devexit azx_remove(struct pci_dev *pci) } /* PCI IDs */ -static struct pci_device_id azx_ids[] = { +static struct pci_device_id azx_ids[] __devinitdata = { { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */ { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */ { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */ diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index bcfca15..40f000b 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -799,10 +799,14 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { { .modelname = "laptop-eapd", .config = AD1986A_LAPTOP_EAPD }, { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024, .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */ + { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153, + .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1213, .config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x11f7, .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5A */ + { .pci_subvendor = 0x1043, .pci_subdevice = 0x1297, + .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */ { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af, .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */ {} @@ -1330,12 +1334,8 @@ enum { AD1981_BASIC, AD1981_HP }; static struct hda_board_config ad1981_cfg_tbl[] = { { .modelname = "hp", .config = AD1981_HP }, - { .pci_subvendor = 0x103c, .pci_subdevice = 0x30aa, - .config = AD1981_HP }, /* HP nx6320 */ - { .pci_subvendor = 0x103c, .pci_subdevice = 0x309f, - .config = AD1981_HP }, /* HP nx9420 AngelFire */ - { .pci_subvendor = 0x103c, .pci_subdevice = 0x30a2, - .config = AD1981_HP }, /* HP nx9420 AngelFire */ + /* All HP models */ + { .pci_subvendor = 0x103c, .config = AD1981_HP }, { .modelname = "basic", .config = AD1981_BASIC }, {} }; @@ -2623,5 +2623,6 @@ struct hda_codec_preset snd_hda_preset_analog[] = { { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, + { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, {} /* terminator */ }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 66bbdb6..f0e9a9c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2148,6 +2148,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { { .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG }, { .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */ { .pci_subvendor = 0x1509, .pci_subdevice = 0x925d, .config = ALC880_6ST_DIG }, /* FIC P4M-915GD1 */ + { .pci_subvendor = 0x1695, .pci_subdevice = 0x4012, .config = ALC880_5ST_DIG }, /* Epox EP-5LDA+ GLi */ { .modelname = "asus", .config = ALC880_ASUS }, { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG }, diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7152607..8c440fb 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1212,8 +1212,8 @@ static hda_nid_t vaio_mux_nids[] = { 0x15 }; static struct hda_input_mux vaio_mux = { .num_items = 2, .items = { - /* { "HP", 0x0 }, - { "Unknown", 0x1 }, */ + /* { "HP", 0x0 }, */ + { "Line", 0x1 }, { "Mic", 0x2 }, { "PCM", 0x3 }, } diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 32f8415..c56793b 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -56,7 +56,6 @@ #include <linux/dma-mapping.h> #include <linux/slab.h> #include <linux/moduleparam.h> -#include <linux/dma-mapping.h> #include <linux/mutex.h> #include <sound/core.h> @@ -108,7 +107,7 @@ module_param_array(dxr_enable, int, NULL, 0444); MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE."); -static struct pci_device_id snd_ice1712_ids[] = { +static struct pci_device_id snd_ice1712_ids[] __devinitdata = { { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICE1712 */ { 0, } }; diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index fce616c..b1c007e 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -86,7 +86,7 @@ MODULE_PARM_DESC(model, "Use the given board model."); /* Both VT1720 and VT1724 have the same PCI IDs */ -static struct pci_device_id snd_vt1724_ids[] = { +static struct pci_device_id snd_vt1724_ids[] __devinitdata = { { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_VT1724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, } }; diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index ebbf2cf..0df7602 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -413,7 +413,7 @@ struct intel8x0 { u32 int_sta_mask; /* interrupt status mask */ }; -static struct pci_device_id snd_intel8x0_ids[] = { +static struct pci_device_id snd_intel8x0_ids[] __devinitdata = { { 0x8086, 0x2415, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */ { 0x8086, 0x2425, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */ { 0x8086, 0x2445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */ @@ -1293,6 +1293,7 @@ static int snd_intel8x0_ali_ac97spdifout_close(struct snd_pcm_substream *substre return 0; } +#if 0 // NYI static int snd_intel8x0_ali_spdifin_open(struct snd_pcm_substream *substream) { struct intel8x0 *chip = snd_pcm_substream_chip(substream); @@ -1308,7 +1309,6 @@ static int snd_intel8x0_ali_spdifin_close(struct snd_pcm_substream *substream) return 0; } -#if 0 // NYI static int snd_intel8x0_ali_spdifout_open(struct snd_pcm_substream *substream) { struct intel8x0 *chip = snd_pcm_substream_chip(substream); @@ -1435,6 +1435,7 @@ static struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = { .pointer = snd_intel8x0_pcm_pointer, }; +#if 0 // NYI static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = { .open = snd_intel8x0_ali_spdifin_open, .close = snd_intel8x0_ali_spdifin_close, @@ -1446,7 +1447,6 @@ static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = { .pointer = snd_intel8x0_pcm_pointer, }; -#if 0 // NYI static struct snd_pcm_ops snd_intel8x0_ali_spdifout_ops = { .open = snd_intel8x0_ali_spdifout_open, .close = snd_intel8x0_ali_spdifout_close, @@ -1582,7 +1582,7 @@ static struct ich_pcm_table ali_pcms[] __devinitdata = { { .suffix = "IEC958", .playback_ops = &snd_intel8x0_ali_ac97spdifout_ops, - .capture_ops = &snd_intel8x0_ali_spdifin_ops, + /* .capture_ops = &snd_intel8x0_ali_spdifin_ops, */ .prealloc_size = 64 * 1024, .prealloc_max_size = 128 * 1024, .ac97_idx = ALID_AC97SPDIFOUT, diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 47e26aa..720635f 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -224,7 +224,7 @@ struct intel8x0m { unsigned int pcm_pos_shift; }; -static struct pci_device_id snd_intel8x0m_ids[] = { +static struct pci_device_id snd_intel8x0m_ids[] __devinitdata = { { 0x8086, 0x2416, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */ { 0x8086, 0x2426, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */ { 0x8086, 0x2446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */ diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 4721c09..e39fad1 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -424,7 +424,7 @@ module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard."); MODULE_AUTHOR("Haroldo Gamal <gamal@alternex.com.br>"); -static struct pci_device_id snd_korg1212_ids[] = { +static struct pci_device_id snd_korg1212_ids[] __devinitdata = { { .vendor = 0x10b5, .device = 0x906d, diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 9c90d90..1928e06 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -41,7 +41,6 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/moduleparam.h> -#include <linux/dma-mapping.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> @@ -870,7 +869,7 @@ struct snd_m3 { /* * pci ids */ -static struct pci_device_id snd_m3_ids[] = { +static struct pci_device_id snd_m3_ids[] __devinitdata = { {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID, diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index b5a0950..09cc078 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -28,7 +28,6 @@ #include <linux/dma-mapping.h> #include <linux/moduleparam.h> #include <linux/mutex.h> -#include <linux/dma-mapping.h> #include <sound/core.h> #include <sound/initval.h> @@ -62,7 +61,7 @@ MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard."); /* */ -static struct pci_device_id snd_mixart_ids[] = { +static struct pci_device_id snd_mixart_ids[] __devinitdata = { { 0x1057, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* MC8240 */ { 0, } }; diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index cc297ab..b92d660 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -263,7 +263,7 @@ struct nm256 { /* * PCI ids */ -static struct pci_device_id snd_nm256_ids[] = { +static struct pci_device_id snd_nm256_ids[] __devinitdata = { {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 35875c8..dafa223 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -30,7 +30,6 @@ #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/mutex.h> -#include <linux/dma-mapping.h> #include <sound/core.h> #include <sound/initval.h> @@ -74,7 +73,7 @@ enum { PCI_ID_LAST }; -static struct pci_device_id pcxhr_ids[] = { +static struct pci_device_id pcxhr_ids[] __devinitdata = { { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, }, /* VX882HR */ { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, }, /* PCX882HR */ { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, }, /* VX881HR */ diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c index 03517c1..369c19f 100644 --- a/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/sound/pci/pcxhr/pcxhr_hwdep.c @@ -385,8 +385,8 @@ static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw, fw.size = dsp->length; fw.data = vmalloc(fw.size); if (! fw.data) { - snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%d bytes)\n", - fw.size); + snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%lu bytes)\n", + (unsigned long)fw.size); return -ENOMEM; } if (copy_from_user(fw.data, dsp->image, dsp->length)) { diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index f148ee4..d8cc985 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -506,7 +506,7 @@ static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip); /* */ -static struct pci_device_id snd_riptide_ids[] = { +static struct pci_device_id snd_riptide_ids[] __devinitdata = { { .vendor = 0x127a,.device = 0x4310, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, @@ -527,7 +527,7 @@ static struct pci_device_id snd_riptide_ids[] = { }; #ifdef SUPPORT_JOYSTICK -static struct pci_device_id snd_riptide_joystick_ids[] = { +static struct pci_device_id snd_riptide_joystick_ids[] __devinitdata = { { .vendor = 0x127a,.device = 0x4312, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index ab78544..55b1d48 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -227,7 +227,7 @@ struct rme32 { struct snd_kcontrol *spdif_ctl; }; -static struct pci_device_id snd_rme32_ids[] = { +static struct pci_device_id snd_rme32_ids[] __devinitdata = { {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8, diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 6c2a9f4..3c1bc53 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -232,7 +232,7 @@ struct rme96 { struct snd_kcontrol *spdif_ctl; }; -static struct pci_device_id snd_rme96_ids[] = { +static struct pci_device_id snd_rme96_ids[] __devinitdata = { { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8, diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index ebf7a2b..61f82f0 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -568,7 +568,7 @@ static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_d } -static struct pci_device_id snd_hdsp_ids[] = { +static struct pci_device_id snd_hdsp_ids[] __devinitdata = { { .vendor = PCI_VENDOR_ID_XILINX, .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index b5538ef..722b9e6 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -426,7 +426,7 @@ static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = { }; -static struct pci_device_id snd_hdspm_ids[] = { +static struct pci_device_id snd_hdspm_ids[] __devinitdata = { { .vendor = PCI_VENDOR_ID_XILINX, .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI, diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index a687eb6..75d6406 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -315,7 +315,7 @@ static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_d } -static struct pci_device_id snd_rme9652_ids[] = { +static struct pci_device_id snd_rme9652_ids[] __devinitdata = { { .vendor = 0x10ee, .device = 0x3fc4, diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 2d66a09..91f8bf3 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -243,7 +243,7 @@ struct sonicvibes { #endif }; -static struct pci_device_id snd_sonic_ids[] = { +static struct pci_device_id snd_sonic_ids[] __devinitdata = { { 0x5333, 0xca00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, { 0, } }; diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index b453804..9624a5f 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -63,7 +63,7 @@ MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM."); module_param_array(wavetable_size, int, NULL, 0444); MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth."); -static struct pci_device_id snd_trident_ids[] = { +static struct pci_device_id snd_trident_ids[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 0f171dd..39daf62 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -123,6 +123,7 @@ module_param(enable, bool, 0444); #define VIA_REV_8233A 0x40 /* 1 rec, 1 multi-pb, spdf */ #define VIA_REV_8235 0x50 /* 2 rec, 4 pb, 1 multi-pb, spdif */ #define VIA_REV_8237 0x60 +#define VIA_REV_8251 0x70 /* * Direct registers @@ -395,7 +396,7 @@ struct via82xx { #endif }; -static struct pci_device_id snd_via82xx_ids[] = { +static struct pci_device_id snd_via82xx_ids[] __devinitdata = { /* 0x1106, 0x3058 */ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */ /* 0x1106, 0x3059 */ @@ -862,6 +863,11 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *subst if (!status) status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); + /* An apparent bug in the 8251 is worked around by sending a + * REG_CTRL_START. */ + if (chip->revision == VIA_REV_8251 && (status & VIA_REG_STAT_EOL)) + snd_via82xx_pcm_trigger(substream, SNDRV_PCM_TRIGGER_START); + if (!(status & VIA_REG_STAT_ACTIVE)) { res = 0; goto unlock; @@ -2313,6 +2319,7 @@ static struct via823x_info via823x_cards[] __devinitdata = { { VIA_REV_8233A, "VIA 8233A", TYPE_VIA8233A }, { VIA_REV_8235, "VIA 8235", TYPE_VIA8233 }, { VIA_REV_8237, "VIA 8237", TYPE_VIA8233 }, + { VIA_REV_8251, "VIA 8251", TYPE_VIA8233 }, }; /* @@ -2325,7 +2332,7 @@ struct dxs_whitelist { short action; /* new dxs_support value */ }; -static int __devinit check_dxs_list(struct pci_dev *pci) +static int __devinit check_dxs_list(struct pci_dev *pci, int revision) { static struct dxs_whitelist whitelist[] = { { .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */ @@ -2342,6 +2349,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .subvendor = 0x1043, .subdevice = 0x810d, .action = VIA_DXS_SRC }, /* ASUS */ { .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */ { .subvendor = 0x1043, .subdevice = 0x8174, .action = VIA_DXS_SRC }, /* ASUS */ + { .subvendor = 0x1043, .subdevice = 0x81b9, .action = VIA_DXS_SRC }, /* ASUS A8V-MX */ { .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ { .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */ { .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ @@ -2405,6 +2413,10 @@ static int __devinit check_dxs_list(struct pci_dev *pci) } } + /* for newer revision, default to DXS_SRC */ + if (revision >= VIA_REV_8235) + return VIA_DXS_SRC; + /* * not detected, try 48k rate only to be sure. */ @@ -2449,7 +2461,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, } if (chip_type != TYPE_VIA8233A) { if (dxs_support == VIA_DXS_AUTO) - dxs_support = check_dxs_list(pci); + dxs_support = check_dxs_list(pci, revision); /* force to use VIA8233 or 8233A model according to * dxs_support module option */ diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 22ce4d3..ef97e50 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -261,7 +261,7 @@ struct via82xx_modem { struct snd_info_entry *proc_entry; }; -static struct pci_device_id snd_via82xx_modem_ids[] = { +static struct pci_device_id snd_via82xx_modem_ids[] __devinitdata = { { 0x1106, 0x3068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA82XX_MODEM, }, { 0, } }; diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index c816ddf..0f1ebb0 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -60,7 +60,7 @@ enum { VX_PCI_VX222_NEW }; -static struct pci_device_id snd_vx222_ids[] = { +static struct pci_device_id snd_vx222_ids[] __devinitdata = { { 0x10b5, 0x9050, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_OLD, }, /* PLX */ { 0x10b5, 0x9030, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_NEW, }, /* PLX */ { 0, } diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index db57ce9..65ebf5f 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -70,7 +70,7 @@ MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); module_param_array(rear_swap, bool, NULL, 0444); MODULE_PARM_DESC(rear_swap, "Swap rear channels (must be enabled for correct IEC958 (S/PDIF)) output"); -static struct pci_device_id snd_ymfpci_ids[] = { +static struct pci_device_id snd_ymfpci_ids[] __devinitdata = { { 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724 */ { 0x1073, 0x000d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724F */ { 0x1073, 0x000a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF740 */ diff --git a/sound/pcmcia/Kconfig b/sound/pcmcia/Kconfig index 5d1b0b7..c9fa1a2 100644 --- a/sound/pcmcia/Kconfig +++ b/sound/pcmcia/Kconfig @@ -5,7 +5,7 @@ menu "PCMCIA devices" config SND_VXPOCKET tristate "Digigram VXpocket" - depends on SND && PCMCIA && ISA + depends on SND && PCMCIA select SND_VX_LIB help Say Y here to include support for Digigram VXpocket and @@ -16,7 +16,7 @@ config SND_VXPOCKET config SND_PDAUDIOCF tristate "Sound Core PDAudioCF" - depends on SND && PCMCIA && ISA + depends on SND && PCMCIA select SND_PCM help Say Y here to include support for Sound Core PDAudioCF diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c index 4e59517..1ac7c85 100644 --- a/sound/ppc/toonie.c +++ b/sound/ppc/toonie.c @@ -335,7 +335,7 @@ static void toonie_cleanup(struct snd_pmac *chip) chip->mixer_data = NULL; } -int snd_pmac_toonie_init(struct snd_pmac *chip) +int __init snd_pmac_toonie_init(struct snd_pmac *chip) { struct pmac_toonie *mix; diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 0992a09..9351846 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -1531,6 +1531,15 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0014), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + .vendor_name = "TerraTec", + .product_name = "PHASE 26", + .ifnum = 3, + .type = QUIRK_MIDI_STANDARD_INTERFACE + } +}, +{ USB_DEVICE(0x0ccd, 0x0035), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { .vendor_name = "Miditech", |