mirror of
https://github.com/torvalds/linux.git
synced 2024-11-08 05:01:48 +00:00
2e341ca686
This is the first big chunk for 3.5 merges of sound stuff. There are a few big changes in different areas. First off, the streaming logic of USB-audio endpoints has been largely rewritten for the better support of "implicit feedback". If anything about USB got broken, this change has to be checked. For HD-audio, the resume procedure was changed; instead of delaying the resume of the hardware until the first use, now waking up immediately at resume. This is for buggy BIOS. For ASoC, dynamic PCM support and the improved support for digital links between off-SoC devices are major framework changes. Some highlights are below: * HD-audio - Avoid the accesses of invalid pin-control bits that may stall the codec - V-ref setup cleanups - Fix the races in power-saving code - Fix the races in codec cache hashes and connection lists - Split some common codes for BIOS auto-parser to hda_auto_parser.c - Changed the PM resume code to wake up immediately for buggy BIOS - Creative SoundCore3D support - Add Conexant CX20751/2/3/4 codec support * ASoC - Dynamic PCM support, allowing support for SoCs with internal routing through components with tight sequencing and formatting constraints within their internal paths or where there are multiple components connected with CPU managed DMA controllers inside the SoC. - Greatly improved support for direct digital links between off-SoC devices, providing a much simpler way of connecting things like digital basebands to CODECs. - Much more fine grained and robust locking, cleaning up some of the confusion that crept in with multi-component. - CPU support for nVidia Tegra 30 I2S and audio hub controllers and ST-Ericsson MSP I2S controolers - New CODEC drivers for Cirrus CS42L52, LAPIS Semiconductor ML26124, Texas Instruments LM49453. - Some regmap changes needed by the Tegra I2S driver. - mc13783 audio support. * Misc - Rewrite with module_pci_driver() - Xonar DGX support for snd-oxygen - Improvement of packet handling in snd-firewire driver - New USB-endpoint streaming logic - Enhanced M-audio FTU quirks and relevant cleanups - Increment the support of OSS devices to 256 - snd-aloop accuracy improvement There are a few more pending changes for 3.5, but they will be sent slightly later as partly depending on the changes of DRM. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iQIcBAABAgAGBQJPvD/9AAoJEGwxgFQ9KSmkPsIP/AuBGpAZy7b7FiEEIy1Hhdws US8WVuPzyDslMVdzZ8OFqyPXanIcL9gscoOGMZOEy7UFtMBiR4GuYiPRPubEMxuP /gopUqK4SqIsIwT238qqYszSJSxE7gNEZ/2jhSGtkX4EkaSZ4bAskn0iOKX5uw2f kTUQknA1rNLIGba2z6rJbgIW7hdxGfpFy05ruv3ct81nO+5JlgyLuP/v5R6jL+do cum0N4dJFRd9YSEi2BG612gdz8LJyzOgPqBKmxMEva6BfqLkR8EdP80FtE3eEOiP Et1q2LhZwOlBt0BEjsjjOVxMsgxVax6ps9cuNRTk5ECEOldU5dbDatC45L/e9mSD OQVUjYAX1mQAtYva4U4PPn6WU6ma2L5yjy4peCObtyCMkEchXk1bfs4CEfVqCXUP yFYN8C+y6osZOyWE3+Enn9ifZdWyLeSVq6CT33Yt+fyKlswp6gRkhKYiEPqTA5aU p71X59Pp7q1y3tQwiMJNpf2QdkxuxfKURHswdc4BS9ct0mdZhQX0GyDS7OffkTd4 Lq5UkVMHA1rLlF9oRPd2C9P4BuMEuvLjf662YCKiw+mWFYdBC036DHLLjm1Hcwuj UkpQ2PSrrdHG1u0c3ooZ9dQj1BNX4LoABLqvaMtce6sESD/hJ5gcprYJWvtituwM ZzZiJavIWsoJ+SWQWBHe =+JSm -----END PGP SIGNATURE----- Merge tag 'sound-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "This is the first big chunk for 3.5 merges of sound stuff. There are a few big changes in different areas. First off, the streaming logic of USB-audio endpoints has been largely rewritten for the better support of "implicit feedback". If anything about USB got broken, this change has to be checked. For HD-audio, the resume procedure was changed; instead of delaying the resume of the hardware until the first use, now waking up immediately at resume. This is for buggy BIOS. For ASoC, dynamic PCM support and the improved support for digital links between off-SoC devices are major framework changes. Some highlights are below: * HD-audio - Avoid accesses of invalid pin-control bits that may stall the codec - V-ref setup cleanups - Fix the races in power-saving code - Fix the races in codec cache hashes and connection lists - Split some common codes for BIOS auto-parser to hda_auto_parser.c - Changed the PM resume code to wake up immediately for buggy BIOS - Creative SoundCore3D support - Add Conexant CX20751/2/3/4 codec support * ASoC - Dynamic PCM support, allowing support for SoCs with internal routing through components with tight sequencing and formatting constraints within their internal paths or where there are multiple components connected with CPU managed DMA controllers inside the SoC. - Greatly improved support for direct digital links between off-SoC devices, providing a much simpler way of connecting things like digital basebands to CODECs. - Much more fine grained and robust locking, cleaning up some of the confusion that crept in with multi-component. - CPU support for nVidia Tegra 30 I2S and audio hub controllers and ST-Ericsson MSP I2S controolers - New CODEC drivers for Cirrus CS42L52, LAPIS Semiconductor ML26124, Texas Instruments LM49453. - Some regmap changes needed by the Tegra I2S driver. - mc13783 audio support. * Misc - Rewrite with module_pci_driver() - Xonar DGX support for snd-oxygen - Improvement of packet handling in snd-firewire driver - New USB-endpoint streaming logic - Enhanced M-audio FTU quirks and relevant cleanups - Increment the support of OSS devices to 256 - snd-aloop accuracy improvement There are a few more pending changes for 3.5, but they will be sent slightly later as partly depending on the changes of DRM." Fix up conflicts in regmap (due to duplicate patches, with some further updates then having already come in from the regmap tree). Also some fairly trivial context conflicts in the imx and mcx soc drivers. * tag 'sound-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (280 commits) ALSA: snd-usb: fix stream info output in /proc ALSA: pcm - Add proper state checks to snd_pcm_drain() ALSA: sh: Fix up namespace collision in sh_dac_audio. ALSA: hda/realtek - Fix unused variable compile warning ASoC: sh: fsi: enable chip specific data transfer mode ASoC: sh: fsi: call fsi_hw_startup/shutdown from fsi_dai_trigger() ASoC: sh: fsi: use same format for IN/OUT ASoC: sh: fsi: add fsi_version() and removed meaningless version check ASoC: sh: fsi: use register field macro name on IN/OUT_DMAC ASoC: tegra: Add machine driver for WM8753 codec ALSA: hda - Fix possible races of accesses to connection list array ASoC: OMAP: HDMI: Introduce codec ARM: mx31_3ds: Add sound support ASoC: imx-mc13783 cleanup mx31moboard: Add sound support ASoC: mc13783 codec cleanups ASoC: add imx-mc13783 sound support ASoC: Add mc13783 codec mfd: mc13xxx: add codec platform data ASoC: don't flip master of DT-instantiated DAI links ...
1474 lines
33 KiB
C
1474 lines
33 KiB
C
/*
|
|
* AP4EVB board support
|
|
*
|
|
* Copyright (C) 2010 Magnus Damm
|
|
* Copyright (C) 2008 Yoshihiro Shimoda
|
|
*
|
|
* 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; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#include <linux/clk.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/mfd/tmio.h>
|
|
#include <linux/mmc/host.h>
|
|
#include <linux/mmc/sh_mobile_sdhi.h>
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/mtd/partitions.h>
|
|
#include <linux/mtd/physmap.h>
|
|
#include <linux/mmc/sh_mmcif.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/i2c/tsc2007.h>
|
|
#include <linux/io.h>
|
|
#include <linux/smsc911x.h>
|
|
#include <linux/sh_intc.h>
|
|
#include <linux/sh_clk.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/input.h>
|
|
#include <linux/leds.h>
|
|
#include <linux/input/sh_keysc.h>
|
|
#include <linux/usb/r8a66597.h>
|
|
#include <linux/pm_clock.h>
|
|
#include <linux/dma-mapping.h>
|
|
|
|
#include <media/sh_mobile_ceu.h>
|
|
#include <media/sh_mobile_csi2.h>
|
|
#include <media/soc_camera.h>
|
|
|
|
#include <sound/sh_fsi.h>
|
|
#include <sound/simple_card.h>
|
|
|
|
#include <video/sh_mobile_hdmi.h>
|
|
#include <video/sh_mobile_lcdc.h>
|
|
#include <video/sh_mipi_dsi.h>
|
|
|
|
#include <mach/common.h>
|
|
#include <mach/irqs.h>
|
|
#include <mach/sh7372.h>
|
|
|
|
#include <asm/mach-types.h>
|
|
#include <asm/mach/arch.h>
|
|
#include <asm/setup.h>
|
|
|
|
/*
|
|
* Address Interface BusWidth note
|
|
* ------------------------------------------------------------------
|
|
* 0x0000_0000 NOR Flash ROM (MCP) 16bit SW7 : bit1 = ON
|
|
* 0x0800_0000 user area -
|
|
* 0x1000_0000 NOR Flash ROM (MCP) 16bit SW7 : bit1 = OFF
|
|
* 0x1400_0000 Ether (LAN9220) 16bit
|
|
* 0x1600_0000 user area - cannot use with NAND
|
|
* 0x1800_0000 user area -
|
|
* 0x1A00_0000 -
|
|
* 0x4000_0000 LPDDR2-SDRAM (POP) 32bit
|
|
*/
|
|
|
|
/*
|
|
* NOR Flash ROM
|
|
*
|
|
* SW1 | SW2 | SW7 | NOR Flash ROM
|
|
* bit1 | bit1 bit2 | bit1 | Memory allocation
|
|
* ------+------------+------+------------------
|
|
* OFF | ON OFF | ON | Area 0
|
|
* OFF | ON OFF | OFF | Area 4
|
|
*/
|
|
|
|
/*
|
|
* NAND Flash ROM
|
|
*
|
|
* SW1 | SW2 | SW7 | NAND Flash ROM
|
|
* bit1 | bit1 bit2 | bit2 | Memory allocation
|
|
* ------+------------+------+------------------
|
|
* OFF | ON OFF | ON | FCE 0
|
|
* OFF | ON OFF | OFF | FCE 1
|
|
*/
|
|
|
|
/*
|
|
* SMSC 9220
|
|
*
|
|
* SW1 SMSC 9220
|
|
* -----------------------
|
|
* ON access disable
|
|
* OFF access enable
|
|
*/
|
|
|
|
/*
|
|
* LCD / IRQ / KEYSC / IrDA
|
|
*
|
|
* IRQ = IRQ26 (TS), IRQ27 (VIO), IRQ28 (QHD-TouchScreen)
|
|
* LCD = 2nd LCDC (WVGA)
|
|
*
|
|
* | SW43 |
|
|
* SW3 | ON | OFF |
|
|
* -------------+-----------------------+---------------+
|
|
* ON | KEY / IrDA | LCD |
|
|
* OFF | KEY / IrDA / IRQ | IRQ |
|
|
*
|
|
*
|
|
* QHD / WVGA display
|
|
*
|
|
* You can choice display type on menuconfig.
|
|
* Then, check above dip-switch.
|
|
*/
|
|
|
|
/*
|
|
* USB
|
|
*
|
|
* J7 : 1-2 MAX3355E VBUS
|
|
* 2-3 DC 5.0V
|
|
*
|
|
* S39: bit2: off
|
|
*/
|
|
|
|
/*
|
|
* FSI/FSMI
|
|
*
|
|
* SW41 : ON : SH-Mobile AP4 Audio Mode
|
|
* : OFF : Bluetooth Audio Mode
|
|
*/
|
|
|
|
/*
|
|
* MMC0/SDHI1 (CN7)
|
|
*
|
|
* J22 : select card voltage
|
|
* 1-2 pin : 1.8v
|
|
* 2-3 pin : 3.3v
|
|
*
|
|
* SW1 | SW33
|
|
* | bit1 | bit2 | bit3 | bit4
|
|
* ------------+------+------+------+-------
|
|
* MMC0 OFF | OFF | ON | ON | X
|
|
* SDHI1 OFF | ON | X | OFF | ON
|
|
*
|
|
* voltage lebel
|
|
* CN7 : 1.8v
|
|
* CN12: 3.3v
|
|
*/
|
|
|
|
/* MTD */
|
|
static struct mtd_partition nor_flash_partitions[] = {
|
|
{
|
|
.name = "loader",
|
|
.offset = 0x00000000,
|
|
.size = 512 * 1024,
|
|
.mask_flags = MTD_WRITEABLE,
|
|
},
|
|
{
|
|
.name = "bootenv",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = 512 * 1024,
|
|
.mask_flags = MTD_WRITEABLE,
|
|
},
|
|
{
|
|
.name = "kernel_ro",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = 8 * 1024 * 1024,
|
|
.mask_flags = MTD_WRITEABLE,
|
|
},
|
|
{
|
|
.name = "kernel",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = 8 * 1024 * 1024,
|
|
},
|
|
{
|
|
.name = "data",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = MTDPART_SIZ_FULL,
|
|
},
|
|
};
|
|
|
|
static struct physmap_flash_data nor_flash_data = {
|
|
.width = 2,
|
|
.parts = nor_flash_partitions,
|
|
.nr_parts = ARRAY_SIZE(nor_flash_partitions),
|
|
};
|
|
|
|
static struct resource nor_flash_resources[] = {
|
|
[0] = {
|
|
.start = 0x20000000, /* CS0 shadow instead of regular CS0 */
|
|
.end = 0x28000000 - 1, /* needed by USB MASK ROM boot */
|
|
.flags = IORESOURCE_MEM,
|
|
}
|
|
};
|
|
|
|
static struct platform_device nor_flash_device = {
|
|
.name = "physmap-flash",
|
|
.dev = {
|
|
.platform_data = &nor_flash_data,
|
|
},
|
|
.num_resources = ARRAY_SIZE(nor_flash_resources),
|
|
.resource = nor_flash_resources,
|
|
};
|
|
|
|
/* SMSC 9220 */
|
|
static struct resource smc911x_resources[] = {
|
|
{
|
|
.start = 0x14000000,
|
|
.end = 0x16000000 - 1,
|
|
.flags = IORESOURCE_MEM,
|
|
}, {
|
|
.start = evt2irq(0x02c0) /* IRQ6A */,
|
|
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
|
|
},
|
|
};
|
|
|
|
static struct smsc911x_platform_config smsc911x_info = {
|
|
.flags = SMSC911X_USE_16BIT | SMSC911X_SAVE_MAC_ADDRESS,
|
|
.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
|
|
.irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
|
|
};
|
|
|
|
static struct platform_device smc911x_device = {
|
|
.name = "smsc911x",
|
|
.id = -1,
|
|
.num_resources = ARRAY_SIZE(smc911x_resources),
|
|
.resource = smc911x_resources,
|
|
.dev = {
|
|
.platform_data = &smsc911x_info,
|
|
},
|
|
};
|
|
|
|
/*
|
|
* The card detect pin of the top SD/MMC slot (CN7) is active low and is
|
|
* connected to GPIO A22 of SH7372 (GPIO_PORT41).
|
|
*/
|
|
static int slot_cn7_get_cd(struct platform_device *pdev)
|
|
{
|
|
return !gpio_get_value(GPIO_PORT41);
|
|
}
|
|
/* MERAM */
|
|
static struct sh_mobile_meram_info meram_info = {
|
|
.addr_mode = SH_MOBILE_MERAM_MODE1,
|
|
};
|
|
|
|
static struct resource meram_resources[] = {
|
|
[0] = {
|
|
.name = "regs",
|
|
.start = 0xe8000000,
|
|
.end = 0xe807ffff,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.name = "meram",
|
|
.start = 0xe8080000,
|
|
.end = 0xe81fffff,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
};
|
|
|
|
static struct platform_device meram_device = {
|
|
.name = "sh_mobile_meram",
|
|
.id = 0,
|
|
.num_resources = ARRAY_SIZE(meram_resources),
|
|
.resource = meram_resources,
|
|
.dev = {
|
|
.platform_data = &meram_info,
|
|
},
|
|
};
|
|
|
|
/* SH_MMCIF */
|
|
static struct resource sh_mmcif_resources[] = {
|
|
[0] = {
|
|
.name = "MMCIF",
|
|
.start = 0xE6BD0000,
|
|
.end = 0xE6BD00FF,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
/* MMC ERR */
|
|
.start = evt2irq(0x1ac0),
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
[2] = {
|
|
/* MMC NOR */
|
|
.start = evt2irq(0x1ae0),
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct sh_mmcif_plat_data sh_mmcif_plat = {
|
|
.sup_pclk = 0,
|
|
.ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
|
|
.caps = MMC_CAP_4_BIT_DATA |
|
|
MMC_CAP_8_BIT_DATA |
|
|
MMC_CAP_NEEDS_POLL,
|
|
.get_cd = slot_cn7_get_cd,
|
|
.slave_id_tx = SHDMA_SLAVE_MMCIF_TX,
|
|
.slave_id_rx = SHDMA_SLAVE_MMCIF_RX,
|
|
};
|
|
|
|
static struct platform_device sh_mmcif_device = {
|
|
.name = "sh_mmcif",
|
|
.id = 0,
|
|
.dev = {
|
|
.dma_mask = NULL,
|
|
.coherent_dma_mask = 0xffffffff,
|
|
.platform_data = &sh_mmcif_plat,
|
|
},
|
|
.num_resources = ARRAY_SIZE(sh_mmcif_resources),
|
|
.resource = sh_mmcif_resources,
|
|
};
|
|
|
|
/* SDHI0 */
|
|
static struct sh_mobile_sdhi_info sdhi0_info = {
|
|
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
|
|
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
|
|
.tmio_caps = MMC_CAP_SDIO_IRQ,
|
|
};
|
|
|
|
static struct resource sdhi0_resources[] = {
|
|
[0] = {
|
|
.name = "SDHI0",
|
|
.start = 0xe6850000,
|
|
.end = 0xe68500ff,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = evt2irq(0x0e00) /* SDHI0_SDHI0I0 */,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
[2] = {
|
|
.start = evt2irq(0x0e20) /* SDHI0_SDHI0I1 */,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
[3] = {
|
|
.start = evt2irq(0x0e40) /* SDHI0_SDHI0I2 */,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device sdhi0_device = {
|
|
.name = "sh_mobile_sdhi",
|
|
.num_resources = ARRAY_SIZE(sdhi0_resources),
|
|
.resource = sdhi0_resources,
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &sdhi0_info,
|
|
},
|
|
};
|
|
|
|
/* SDHI1 */
|
|
static struct sh_mobile_sdhi_info sdhi1_info = {
|
|
.dma_slave_tx = SHDMA_SLAVE_SDHI1_TX,
|
|
.dma_slave_rx = SHDMA_SLAVE_SDHI1_RX,
|
|
.tmio_ocr_mask = MMC_VDD_165_195,
|
|
.tmio_flags = TMIO_MMC_WRPROTECT_DISABLE,
|
|
.tmio_caps = MMC_CAP_NEEDS_POLL | MMC_CAP_SDIO_IRQ,
|
|
.get_cd = slot_cn7_get_cd,
|
|
};
|
|
|
|
static struct resource sdhi1_resources[] = {
|
|
[0] = {
|
|
.name = "SDHI1",
|
|
.start = 0xe6860000,
|
|
.end = 0xe68600ff,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = evt2irq(0x0e80), /* SDHI1_SDHI1I0 */
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
[2] = {
|
|
.start = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
[3] = {
|
|
.start = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device sdhi1_device = {
|
|
.name = "sh_mobile_sdhi",
|
|
.num_resources = ARRAY_SIZE(sdhi1_resources),
|
|
.resource = sdhi1_resources,
|
|
.id = 1,
|
|
.dev = {
|
|
.platform_data = &sdhi1_info,
|
|
},
|
|
};
|
|
|
|
/* USB1 */
|
|
static void usb1_host_port_power(int port, int power)
|
|
{
|
|
if (!power) /* only power-on supported for now */
|
|
return;
|
|
|
|
/* set VBOUT/PWEN and EXTLP1 in DVSTCTR */
|
|
__raw_writew(__raw_readw(0xE68B0008) | 0x600, 0xE68B0008);
|
|
}
|
|
|
|
static struct r8a66597_platdata usb1_host_data = {
|
|
.on_chip = 1,
|
|
.port_power = usb1_host_port_power,
|
|
};
|
|
|
|
static struct resource usb1_host_resources[] = {
|
|
[0] = {
|
|
.name = "USBHS",
|
|
.start = 0xE68B0000,
|
|
.end = 0xE68B00E6 - 1,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = evt2irq(0x1ce0) /* USB1_USB1I0 */,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device usb1_host_device = {
|
|
.name = "r8a66597_hcd",
|
|
.id = 1,
|
|
.dev = {
|
|
.dma_mask = NULL, /* not use dma */
|
|
.coherent_dma_mask = 0xffffffff,
|
|
.platform_data = &usb1_host_data,
|
|
},
|
|
.num_resources = ARRAY_SIZE(usb1_host_resources),
|
|
.resource = usb1_host_resources,
|
|
};
|
|
|
|
/*
|
|
* QHD display
|
|
*/
|
|
#ifdef CONFIG_AP4EVB_QHD
|
|
|
|
/* KEYSC (Needs SW43 set to ON) */
|
|
static struct sh_keysc_info keysc_info = {
|
|
.mode = SH_KEYSC_MODE_1,
|
|
.scan_timing = 3,
|
|
.delay = 2500,
|
|
.keycodes = {
|
|
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4,
|
|
KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
|
|
KEY_A, KEY_B, KEY_C, KEY_D, KEY_E,
|
|
KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
|
|
KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
|
|
},
|
|
};
|
|
|
|
static struct resource keysc_resources[] = {
|
|
[0] = {
|
|
.name = "KEYSC",
|
|
.start = 0xe61b0000,
|
|
.end = 0xe61b0063,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = evt2irq(0x0be0), /* KEYSC_KEY */
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device keysc_device = {
|
|
.name = "sh_keysc",
|
|
.id = 0, /* "keysc0" clock */
|
|
.num_resources = ARRAY_SIZE(keysc_resources),
|
|
.resource = keysc_resources,
|
|
.dev = {
|
|
.platform_data = &keysc_info,
|
|
},
|
|
};
|
|
|
|
/* MIPI-DSI */
|
|
static int sh_mipi_set_dot_clock(struct platform_device *pdev,
|
|
void __iomem *base,
|
|
int enable)
|
|
{
|
|
struct clk *pck = clk_get(&pdev->dev, "dsip_clk");
|
|
|
|
if (IS_ERR(pck))
|
|
return PTR_ERR(pck);
|
|
|
|
if (enable) {
|
|
/*
|
|
* DSIPCLK = 24MHz
|
|
* D-PHY = DSIPCLK * ((0x6*2)+1) = 312MHz (see .phyctrl)
|
|
* HsByteCLK = D-PHY/8 = 39MHz
|
|
*
|
|
* X * Y * FPS =
|
|
* (544+72+600+16) * (961+8+8+2) * 30 = 36.1MHz
|
|
*/
|
|
clk_set_rate(pck, clk_round_rate(pck, 24000000));
|
|
clk_enable(pck);
|
|
} else {
|
|
clk_disable(pck);
|
|
}
|
|
|
|
clk_put(pck);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct resource mipidsi0_resources[] = {
|
|
[0] = {
|
|
.start = 0xffc60000,
|
|
.end = 0xffc63073,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = 0xffc68000,
|
|
.end = 0xffc680ef,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
};
|
|
|
|
static struct sh_mobile_lcdc_info lcdc_info;
|
|
|
|
static struct sh_mipi_dsi_info mipidsi0_info = {
|
|
.data_format = MIPI_RGB888,
|
|
.lcd_chan = &lcdc_info.ch[0],
|
|
.lane = 2,
|
|
.vsynw_offset = 17,
|
|
.phyctrl = 0x6 << 8,
|
|
.flags = SH_MIPI_DSI_SYNC_PULSES_MODE |
|
|
SH_MIPI_DSI_HSbyteCLK,
|
|
.set_dot_clock = sh_mipi_set_dot_clock,
|
|
};
|
|
|
|
static struct platform_device mipidsi0_device = {
|
|
.name = "sh-mipi-dsi",
|
|
.num_resources = ARRAY_SIZE(mipidsi0_resources),
|
|
.resource = mipidsi0_resources,
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &mipidsi0_info,
|
|
},
|
|
};
|
|
|
|
static struct platform_device *qhd_devices[] __initdata = {
|
|
&mipidsi0_device,
|
|
&keysc_device,
|
|
};
|
|
#endif /* CONFIG_AP4EVB_QHD */
|
|
|
|
/* LCDC0 */
|
|
static const struct fb_videomode ap4evb_lcdc_modes[] = {
|
|
{
|
|
#ifdef CONFIG_AP4EVB_QHD
|
|
.name = "R63302(QHD)",
|
|
.xres = 544,
|
|
.yres = 961,
|
|
.left_margin = 72,
|
|
.right_margin = 600,
|
|
.hsync_len = 16,
|
|
.upper_margin = 8,
|
|
.lower_margin = 8,
|
|
.vsync_len = 2,
|
|
.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
|
|
#else
|
|
.name = "WVGA Panel",
|
|
.xres = 800,
|
|
.yres = 480,
|
|
.left_margin = 220,
|
|
.right_margin = 110,
|
|
.hsync_len = 70,
|
|
.upper_margin = 20,
|
|
.lower_margin = 5,
|
|
.vsync_len = 5,
|
|
.sync = 0,
|
|
#endif
|
|
},
|
|
};
|
|
|
|
static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
|
|
.icb[0] = {
|
|
.meram_size = 0x40,
|
|
},
|
|
.icb[1] = {
|
|
.meram_size = 0x40,
|
|
},
|
|
};
|
|
|
|
static struct sh_mobile_lcdc_info lcdc_info = {
|
|
.meram_dev = &meram_info,
|
|
.ch[0] = {
|
|
.chan = LCDC_CHAN_MAINLCD,
|
|
.fourcc = V4L2_PIX_FMT_RGB565,
|
|
.lcd_modes = ap4evb_lcdc_modes,
|
|
.num_modes = ARRAY_SIZE(ap4evb_lcdc_modes),
|
|
.meram_cfg = &lcd_meram_cfg,
|
|
#ifdef CONFIG_AP4EVB_QHD
|
|
.tx_dev = &mipidsi0_device,
|
|
#endif
|
|
}
|
|
};
|
|
|
|
static struct resource lcdc_resources[] = {
|
|
[0] = {
|
|
.name = "LCDC",
|
|
.start = 0xfe940000, /* P4-only space */
|
|
.end = 0xfe943fff,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = intcs_evt2irq(0x580),
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device lcdc_device = {
|
|
.name = "sh_mobile_lcdc_fb",
|
|
.num_resources = ARRAY_SIZE(lcdc_resources),
|
|
.resource = lcdc_resources,
|
|
.dev = {
|
|
.platform_data = &lcdc_info,
|
|
.coherent_dma_mask = ~0,
|
|
},
|
|
};
|
|
|
|
/* FSI */
|
|
#define IRQ_FSI evt2irq(0x1840)
|
|
static int __fsi_set_rate(struct clk *clk, long rate, int enable)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (rate <= 0)
|
|
return ret;
|
|
|
|
if (enable) {
|
|
ret = clk_set_rate(clk, rate);
|
|
if (0 == ret)
|
|
ret = clk_enable(clk);
|
|
} else {
|
|
clk_disable(clk);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
|
|
{
|
|
return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable);
|
|
}
|
|
|
|
static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable)
|
|
{
|
|
struct clk *fsia_ick;
|
|
struct clk *fsiack;
|
|
int ret = -EIO;
|
|
|
|
fsia_ick = clk_get(dev, "icka");
|
|
if (IS_ERR(fsia_ick))
|
|
return PTR_ERR(fsia_ick);
|
|
|
|
/*
|
|
* FSIACK is connected to AK4642,
|
|
* and use external clock pin from it.
|
|
* it is parent of fsia_ick now.
|
|
*/
|
|
fsiack = clk_get_parent(fsia_ick);
|
|
if (!fsiack)
|
|
goto fsia_ick_out;
|
|
|
|
/*
|
|
* we get 1/1 divided clock by setting same rate to fsiack and fsia_ick
|
|
*
|
|
** FIXME **
|
|
* Because the freq_table of external clk (fsiack) are all 0,
|
|
* the return value of clk_round_rate became 0.
|
|
* So, it use __fsi_set_rate here.
|
|
*/
|
|
ret = __fsi_set_rate(fsiack, rate, enable);
|
|
if (ret < 0)
|
|
goto fsiack_out;
|
|
|
|
ret = __fsi_set_round_rate(fsia_ick, rate, enable);
|
|
if ((ret < 0) && enable)
|
|
__fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */
|
|
|
|
fsiack_out:
|
|
clk_put(fsiack);
|
|
|
|
fsia_ick_out:
|
|
clk_put(fsia_ick);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
|
|
{
|
|
struct clk *fsib_clk;
|
|
struct clk *fdiv_clk = &sh7372_fsidivb_clk;
|
|
long fsib_rate = 0;
|
|
long fdiv_rate = 0;
|
|
int ackmd_bpfmd;
|
|
int ret;
|
|
|
|
switch (rate) {
|
|
case 44100:
|
|
fsib_rate = rate * 256;
|
|
ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
|
|
break;
|
|
case 48000:
|
|
fsib_rate = 85428000; /* around 48kHz x 256 x 7 */
|
|
fdiv_rate = rate * 256;
|
|
ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
|
|
break;
|
|
default:
|
|
pr_err("unsupported rate in FSI2 port B\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* FSI B setting */
|
|
fsib_clk = clk_get(dev, "ickb");
|
|
if (IS_ERR(fsib_clk))
|
|
return -EIO;
|
|
|
|
ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
|
|
if (ret < 0)
|
|
goto fsi_set_rate_end;
|
|
|
|
/* FSI DIV setting */
|
|
ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
|
|
if (ret < 0) {
|
|
/* disable FSI B */
|
|
if (enable)
|
|
__fsi_set_round_rate(fsib_clk, fsib_rate, 0);
|
|
goto fsi_set_rate_end;
|
|
}
|
|
|
|
ret = ackmd_bpfmd;
|
|
|
|
fsi_set_rate_end:
|
|
clk_put(fsib_clk);
|
|
return ret;
|
|
}
|
|
|
|
static struct sh_fsi_platform_info fsi_info = {
|
|
.port_a = {
|
|
.flags = SH_FSI_BRS_INV,
|
|
.set_rate = fsi_ak4642_set_rate,
|
|
},
|
|
.port_b = {
|
|
.flags = SH_FSI_BRS_INV |
|
|
SH_FSI_BRM_INV |
|
|
SH_FSI_LRS_INV |
|
|
SH_FSI_FMT_SPDIF,
|
|
.set_rate = fsi_hdmi_set_rate,
|
|
},
|
|
};
|
|
|
|
static struct resource fsi_resources[] = {
|
|
[0] = {
|
|
.name = "FSI",
|
|
.start = 0xFE3C0000,
|
|
.end = 0xFE3C0400 - 1,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = IRQ_FSI,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device fsi_device = {
|
|
.name = "sh_fsi2",
|
|
.id = -1,
|
|
.num_resources = ARRAY_SIZE(fsi_resources),
|
|
.resource = fsi_resources,
|
|
.dev = {
|
|
.platform_data = &fsi_info,
|
|
},
|
|
};
|
|
|
|
static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = {
|
|
.fmt = SND_SOC_DAIFMT_LEFT_J,
|
|
.codec_daifmt = SND_SOC_DAIFMT_CBM_CFM,
|
|
.cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS,
|
|
.sysclk = 11289600,
|
|
};
|
|
|
|
static struct asoc_simple_card_info fsi2_ak4643_info = {
|
|
.name = "AK4643",
|
|
.card = "FSI2A-AK4643",
|
|
.cpu_dai = "fsia-dai",
|
|
.codec = "ak4642-codec.0-0013",
|
|
.platform = "sh_fsi2",
|
|
.codec_dai = "ak4642-hifi",
|
|
.init = &fsi2_ak4643_init_info,
|
|
};
|
|
|
|
static struct platform_device fsi_ak4643_device = {
|
|
.name = "asoc-simple-card",
|
|
.dev = {
|
|
.platform_data = &fsi2_ak4643_info,
|
|
},
|
|
};
|
|
|
|
/* LCDC1 */
|
|
static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
|
|
unsigned long *parent_freq);
|
|
|
|
static struct sh_mobile_hdmi_info hdmi_info = {
|
|
.flags = HDMI_SND_SRC_SPDIF,
|
|
.clk_optimize_parent = ap4evb_clk_optimize,
|
|
};
|
|
|
|
static struct resource hdmi_resources[] = {
|
|
[0] = {
|
|
.name = "HDMI",
|
|
.start = 0xe6be0000,
|
|
.end = 0xe6be00ff,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
/* There's also an HDMI interrupt on INTCS @ 0x18e0 */
|
|
.start = evt2irq(0x17e0),
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device hdmi_device = {
|
|
.name = "sh-mobile-hdmi",
|
|
.num_resources = ARRAY_SIZE(hdmi_resources),
|
|
.resource = hdmi_resources,
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &hdmi_info,
|
|
},
|
|
};
|
|
|
|
static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
|
|
unsigned long *parent_freq)
|
|
{
|
|
struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
|
|
long error;
|
|
|
|
if (IS_ERR(hdmi_ick)) {
|
|
int ret = PTR_ERR(hdmi_ick);
|
|
pr_err("Cannot get HDMI ICK: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
error = clk_round_parent(hdmi_ick, target, best_freq, parent_freq, 1, 64);
|
|
|
|
clk_put(hdmi_ick);
|
|
|
|
return error;
|
|
}
|
|
|
|
static const struct sh_mobile_meram_cfg hdmi_meram_cfg = {
|
|
.icb[0] = {
|
|
.meram_size = 0x100,
|
|
},
|
|
.icb[1] = {
|
|
.meram_size = 0x100,
|
|
},
|
|
};
|
|
|
|
static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
|
|
.clock_source = LCDC_CLK_EXTERNAL,
|
|
.meram_dev = &meram_info,
|
|
.ch[0] = {
|
|
.chan = LCDC_CHAN_MAINLCD,
|
|
.fourcc = V4L2_PIX_FMT_RGB565,
|
|
.interface_type = RGB24,
|
|
.clock_divider = 1,
|
|
.flags = LCDC_FLAGS_DWPOL,
|
|
.meram_cfg = &hdmi_meram_cfg,
|
|
.tx_dev = &hdmi_device,
|
|
}
|
|
};
|
|
|
|
static struct resource lcdc1_resources[] = {
|
|
[0] = {
|
|
.name = "LCDC1",
|
|
.start = 0xfe944000,
|
|
.end = 0xfe947fff,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = intcs_evt2irq(0x1780),
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device lcdc1_device = {
|
|
.name = "sh_mobile_lcdc_fb",
|
|
.num_resources = ARRAY_SIZE(lcdc1_resources),
|
|
.resource = lcdc1_resources,
|
|
.id = 1,
|
|
.dev = {
|
|
.platform_data = &sh_mobile_lcdc1_info,
|
|
.coherent_dma_mask = ~0,
|
|
},
|
|
};
|
|
|
|
static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
|
|
.cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM,
|
|
};
|
|
|
|
static struct asoc_simple_card_info fsi2_hdmi_info = {
|
|
.name = "HDMI",
|
|
.card = "FSI2B-HDMI",
|
|
.cpu_dai = "fsib-dai",
|
|
.codec = "sh-mobile-hdmi",
|
|
.platform = "sh_fsi2",
|
|
.codec_dai = "sh_mobile_hdmi-hifi",
|
|
.init = &fsi2_hdmi_init_info,
|
|
};
|
|
|
|
static struct platform_device fsi_hdmi_device = {
|
|
.name = "asoc-simple-card",
|
|
.id = 1,
|
|
.dev = {
|
|
.platform_data = &fsi2_hdmi_info,
|
|
},
|
|
};
|
|
|
|
static struct gpio_led ap4evb_leds[] = {
|
|
{
|
|
.name = "led4",
|
|
.gpio = GPIO_PORT185,
|
|
.default_state = LEDS_GPIO_DEFSTATE_ON,
|
|
},
|
|
{
|
|
.name = "led2",
|
|
.gpio = GPIO_PORT186,
|
|
.default_state = LEDS_GPIO_DEFSTATE_ON,
|
|
},
|
|
{
|
|
.name = "led3",
|
|
.gpio = GPIO_PORT187,
|
|
.default_state = LEDS_GPIO_DEFSTATE_ON,
|
|
},
|
|
{
|
|
.name = "led1",
|
|
.gpio = GPIO_PORT188,
|
|
.default_state = LEDS_GPIO_DEFSTATE_ON,
|
|
}
|
|
};
|
|
|
|
static struct gpio_led_platform_data ap4evb_leds_pdata = {
|
|
.num_leds = ARRAY_SIZE(ap4evb_leds),
|
|
.leds = ap4evb_leds,
|
|
};
|
|
|
|
static struct platform_device leds_device = {
|
|
.name = "leds-gpio",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &ap4evb_leds_pdata,
|
|
},
|
|
};
|
|
|
|
static struct i2c_board_info imx074_info = {
|
|
I2C_BOARD_INFO("imx074", 0x1a),
|
|
};
|
|
|
|
static struct soc_camera_link imx074_link = {
|
|
.bus_id = 0,
|
|
.board_info = &imx074_info,
|
|
.i2c_adapter_id = 0,
|
|
.module_name = "imx074",
|
|
};
|
|
|
|
static struct platform_device ap4evb_camera = {
|
|
.name = "soc-camera-pdrv",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &imx074_link,
|
|
},
|
|
};
|
|
|
|
static struct sh_csi2_client_config csi2_clients[] = {
|
|
{
|
|
.phy = SH_CSI2_PHY_MAIN,
|
|
.lanes = 0, /* default: 2 lanes */
|
|
.channel = 0,
|
|
.pdev = &ap4evb_camera,
|
|
},
|
|
};
|
|
|
|
static struct sh_csi2_pdata csi2_info = {
|
|
.type = SH_CSI2C,
|
|
.clients = csi2_clients,
|
|
.num_clients = ARRAY_SIZE(csi2_clients),
|
|
.flags = SH_CSI2_ECC | SH_CSI2_CRC,
|
|
};
|
|
|
|
static struct resource csi2_resources[] = {
|
|
[0] = {
|
|
.name = "CSI2",
|
|
.start = 0xffc90000,
|
|
.end = 0xffc90fff,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = intcs_evt2irq(0x17a0),
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct sh_mobile_ceu_companion csi2 = {
|
|
.id = 0,
|
|
.num_resources = ARRAY_SIZE(csi2_resources),
|
|
.resource = csi2_resources,
|
|
.platform_data = &csi2_info,
|
|
};
|
|
|
|
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
|
|
.flags = SH_CEU_FLAG_USE_8BIT_BUS,
|
|
.max_width = 8188,
|
|
.max_height = 8188,
|
|
.csi2 = &csi2,
|
|
};
|
|
|
|
static struct resource ceu_resources[] = {
|
|
[0] = {
|
|
.name = "CEU",
|
|
.start = 0xfe910000,
|
|
.end = 0xfe91009f,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = intcs_evt2irq(0x880),
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
[2] = {
|
|
/* place holder for contiguous memory */
|
|
},
|
|
};
|
|
|
|
static struct platform_device ceu_device = {
|
|
.name = "sh_mobile_ceu",
|
|
.id = 0, /* "ceu0" clock */
|
|
.num_resources = ARRAY_SIZE(ceu_resources),
|
|
.resource = ceu_resources,
|
|
.dev = {
|
|
.platform_data = &sh_mobile_ceu_info,
|
|
.coherent_dma_mask = 0xffffffff,
|
|
},
|
|
};
|
|
|
|
static struct platform_device *ap4evb_devices[] __initdata = {
|
|
&leds_device,
|
|
&nor_flash_device,
|
|
&smc911x_device,
|
|
&sdhi0_device,
|
|
&sdhi1_device,
|
|
&usb1_host_device,
|
|
&fsi_device,
|
|
&fsi_ak4643_device,
|
|
&fsi_hdmi_device,
|
|
&sh_mmcif_device,
|
|
&hdmi_device,
|
|
&lcdc_device,
|
|
&lcdc1_device,
|
|
&ceu_device,
|
|
&ap4evb_camera,
|
|
&meram_device,
|
|
};
|
|
|
|
static void __init hdmi_init_pm_clock(void)
|
|
{
|
|
struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
|
|
int ret;
|
|
long rate;
|
|
|
|
if (IS_ERR(hdmi_ick)) {
|
|
ret = PTR_ERR(hdmi_ick);
|
|
pr_err("Cannot get HDMI ICK: %d\n", ret);
|
|
goto out;
|
|
}
|
|
|
|
ret = clk_set_parent(&sh7372_pllc2_clk, &sh7372_dv_clki_div2_clk);
|
|
if (ret < 0) {
|
|
pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, sh7372_pllc2_clk.usecount);
|
|
goto out;
|
|
}
|
|
|
|
pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&sh7372_pllc2_clk));
|
|
|
|
rate = clk_round_rate(&sh7372_pllc2_clk, 594000000);
|
|
if (rate < 0) {
|
|
pr_err("Cannot get suitable rate: %ld\n", rate);
|
|
ret = rate;
|
|
goto out;
|
|
}
|
|
|
|
ret = clk_set_rate(&sh7372_pllc2_clk, rate);
|
|
if (ret < 0) {
|
|
pr_err("Cannot set rate %ld: %d\n", rate, ret);
|
|
goto out;
|
|
}
|
|
|
|
pr_debug("PLLC2 set frequency %lu\n", rate);
|
|
|
|
ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
|
|
if (ret < 0)
|
|
pr_err("Cannot set HDMI parent: %d\n", ret);
|
|
|
|
out:
|
|
if (!IS_ERR(hdmi_ick))
|
|
clk_put(hdmi_ick);
|
|
}
|
|
|
|
static void __init fsi_init_pm_clock(void)
|
|
{
|
|
struct clk *fsia_ick;
|
|
int ret;
|
|
|
|
fsia_ick = clk_get(&fsi_device.dev, "icka");
|
|
if (IS_ERR(fsia_ick)) {
|
|
ret = PTR_ERR(fsia_ick);
|
|
pr_err("Cannot get FSI ICK: %d\n", ret);
|
|
return;
|
|
}
|
|
|
|
ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk);
|
|
if (ret < 0)
|
|
pr_err("Cannot set FSI-A parent: %d\n", ret);
|
|
|
|
clk_put(fsia_ick);
|
|
}
|
|
|
|
/*
|
|
* FIXME !!
|
|
*
|
|
* gpio_no_direction
|
|
* are quick_hack.
|
|
*
|
|
* current gpio frame work doesn't have
|
|
* the method to control only pull up/down/free.
|
|
* this function should be replaced by correct gpio function
|
|
*/
|
|
static void __init gpio_no_direction(u32 addr)
|
|
{
|
|
__raw_writeb(0x00, addr);
|
|
}
|
|
|
|
/* TouchScreen */
|
|
#ifdef CONFIG_AP4EVB_QHD
|
|
# define GPIO_TSC_IRQ GPIO_FN_IRQ28_123
|
|
# define GPIO_TSC_PORT GPIO_PORT123
|
|
#else /* WVGA */
|
|
# define GPIO_TSC_IRQ GPIO_FN_IRQ7_40
|
|
# define GPIO_TSC_PORT GPIO_PORT40
|
|
#endif
|
|
|
|
#define IRQ28 evt2irq(0x3380) /* IRQ28A */
|
|
#define IRQ7 evt2irq(0x02e0) /* IRQ7A */
|
|
static int ts_get_pendown_state(void)
|
|
{
|
|
int val;
|
|
|
|
gpio_free(GPIO_TSC_IRQ);
|
|
|
|
gpio_request(GPIO_TSC_PORT, NULL);
|
|
|
|
gpio_direction_input(GPIO_TSC_PORT);
|
|
|
|
val = gpio_get_value(GPIO_TSC_PORT);
|
|
|
|
gpio_request(GPIO_TSC_IRQ, NULL);
|
|
|
|
return !val;
|
|
}
|
|
|
|
static int ts_init(void)
|
|
{
|
|
gpio_request(GPIO_TSC_IRQ, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct tsc2007_platform_data tsc2007_info = {
|
|
.model = 2007,
|
|
.x_plate_ohms = 180,
|
|
.get_pendown_state = ts_get_pendown_state,
|
|
.init_platform_hw = ts_init,
|
|
};
|
|
|
|
static struct i2c_board_info tsc_device = {
|
|
I2C_BOARD_INFO("tsc2007", 0x48),
|
|
.type = "tsc2007",
|
|
.platform_data = &tsc2007_info,
|
|
/*.irq is selected on ap4evb_init */
|
|
};
|
|
|
|
/* I2C */
|
|
static struct i2c_board_info i2c0_devices[] = {
|
|
{
|
|
I2C_BOARD_INFO("ak4643", 0x13),
|
|
},
|
|
};
|
|
|
|
static struct i2c_board_info i2c1_devices[] = {
|
|
{
|
|
I2C_BOARD_INFO("r2025sd", 0x32),
|
|
},
|
|
};
|
|
|
|
|
|
#define GPIO_PORT9CR 0xE6051009
|
|
#define GPIO_PORT10CR 0xE605100A
|
|
#define USCCR1 0xE6058144
|
|
static void __init ap4evb_init(void)
|
|
{
|
|
u32 srcr4;
|
|
struct clk *clk;
|
|
|
|
/* External clock source */
|
|
clk_set_rate(&sh7372_dv_clki_clk, 27000000);
|
|
|
|
sh7372_pinmux_init();
|
|
|
|
/* enable SCIFA0 */
|
|
gpio_request(GPIO_FN_SCIFA0_TXD, NULL);
|
|
gpio_request(GPIO_FN_SCIFA0_RXD, NULL);
|
|
|
|
/* enable SMSC911X */
|
|
gpio_request(GPIO_FN_CS5A, NULL);
|
|
gpio_request(GPIO_FN_IRQ6_39, NULL);
|
|
|
|
/* enable Debug switch (S6) */
|
|
gpio_request(GPIO_PORT32, NULL);
|
|
gpio_request(GPIO_PORT33, NULL);
|
|
gpio_request(GPIO_PORT34, NULL);
|
|
gpio_request(GPIO_PORT35, NULL);
|
|
gpio_direction_input(GPIO_PORT32);
|
|
gpio_direction_input(GPIO_PORT33);
|
|
gpio_direction_input(GPIO_PORT34);
|
|
gpio_direction_input(GPIO_PORT35);
|
|
gpio_export(GPIO_PORT32, 0);
|
|
gpio_export(GPIO_PORT33, 0);
|
|
gpio_export(GPIO_PORT34, 0);
|
|
gpio_export(GPIO_PORT35, 0);
|
|
|
|
/* SDHI0 */
|
|
gpio_request(GPIO_FN_SDHICD0, NULL);
|
|
gpio_request(GPIO_FN_SDHIWP0, NULL);
|
|
gpio_request(GPIO_FN_SDHICMD0, NULL);
|
|
gpio_request(GPIO_FN_SDHICLK0, NULL);
|
|
gpio_request(GPIO_FN_SDHID0_3, NULL);
|
|
gpio_request(GPIO_FN_SDHID0_2, NULL);
|
|
gpio_request(GPIO_FN_SDHID0_1, NULL);
|
|
gpio_request(GPIO_FN_SDHID0_0, NULL);
|
|
|
|
/* SDHI1 */
|
|
gpio_request(GPIO_FN_SDHICMD1, NULL);
|
|
gpio_request(GPIO_FN_SDHICLK1, NULL);
|
|
gpio_request(GPIO_FN_SDHID1_3, NULL);
|
|
gpio_request(GPIO_FN_SDHID1_2, NULL);
|
|
gpio_request(GPIO_FN_SDHID1_1, NULL);
|
|
gpio_request(GPIO_FN_SDHID1_0, NULL);
|
|
|
|
/* MMCIF */
|
|
gpio_request(GPIO_FN_MMCD0_0, NULL);
|
|
gpio_request(GPIO_FN_MMCD0_1, NULL);
|
|
gpio_request(GPIO_FN_MMCD0_2, NULL);
|
|
gpio_request(GPIO_FN_MMCD0_3, NULL);
|
|
gpio_request(GPIO_FN_MMCD0_4, NULL);
|
|
gpio_request(GPIO_FN_MMCD0_5, NULL);
|
|
gpio_request(GPIO_FN_MMCD0_6, NULL);
|
|
gpio_request(GPIO_FN_MMCD0_7, NULL);
|
|
gpio_request(GPIO_FN_MMCCMD0, NULL);
|
|
gpio_request(GPIO_FN_MMCCLK0, NULL);
|
|
|
|
/* USB enable */
|
|
gpio_request(GPIO_FN_VBUS0_1, NULL);
|
|
gpio_request(GPIO_FN_IDIN_1_18, NULL);
|
|
gpio_request(GPIO_FN_PWEN_1_115, NULL);
|
|
gpio_request(GPIO_FN_OVCN_1_114, NULL);
|
|
gpio_request(GPIO_FN_EXTLP_1, NULL);
|
|
gpio_request(GPIO_FN_OVCN2_1, NULL);
|
|
|
|
/* setup USB phy */
|
|
__raw_writew(0x8a0a, 0xE6058130); /* USBCR4 */
|
|
|
|
/* enable FSI2 port A (ak4643) */
|
|
gpio_request(GPIO_FN_FSIAIBT, NULL);
|
|
gpio_request(GPIO_FN_FSIAILR, NULL);
|
|
gpio_request(GPIO_FN_FSIAISLD, NULL);
|
|
gpio_request(GPIO_FN_FSIAOSLD, NULL);
|
|
gpio_request(GPIO_PORT161, NULL);
|
|
gpio_direction_output(GPIO_PORT161, 0); /* slave */
|
|
|
|
gpio_request(GPIO_PORT9, NULL);
|
|
gpio_request(GPIO_PORT10, NULL);
|
|
gpio_no_direction(GPIO_PORT9CR); /* FSIAOBT needs no direction */
|
|
gpio_no_direction(GPIO_PORT10CR); /* FSIAOLR needs no direction */
|
|
|
|
/* card detect pin for MMC slot (CN7) */
|
|
gpio_request(GPIO_PORT41, NULL);
|
|
gpio_direction_input(GPIO_PORT41);
|
|
|
|
/* setup FSI2 port B (HDMI) */
|
|
gpio_request(GPIO_FN_FSIBCK, NULL);
|
|
__raw_writew(__raw_readw(USCCR1) & ~(1 << 6), USCCR1); /* use SPDIF */
|
|
|
|
/* set SPU2 clock to 119.6 MHz */
|
|
clk = clk_get(NULL, "spu_clk");
|
|
if (!IS_ERR(clk)) {
|
|
clk_set_rate(clk, clk_round_rate(clk, 119600000));
|
|
clk_put(clk);
|
|
}
|
|
|
|
/*
|
|
* set irq priority, to avoid sound chopping
|
|
* when NFS rootfs is used
|
|
* FSI(3) > SMSC911X(2)
|
|
*/
|
|
intc_set_priority(IRQ_FSI, 3);
|
|
|
|
i2c_register_board_info(0, i2c0_devices,
|
|
ARRAY_SIZE(i2c0_devices));
|
|
|
|
i2c_register_board_info(1, i2c1_devices,
|
|
ARRAY_SIZE(i2c1_devices));
|
|
|
|
#ifdef CONFIG_AP4EVB_QHD
|
|
|
|
/*
|
|
* For QHD Panel (MIPI-DSI, CONFIG_AP4EVB_QHD=y) and
|
|
* IRQ28 for Touch Panel, set dip switches S3, S43 as OFF, ON.
|
|
*/
|
|
|
|
/* enable KEYSC */
|
|
gpio_request(GPIO_FN_KEYOUT0, NULL);
|
|
gpio_request(GPIO_FN_KEYOUT1, NULL);
|
|
gpio_request(GPIO_FN_KEYOUT2, NULL);
|
|
gpio_request(GPIO_FN_KEYOUT3, NULL);
|
|
gpio_request(GPIO_FN_KEYOUT4, NULL);
|
|
gpio_request(GPIO_FN_KEYIN0_136, NULL);
|
|
gpio_request(GPIO_FN_KEYIN1_135, NULL);
|
|
gpio_request(GPIO_FN_KEYIN2_134, NULL);
|
|
gpio_request(GPIO_FN_KEYIN3_133, NULL);
|
|
gpio_request(GPIO_FN_KEYIN4, NULL);
|
|
|
|
/* enable TouchScreen */
|
|
irq_set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW);
|
|
|
|
tsc_device.irq = IRQ28;
|
|
i2c_register_board_info(1, &tsc_device, 1);
|
|
|
|
/* LCDC0 */
|
|
lcdc_info.clock_source = LCDC_CLK_PERIPHERAL;
|
|
lcdc_info.ch[0].interface_type = RGB24;
|
|
lcdc_info.ch[0].clock_divider = 1;
|
|
lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL;
|
|
lcdc_info.ch[0].panel_cfg.width = 44;
|
|
lcdc_info.ch[0].panel_cfg.height = 79;
|
|
|
|
platform_add_devices(qhd_devices, ARRAY_SIZE(qhd_devices));
|
|
|
|
#else
|
|
/*
|
|
* For WVGA Panel (18-bit RGB, CONFIG_AP4EVB_WVGA=y) and
|
|
* IRQ7 for Touch Panel, set dip switches S3, S43 to ON, OFF.
|
|
*/
|
|
|
|
gpio_request(GPIO_FN_LCDD17, NULL);
|
|
gpio_request(GPIO_FN_LCDD16, NULL);
|
|
gpio_request(GPIO_FN_LCDD15, NULL);
|
|
gpio_request(GPIO_FN_LCDD14, NULL);
|
|
gpio_request(GPIO_FN_LCDD13, NULL);
|
|
gpio_request(GPIO_FN_LCDD12, NULL);
|
|
gpio_request(GPIO_FN_LCDD11, NULL);
|
|
gpio_request(GPIO_FN_LCDD10, NULL);
|
|
gpio_request(GPIO_FN_LCDD9, NULL);
|
|
gpio_request(GPIO_FN_LCDD8, NULL);
|
|
gpio_request(GPIO_FN_LCDD7, NULL);
|
|
gpio_request(GPIO_FN_LCDD6, NULL);
|
|
gpio_request(GPIO_FN_LCDD5, NULL);
|
|
gpio_request(GPIO_FN_LCDD4, NULL);
|
|
gpio_request(GPIO_FN_LCDD3, NULL);
|
|
gpio_request(GPIO_FN_LCDD2, NULL);
|
|
gpio_request(GPIO_FN_LCDD1, NULL);
|
|
gpio_request(GPIO_FN_LCDD0, NULL);
|
|
gpio_request(GPIO_FN_LCDDISP, NULL);
|
|
gpio_request(GPIO_FN_LCDDCK, NULL);
|
|
|
|
gpio_request(GPIO_PORT189, NULL); /* backlight */
|
|
gpio_direction_output(GPIO_PORT189, 1);
|
|
|
|
gpio_request(GPIO_PORT151, NULL); /* LCDDON */
|
|
gpio_direction_output(GPIO_PORT151, 1);
|
|
|
|
lcdc_info.clock_source = LCDC_CLK_BUS;
|
|
lcdc_info.ch[0].interface_type = RGB18;
|
|
lcdc_info.ch[0].clock_divider = 3;
|
|
lcdc_info.ch[0].flags = 0;
|
|
lcdc_info.ch[0].panel_cfg.width = 152;
|
|
lcdc_info.ch[0].panel_cfg.height = 91;
|
|
|
|
/* enable TouchScreen */
|
|
irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
|
|
|
|
tsc_device.irq = IRQ7;
|
|
i2c_register_board_info(0, &tsc_device, 1);
|
|
#endif /* CONFIG_AP4EVB_QHD */
|
|
|
|
/* CEU */
|
|
|
|
/*
|
|
* TODO: reserve memory for V4L2 DMA buffers, when a suitable API
|
|
* becomes available
|
|
*/
|
|
|
|
/* MIPI-CSI stuff */
|
|
gpio_request(GPIO_FN_VIO_CKO, NULL);
|
|
|
|
clk = clk_get(NULL, "vck1_clk");
|
|
if (!IS_ERR(clk)) {
|
|
clk_set_rate(clk, clk_round_rate(clk, 13000000));
|
|
clk_enable(clk);
|
|
clk_put(clk);
|
|
}
|
|
|
|
sh7372_add_standard_devices();
|
|
|
|
/* HDMI */
|
|
gpio_request(GPIO_FN_HDMI_HPD, NULL);
|
|
gpio_request(GPIO_FN_HDMI_CEC, NULL);
|
|
|
|
/* Reset HDMI, must be held at least one EXTALR (32768Hz) period */
|
|
#define SRCR4 0xe61580bc
|
|
srcr4 = __raw_readl(SRCR4);
|
|
__raw_writel(srcr4 | (1 << 13), SRCR4);
|
|
udelay(50);
|
|
__raw_writel(srcr4 & ~(1 << 13), SRCR4);
|
|
|
|
platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
|
|
|
|
sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc1_device);
|
|
sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
|
|
sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
|
|
|
|
sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
|
|
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
|
|
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
|
|
sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
|
|
|
|
hdmi_init_pm_clock();
|
|
fsi_init_pm_clock();
|
|
sh7372_pm_init();
|
|
pm_clk_add(&fsi_device.dev, "spu2");
|
|
pm_clk_add(&lcdc1_device.dev, "hdmi");
|
|
}
|
|
|
|
MACHINE_START(AP4EVB, "ap4evb")
|
|
.map_io = sh7372_map_io,
|
|
.init_early = sh7372_add_early_devices,
|
|
.init_irq = sh7372_init_irq,
|
|
.handle_irq = shmobile_handle_irq_intc,
|
|
.init_machine = ap4evb_init,
|
|
.timer = &shmobile_timer,
|
|
MACHINE_END
|