From 1af71dd0514d33b9d79a77d693608eecba2c66df Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Tue, 8 Apr 2014 13:53:48 +0200 Subject: apalis_imx6: spdif support Integrate S/PDIF support on standard Apalis MXM3 pins 215 (SPDIF1_OUT) and 217 (SPDIF1_IN): card 1: imxspdif [imx-spdif], device 0: IMX SPDIF mxc-spdif-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 Tested with Apalis iMX6Q 1GB V1.0A on Apalis Evaluation Board V1.0A (JP25 1-2 S/PDIF OUT X21 and SPDIF1_IN X5-3). --- arch/arm/mach-mx6/board-apalis_imx6.c | 41 ++++++++++++++++++++++++++++++++++- arch/arm/mach-mx6/pads-apalis_imx6.h | 6 +++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-mx6/board-apalis_imx6.c b/arch/arm/mach-mx6/board-apalis_imx6.c index 48e5c2308bcd..8bc0eeccdeed 100644 --- a/arch/arm/mach-mx6/board-apalis_imx6.c +++ b/arch/arm/mach-mx6/board-apalis_imx6.c @@ -1362,6 +1362,7 @@ static void mx6_snvs_poweroff(void) } static const struct imx_pcie_platform_data pcie_data __initconst = { +//PLX switch? .pcie_pwr_en = -EINVAL, .pcie_rst = -EINVAL, .pcie_wake_up = -EINVAL, @@ -1388,6 +1389,35 @@ static void apalis_imx6_gpio_init(void) } } } + +static int spdif_clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long rate_actual; + rate_actual = clk_round_rate(clk, rate); + clk_set_rate(clk, rate_actual); + return 0; +} + +static struct mxc_spdif_platform_data mxc_spdif_data = { + .spdif_tx = 1, /* enable tx */ + .spdif_rx = 1, /* enable rx */ + /* + * spdif0_clk will be 454.7MHz divided by ccm dividers. + * + * 44.1KHz: 454.7MHz / 7 (ccm) / 23 (spdif) = 44,128 Hz ~ 0.06% error + * 48KHz: 454.7MHz / 4 (ccm) / 37 (spdif) = 48,004 Hz ~ 0.01% error + * 32KHz: 454.7MHz / 6 (ccm) / 37 (spdif) = 32,003 Hz ~ 0.01% error + */ + .spdif_clk_44100 = 1, /* tx clk from spdif0_clk_root */ + .spdif_clk_48000 = 1, /* tx clk from spdif0_clk_root */ + .spdif_div_44100 = 23, + .spdif_div_48000 = 37, + .spdif_div_32000 = 37, + .spdif_rx_clk = 0, /* rx clk from spdif stream */ + .spdif_clk_set_rate = spdif_clk_set_rate, + .spdif_clk = NULL, /* spdif bus clk */ +}; + /*! * Board specific initialization. */ @@ -1412,6 +1442,8 @@ static void __init board_init(void) #if !defined(CSI0_CAMERA) IOMUX_SETUP(csi0_gpio_pads); #endif + IOMUX_SETUP(spdif_pads); + /* setup MMC/SD pads with settings for slow clock */ plt_sd_pad_change(0, 400000); plt_sd_pad_change(1, 400000); @@ -1420,7 +1452,8 @@ static void __init board_init(void) lcd_disable_pins(); vga_dac_enable_pins(); - /* PCIe set switch reset, inital 0 */ + /* PCIe set PLX switch reset, inital 0 */ +//does not take chip errata into account gpio_request(GP_PEX_PERST, "PEX_PERST"); gpio_direction_output(GP_PEX_PERST, 0); msleep(100); /* TODO Wait asynchronous */ @@ -1558,6 +1591,12 @@ static void __init board_init(void) imx6q_add_hdmi_soc(); imx6q_add_hdmi_soc_dai(); + mxc_spdif_data.spdif_core_clk = clk_get_sys("mxc_spdif.0", NULL); + clk_put(mxc_spdif_data.spdif_core_clk); + imx6q_add_spdif(&mxc_spdif_data); + imx6q_add_spdif_dai(); + imx6q_add_spdif_audio_device(); + ret = gpio_request_array(flexcan_gpios, ARRAY_SIZE(flexcan_gpios)); if (ret) { pr_err("failed to request flexcan1-gpios: %d\n", ret); diff --git a/arch/arm/mach-mx6/pads-apalis_imx6.h b/arch/arm/mach-mx6/pads-apalis_imx6.h index db826be33a5c..1db391c89880 100644 --- a/arch/arm/mach-mx6/pads-apalis_imx6.h +++ b/arch/arm/mach-mx6/pads-apalis_imx6.h @@ -621,4 +621,10 @@ static iomux_v3_cfg_t * MX6NAME(sd_pads)[] = MX6NAME(sd4_100mhz), MX6NAME(sd4_200mhz), }; + +/* Apalis SPDIF */ +static iomux_v3_cfg_t MX6NAME(spdif_pads)[] = { + MX6Q_PAD_GPIO_16__SPDIF_IN1, + MX6Q_PAD_GPIO_17__SPDIF_OUT1, +}; #define FIRST_INCLUDE_DONE -- cgit v1.2.3