Module Name: src Committed By: jmcneill Date: Mon May 18 19:32:48 UTC 2015
Modified Files: src/sys/arch/arm/nvidia: files.tegra tegra_car.c tegra_carreg.h tegra_io.c tegra_var.h src/sys/arch/evbarm/conf: JETSONTK1 src/sys/arch/evbarm/tegra: tegra_machdep.c Added Files: src/sys/arch/arm/nvidia: tegra_dc.c tegra_dcreg.h tegra_genfb.c tegra_hdmi.c tegra_hdmireg.h Log Message: Work in progress HDMI / framebuffer support for Tegra K1. To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 src/sys/arch/arm/nvidia/files.tegra cvs rdiff -u -r1.15 -r1.16 src/sys/arch/arm/nvidia/tegra_car.c cvs rdiff -u -r1.14 -r1.15 src/sys/arch/arm/nvidia/tegra_carreg.h cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/nvidia/tegra_dc.c \ src/sys/arch/arm/nvidia/tegra_dcreg.h \ src/sys/arch/arm/nvidia/tegra_genfb.c \ src/sys/arch/arm/nvidia/tegra_hdmi.c \ src/sys/arch/arm/nvidia/tegra_hdmireg.h cvs rdiff -u -r1.9 -r1.10 src/sys/arch/arm/nvidia/tegra_io.c cvs rdiff -u -r1.16 -r1.17 src/sys/arch/arm/nvidia/tegra_var.h cvs rdiff -u -r1.20 -r1.21 src/sys/arch/evbarm/conf/JETSONTK1 cvs rdiff -u -r1.15 -r1.16 src/sys/arch/evbarm/tegra/tegra_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/nvidia/files.tegra diff -u src/sys/arch/arm/nvidia/files.tegra:1.11 src/sys/arch/arm/nvidia/files.tegra:1.12 --- src/sys/arch/arm/nvidia/files.tegra:1.11 Fri May 15 11:49:10 2015 +++ src/sys/arch/arm/nvidia/files.tegra Mon May 18 19:32:48 2015 @@ -1,4 +1,4 @@ -# $NetBSD: files.tegra,v 1.11 2015/05/15 11:49:10 jmcneill Exp $ +# $NetBSD: files.tegra,v 1.12 2015/05/18 19:32:48 jmcneill Exp $ # # Configuration info for NVIDIA Tegra ARM Peripherals # @@ -87,6 +87,20 @@ file arch/arm/nvidia/tegra_ahcisata.c te attach hdaudio at tegraio with tegra_hdaudio file arch/arm/nvidia/tegra_hdaudio.c tegra_hdaudio +# Display controller +device tegradc { } +attach tegradc at tegraio with tegra_dc +file arch/arm/nvidia/tegra_dc.c tegra_dc + +# Framebuffer console +attach genfb at tegradc with tegra_genfb +file arch/arm/nvidia/tegra_genfb.c tegra_genfb + +# HDMI +device tegrahdmi: edid, ddc_read_edid, videomode +attach tegrahdmi at tegraio with tegra_hdmi +file arch/arm/nvidia/tegra_hdmi.c tegra_hdmi + # Console parameters defparam opt_tegra.h CONADDR defparam opt_tegra.h CONSPEED Index: src/sys/arch/arm/nvidia/tegra_car.c diff -u src/sys/arch/arm/nvidia/tegra_car.c:1.15 src/sys/arch/arm/nvidia/tegra_car.c:1.16 --- src/sys/arch/arm/nvidia/tegra_car.c:1.15 Sat May 16 23:07:51 2015 +++ src/sys/arch/arm/nvidia/tegra_car.c Mon May 18 19:32:48 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: tegra_car.c,v 1.15 2015/05/16 23:07:51 jmcneill Exp $ */ +/* $NetBSD: tegra_car.c,v 1.16 2015/05/18 19:32:48 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> @@ -29,7 +29,7 @@ #include "locators.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tegra_car.c,v 1.15 2015/05/16 23:07:51 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tegra_car.c,v 1.16 2015/05/18 19:32:48 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -52,6 +52,8 @@ struct tegra_car_softc { bus_space_handle_t sc_bsh; }; +static void tegra_car_init(struct tegra_car_softc *); + static struct tegra_car_softc *pmc_softc = NULL; CFATTACH_DECL_NEW(tegra_car, sizeof(struct tegra_car_softc), @@ -81,11 +83,28 @@ tegra_car_attach(device_t parent, device aprint_naive("\n"); aprint_normal(": CAR\n"); + tegra_car_init(sc); + aprint_verbose_dev(self, "PLLX = %u Hz\n", tegra_car_pllx_rate()); aprint_verbose_dev(self, "PLLC = %u Hz\n", tegra_car_pllc_rate()); aprint_verbose_dev(self, "PLLE = %u Hz\n", tegra_car_plle_rate()); aprint_verbose_dev(self, "PLLU = %u Hz\n", tegra_car_pllu_rate()); aprint_verbose_dev(self, "PLLP0 = %u Hz\n", tegra_car_pllp0_rate()); + aprint_verbose_dev(self, "PLLD2 = %u Hz\n", tegra_car_plld2_rate()); +} + +static void +tegra_car_init(struct tegra_car_softc *sc) +{ + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + + tegra_reg_set_clear(bst, bsh, CAR_PLLD2_BASE_REG, + __SHIFTIN(1, CAR_PLLD2_BASE_MDIV) | + __SHIFTIN(99, CAR_PLLD2_BASE_NDIV) | + __SHIFTIN(2, CAR_PLLD2_BASE_PLDIV), + CAR_PLLD2_BASE_REF_SRC_SEL | + CAR_PLLD2_BASE_PLDIV | CAR_PLLD2_BASE_NDIV | CAR_PLLD2_BASE_MDIV); } static void @@ -220,6 +239,13 @@ tegra_car_pllp0_rate(void) } u_int +tegra_car_plld2_rate(void) +{ + return tegra_car_pll_rate(CAR_PLLD2_BASE_REG, CAR_PLLD2_BASE_MDIV, + CAR_PLLD2_BASE_NDIV, CAR_PLLD2_BASE_PLDIV); +} + +u_int tegra_car_uart_rate(u_int port) { bus_space_tag_t bst; @@ -577,3 +603,71 @@ tegra_car_periph_i2c_enable(u_int port, return 0; } + +void +tegra_car_hdmi_enable(u_int rate) +{ + bus_space_tag_t bst; + bus_space_handle_t bsh; + + tegra_car_get_bs(&bst, &bsh); + + /* Enter reset, enable clock */ + bus_space_write_4(bst, bsh, CAR_RST_DEV_H_SET_REG, CAR_DEV_H_HDMI); + bus_space_write_4(bst, bsh, CAR_CLK_ENB_H_SET_REG, CAR_DEV_H_HDMI); + + /* Change IDDQ from 1 to 0 */ + tegra_reg_set_clear(bst, bsh, CAR_PLLD2_BASE_REG, + 0, CAR_PLLD2_BASE_IDDQ); + delay(2); + /* Enable PLLD2 */ + tegra_reg_set_clear(bst, bsh, CAR_PLLD2_BASE_REG, + CAR_PLLD2_BASE_ENABLE, 0); + + /* Set clock source to PLLD2 */ + const u_int div = howmany(tegra_car_plld2_rate(), rate);; + bus_space_write_4(bst, bsh, CAR_CLKSRC_HDMI_REG, + __SHIFTIN(CAR_CLKSRC_HDMI_SRC_PLLD2_OUT0, CAR_CLKSRC_HDMI_SRC) | + __SHIFTIN(div - 1, CAR_CLKSRC_HDMI_DIV)); + + /* Leave reset */ + bus_space_write_4(bst, bsh, CAR_RST_DEV_H_CLR_REG, CAR_DEV_H_HDMI); +} + +int +tegra_car_dc_enable(u_int port) +{ + bus_space_tag_t bst; + bus_space_handle_t bsh; + bus_size_t src_reg; + uint32_t dev_bit; + + tegra_car_get_bs(&bst, &bsh); + + switch (port) { + case 0: + dev_bit = CAR_DEV_L_DISP1; + src_reg = CAR_CLKSRC_DISP1_REG; + break; + case 1: + dev_bit = CAR_DEV_L_DISP2; + src_reg = CAR_CLKSRC_DISP2_REG; + break; + default: + return EINVAL; + } + + /* Enter reset, enable clock */ + bus_space_write_4(bst, bsh, CAR_RST_DEV_L_SET_REG, dev_bit); + bus_space_write_4(bst, bsh, CAR_CLK_ENB_L_SET_REG, dev_bit); + + /* Select PLLP for clock source */ + bus_space_write_4(bst, bsh, src_reg, + __SHIFTIN(CAR_CLKSRC_DISP_SRC_PLLP_OUT0, + CAR_CLKSRC_DISP_SRC)); + + /* Leave reset */ + bus_space_write_4(bst, bsh, CAR_RST_DEV_L_CLR_REG, dev_bit); + + return 0; +} Index: src/sys/arch/arm/nvidia/tegra_carreg.h diff -u src/sys/arch/arm/nvidia/tegra_carreg.h:1.14 src/sys/arch/arm/nvidia/tegra_carreg.h:1.15 --- src/sys/arch/arm/nvidia/tegra_carreg.h:1.14 Thu May 14 10:23:03 2015 +++ src/sys/arch/arm/nvidia/tegra_carreg.h Mon May 18 19:32:48 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: tegra_carreg.h,v 1.14 2015/05/14 10:23:03 jmcneill Exp $ */ +/* $NetBSD: tegra_carreg.h,v 1.15 2015/05/18 19:32:48 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> @@ -104,6 +104,30 @@ #define CAR_PLLE_MISC_REG 0xec +#define CAR_PLLD2_BASE_REG 0x4b8 +#define CAR_PLLD2_BASE_BYPASS __BIT(31) +#define CAR_PLLD2_BASE_ENABLE __BIT(30) +#define CAR_PLLD2_BASE_REF_DIS __BIT(29) +#define CAR_PLLD2_BASE_FREQLOCK __BIT(28) +#define CAR_PLLD2_BASE_LOCK __BIT(27) +#define CAR_PLLD2_BASE_REF_SRC_SEL __BITS(26,25) +#define CAR_PLLD2_BASE_REF_SRC_SEL_PLL_D 0 +#define CAR_PLLD2_BASE_REF_SRC_SEL_PLL_D2 1 +#define CAR_PLLD2_BASE_LOCK_OVERRIDE __BIT(24) +#define CAR_PLLD2_BASE_PLDIV __BITS(23,20) +#define CAR_PLLD2_BASE_IDDQ __BIT(19) +#define CAR_PLLD2_BASE_PTS __BIT(16) +#define CAR_PLLD2_BASE_NDIV __BITS(15,8) +#define CAR_PLLD2_BASE_MDIV __BITS(7,0) + +#define CAR_PLLD2_MISC_REG 0x4bc +#define CAR_PLLD2_MISC_EN_FSTLCK __BIT(31) +#define CAR_PLLD2_MISC_LOCK_ENABLE __BIT(30) +#define CAR_PLLD2_MISC_MON_TEST_OUT __BITS(29,27) +#define CAR_PLLD2_MISC_KCP __BITS(26,25) +#define CAR_PLLD2_MISC_KVCO __BIT(24) +#define CAR_PLLD2_MISC_SETUP __BITS(23,0) + #define CAR_CLKSRC_I2C1_REG 0x124 #define CAR_CLKSRC_I2C2_REG 0x198 #define CAR_CLKSRC_I2C3_REG 0x1b8 @@ -150,6 +174,28 @@ #define CAR_CLKSRC_SDMMC_SRC_CLK_M 6 #define CAR_CLKSRC_SDMMC_DIV __BITS(7,0) +#define CAR_CLKSRC_HDMI_REG 0x18c +#define CAR_CLKSRC_HDMI_SRC __BITS(31,29) +#define CAR_CLKSRC_HDMI_SRC_PLLP_OUT0 0 +#define CAR_CLKSRC_HDMI_SRC_PLLM_OUT0 1 +#define CAR_CLKSRC_HDMI_SRC_PLLD_OUT0 2 +#define CAR_CLKSRC_HDMI_SRC_PLLA_OUT0 3 +#define CAR_CLKSRC_HDMI_SRC_PLLC_OUT0 4 +#define CAR_CLKSRC_HDMI_SRC_PLLD2_OUT0 5 +#define CAR_CLKSRC_HDMI_SRC_CLK_M 6 +#define CAR_CLKSRC_HDMI_DIV __BITS(7,0) + +#define CAR_CLKSRC_DISP1_REG 0x138 +#define CAR_CLKSRC_DISP2_REG 0x13c +#define CAR_CLKSRC_DISP_SRC __BITS(31,29) +#define CAR_CLKSRC_DISP_SRC_PLLP_OUT0 0 +#define CAR_CLKSRC_DISP_SRC_PLLM_OUT0 1 +#define CAR_CLKSRC_DISP_SRC_PLLD_OUT0 2 +#define CAR_CLKSRC_DISP_SRC_PLLA_OUT0 3 +#define CAR_CLKSRC_DISP_SRC_PLLC_OUT0 4 +#define CAR_CLKSRC_DISP_SRC_PLLD2_OUT0 5 +#define CAR_CLKSRC_DISP_SRC_CLK_M 6 + #define CAR_RST_DEV_L_SET_REG 0x300 #define CAR_RST_DEV_L_CLR_REG 0x304 #define CAR_RST_DEV_H_SET_REG 0x308 Index: src/sys/arch/arm/nvidia/tegra_io.c diff -u src/sys/arch/arm/nvidia/tegra_io.c:1.9 src/sys/arch/arm/nvidia/tegra_io.c:1.10 --- src/sys/arch/arm/nvidia/tegra_io.c:1.9 Fri May 15 11:49:10 2015 +++ src/sys/arch/arm/nvidia/tegra_io.c Mon May 18 19:32:48 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: tegra_io.c,v 1.9 2015/05/15 11:49:10 jmcneill Exp $ */ +/* $NetBSD: tegra_io.c,v 1.10 2015/05/18 19:32:48 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> @@ -29,7 +29,7 @@ #include "opt_tegra.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.9 2015/05/15 11:49:10 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tegra_io.c,v 1.10 2015/05/18 19:32:48 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -127,6 +127,15 @@ static const struct tegra_locators tegra TEGRA_PCIE_OFFSET, TEGRA_PCIE_SIZE, NOPORT, TEGRA_INTR_PCIE_INT }, }; +static const struct tegra_locators tegra_ghost_locators[] = { + { "tegradc", + TEGRA_DISPLAYA_OFFSET, TEGRA_DISPLAYA_SIZE, 0, TEGRA_INTR_DISPLAYA }, + { "tegradc", + TEGRA_DISPLAYB_OFFSET, TEGRA_DISPLAYB_SIZE, 1, TEGRA_INTR_DISPLAYB }, + { "tegrahdmi", + TEGRA_HDMI_OFFSET, TEGRA_HDMI_SIZE, NOPORT, TEGRA_INTR_HDMI }, +}; + int tegraio_match(device_t parent, cfdata_t cf, void *aux) { @@ -150,6 +159,8 @@ tegraio_attach(device_t parent, device_t tegraio_scan(self, tegra_ahb_a2_bsh, tegra_ahb_a2_locators, __arraycount(tegra_ahb_a2_locators)); tegraio_scan(self, (bus_space_handle_t)NULL, + tegra_ghost_locators, __arraycount(tegra_ghost_locators)); + tegraio_scan(self, (bus_space_handle_t)NULL, tegra_pcie_locators, __arraycount(tegra_pcie_locators)); } Index: src/sys/arch/arm/nvidia/tegra_var.h diff -u src/sys/arch/arm/nvidia/tegra_var.h:1.16 src/sys/arch/arm/nvidia/tegra_var.h:1.17 --- src/sys/arch/arm/nvidia/tegra_var.h:1.16 Fri May 15 11:50:30 2015 +++ src/sys/arch/arm/nvidia/tegra_var.h Mon May 18 19:32:48 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: tegra_var.h,v 1.16 2015/05/15 11:50:30 jmcneill Exp $ */ +/* $NetBSD: tegra_var.h,v 1.17 2015/05/18 19:32:48 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> @@ -53,6 +53,18 @@ struct tegraio_attach_args { bus_dma_tag_t tio_coherent_dmat; }; +struct tegrafb_attach_args { + bool tfb_console; + bus_dma_tag_t tfb_dmat; + bus_dmamap_t tfb_dmamap; + void *tfb_dmap; + u_int tfb_width; + u_int tfb_height; + u_int tfb_depth; + u_int tfb_stride; + device_t tfb_outputdev; +}; + extern struct bus_space armv7_generic_bs_tag; extern struct bus_space armv7_generic_a4x_bs_tag; extern bus_space_handle_t tegra_host1x_bsh; @@ -81,6 +93,7 @@ u_int tegra_car_pllx_rate(void); void tegra_car_pllx_set_rate(u_int, u_int, u_int); u_int tegra_car_pllu_rate(void); u_int tegra_car_pllp0_rate(void); +u_int tegra_car_plld2_rate(void); u_int tegra_car_uart_rate(u_int); u_int tegra_car_periph_sdmmc_rate(u_int); int tegra_car_periph_sdmmc_set_div(u_int, u_int); @@ -90,6 +103,8 @@ void tegra_car_periph_sata_enable(void); int tegra_car_periph_i2c_enable(u_int, u_int); void tegra_car_utmip_init(void); void tegra_car_utmip_enable(u_int); +void tegra_car_hdmi_enable(u_int); +int tegra_car_dc_enable(u_int); struct tegra_gpio_pin; struct tegra_gpio_pin *tegra_gpio_acquire(const char *, u_int); @@ -126,6 +141,11 @@ psize_t tegra_mc_memsize(void); void tegra_xusbpad_sata_enable(void); +struct videomode; +int tegra_dc_port(device_t); +int tegra_dc_enable(device_t, device_t, const struct videomode *); +void tegra_dc_hdmi_start(device_t); + #define TEGRA_CPUFREQ_MAX 16 struct tegra_cpufreq_func { u_int (*set_rate)(u_int); Index: src/sys/arch/evbarm/conf/JETSONTK1 diff -u src/sys/arch/evbarm/conf/JETSONTK1:1.20 src/sys/arch/evbarm/conf/JETSONTK1:1.21 --- src/sys/arch/evbarm/conf/JETSONTK1:1.20 Sat May 16 11:49:01 2015 +++ src/sys/arch/evbarm/conf/JETSONTK1 Mon May 18 19:32:48 2015 @@ -1,5 +1,5 @@ # -# $NetBSD: JETSONTK1,v 1.20 2015/05/16 11:49:01 jmcneill Exp $ +# $NetBSD: JETSONTK1,v 1.21 2015/05/18 19:32:48 jmcneill Exp $ # # NVIDIA Jetson TK1 - Tegra K1 development kit # https://developer.nvidia.com/jetson-tk1 @@ -116,6 +116,28 @@ wd* at atabus? drive ? #options HDAUDIO_ENABLE_HDMI #options HDAUDIO_ENABLE_DISPLAYPORT +# Display controller +tegradc0 at tegraio? port 0 # DISPLAYA +tegradc1 at tegraio? port 1 # DISPLAYB +genfb* at tegradc? +wsdisplay* at genfb? +options VCONS_DRAW_INTR +options WSEMUL_VT100 +options WS_DEFAULT_FG=WSCOL_WHITE +options WS_DEFAULT_BG=WSCOL_BLACK +options WS_KERNEL_FG=WSCOL_GREEN +options WS_KERNEL_BG=WSCOL_BLACK +options WSDISPLAY_COMPAT_PCVT +options WSDISPLAY_COMPAT_SYSCONS +options WSDISPLAY_COMPAT_USL +options WSDISPLAY_COMPAT_RAWKBD +options WSDISPLAY_DEFAULTSCREENS=4 +pseudo-device wsmux +pseudo-device wsfont + +# HDMI +tegrahdmi0 at tegraio? # HDMI + # USB 2.0 ehci0 at tegraio? port 0 # USB1 ehci1 at tegraio? port 1 # USB2 Index: src/sys/arch/evbarm/tegra/tegra_machdep.c diff -u src/sys/arch/evbarm/tegra/tegra_machdep.c:1.15 src/sys/arch/evbarm/tegra/tegra_machdep.c:1.16 --- src/sys/arch/evbarm/tegra/tegra_machdep.c:1.15 Thu May 14 00:02:00 2015 +++ src/sys/arch/evbarm/tegra/tegra_machdep.c Mon May 18 19:32:48 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: tegra_machdep.c,v 1.15 2015/05/14 00:02:00 jmcneill Exp $ */ +/* $NetBSD: tegra_machdep.c,v 1.16 2015/05/18 19:32:48 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tegra_machdep.c,v 1.15 2015/05/14 00:02:00 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tegra_machdep.c,v 1.16 2015/05/18 19:32:48 jmcneill Exp $"); #include "opt_tegra.h" #include "opt_machdep.h" @@ -356,6 +356,17 @@ consinit(void) #endif } +static bool +tegra_bootconf_match(const char *key, const char *val) +{ + char *s; + + if (!get_bootconf_option(boot_args, key, BOOTOPT_TYPE_STRING, &s)) + return false; + + return strncmp(s, val, strlen(val)) == 0; +} + void tegra_device_register(device_t self, void *aux) { @@ -377,6 +388,14 @@ tegra_device_register(device_t self, voi tegra_cpuinit(); } + if (device_is_a(self, "tegradc") + && tegra_bootconf_match("console", "fb")) { + prop_dictionary_set_bool(dict, "is_console", true); +#if NUKBD > 0 + ukbd_cnattach(); +#endif + } + #ifdef BOARD_JETSONTK1 if (device_is_a(self, "sdhc") && device_is_a(device_parent(self), "tegraio")) { @@ -406,5 +425,13 @@ tegra_device_register(device_t self, voi prop_dictionary_set_cstring(dict, "vbus-gpio", "N5"); } } + + if (device_is_a(self, "tegrahdmi")) { + prop_dictionary_set_cstring(dict, "hpd-gpio", "N7"); + prop_dictionary_set_cstring(dict, "pll-gpio", "H7"); + prop_dictionary_set_cstring(dict, "power-gpio", "K6"); + prop_dictionary_set_cstring(dict, "ddc-device", "ddc0"); + prop_dictionary_set_cstring(dict, "display-device", "tegradc1"); + } #endif } Added files: Index: src/sys/arch/arm/nvidia/tegra_dc.c diff -u /dev/null src/sys/arch/arm/nvidia/tegra_dc.c:1.1 --- /dev/null Mon May 18 19:32:48 2015 +++ src/sys/arch/arm/nvidia/tegra_dc.c Mon May 18 19:32:48 2015 @@ -0,0 +1,354 @@ +/* $NetBSD: tegra_dc.c,v 1.1 2015/05/18 19:32:48 jmcneill Exp $ */ + +/*- + * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. + */ + +#include "locators.h" + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: tegra_dc.c,v 1.1 2015/05/18 19:32:48 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/kernel.h> + +#include <dev/videomode/videomode.h> + +#include <arm/nvidia/tegra_reg.h> +#include <arm/nvidia/tegra_dcreg.h> +#include <arm/nvidia/tegra_var.h> + +#define TEGRA_DC_NPORTS 2 +#define TEGRA_DC_DEPTH 32 +#define TEGRA_DC_FBALIGN 16 + +static int tegra_dc_match(device_t, cfdata_t, void *); +static void tegra_dc_attach(device_t, device_t, void *); + +struct tegra_dc_softc { + device_t sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + bus_dma_tag_t sc_dmat; + int sc_port; + + bus_dma_segment_t sc_dmasegs[1]; + bus_size_t sc_dmasize; + bus_dmamap_t sc_dmamap; + void *sc_dmap; + + device_t sc_fbdev; +}; + +static int tegra_dc_print(void *, const char *); +static int tegra_dc_allocmem(struct tegra_dc_softc *, bus_size_t); +static int tegra_dc_init(struct tegra_dc_softc *, + const struct videomode *); +static void tegra_dc_init_win(struct tegra_dc_softc *, + const struct videomode *); +static void tegra_dc_init_disp(struct tegra_dc_softc *, + const struct videomode *); +static void tegra_dc_update(struct tegra_dc_softc *); + +CFATTACH_DECL_NEW(tegra_dc, sizeof(struct tegra_dc_softc), + tegra_dc_match, tegra_dc_attach, NULL, NULL); + +#define DC_READ(sc, reg) \ + bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) +#define DC_WRITE(sc, reg, val) \ + bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) +#define DC_SET_CLEAR(sc, reg, set, clr) \ + tegra_reg_set_clear((sc)->sc_bst, (sc)->sc_bsh, (reg), (set), (clr)) + +static int +tegra_dc_match(device_t parent, cfdata_t cf, void *aux) +{ + struct tegraio_attach_args * const tio = aux; + const struct tegra_locators * const loc = &tio->tio_loc; + + if (loc->loc_port == TEGRAIOCF_PORT_DEFAULT || + loc->loc_port >= TEGRA_DC_NPORTS) + return 0; + + return 1; +} + +static void +tegra_dc_attach(device_t parent, device_t self, void *aux) +{ + struct tegra_dc_softc * const sc = device_private(self); + struct tegraio_attach_args * const tio = aux; + const struct tegra_locators * const loc = &tio->tio_loc; + + sc->sc_dev = self; + sc->sc_port = loc->loc_port; + sc->sc_bst = tio->tio_bst; + sc->sc_dmat = tio->tio_dmat; + if (bus_space_map(sc->sc_bst, TEGRA_GHOST_BASE + loc->loc_offset, + loc->loc_size, 0, &sc->sc_bsh) != 0) { + aprint_error(": couldn't map DC\n"); + return; + } + + aprint_naive("\n"); + aprint_normal(": DISPLAY%c\n", loc->loc_port + 'A'); +} + + +static int +tegra_dc_allocmem(struct tegra_dc_softc *sc, bus_size_t size) +{ + int error, nsegs; + + error = bus_dmamem_alloc(sc->sc_dmat, size, TEGRA_DC_FBALIGN, 0, + sc->sc_dmasegs, 1, &nsegs, BUS_DMA_WAITOK); + if (error) + return error; + error = bus_dmamem_map(sc->sc_dmat, sc->sc_dmasegs, nsegs, size, + &sc->sc_dmap, BUS_DMA_WAITOK | BUS_DMA_COHERENT); + if (error) + goto free; + error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, + BUS_DMA_WAITOK, &sc->sc_dmamap); + if (error) + goto unmap; + error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_dmap, + size, NULL, BUS_DMA_WAITOK); + if (error) + goto destroy; + + sc->sc_dmasize = size; + + return 0; + +destroy: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap); +unmap: + bus_dmamem_unmap(sc->sc_dmat, sc->sc_dmap, size); +free: + bus_dmamem_free(sc->sc_dmat, sc->sc_dmasegs, nsegs); + + sc->sc_dmasize = 0; + sc->sc_dmap = NULL; + + return error; +} + +static int +tegra_dc_print(void *aux, const char *pnp) +{ + const struct tegrafb_attach_args * const tfb = aux; + + aprint_normal(" output %s", device_xname(tfb->tfb_outputdev)); + + return UNCONF; +} + +static int +tegra_dc_init(struct tegra_dc_softc *sc, const struct videomode *mode) +{ + tegra_car_dc_enable(sc->sc_port); + + tegra_dc_init_win(sc, mode); + tegra_dc_init_disp(sc, mode); + tegra_dc_update(sc); + return 0; +} + + +static void +tegra_dc_init_win(struct tegra_dc_softc *sc, const struct videomode *mode) +{ + /* Enable window A programming */ + DC_WRITE(sc, DC_CMD_DISPLAY_WINDOW_HEADER_REG, + DC_CMD_DISPLAY_WINDOW_HEADER_WINDOW_A_SELECT); + + /* Set colour depth to ARGB8888 */ + DC_WRITE(sc, DC_WINC_A_COLOR_DEPTH_REG, + __SHIFTIN(DC_WINC_A_COLOR_DEPTH_DEPTH_T_A8R8G8B8, + DC_WINC_A_COLOR_DEPTH_DEPTH)); + + /* Disable byte swapping */ + DC_WRITE(sc, DC_WINC_A_BYTE_SWAP_REG, + __SHIFTIN(DC_WINC_A_BYTE_SWAP_SWAP_NOSWAP, + DC_WINC_A_BYTE_SWAP_SWAP)); + + /* Window position, size, stride */ + DC_WRITE(sc, DC_WINC_A_POSITION_REG, + __SHIFTIN(0, DC_WINC_A_POSITION_V) | + __SHIFTIN(0, DC_WINC_A_POSITION_H)); + DC_WRITE(sc, DC_WINC_A_SIZE_REG, + __SHIFTIN(mode->vdisplay, DC_WINC_A_SIZE_V) | + __SHIFTIN(mode->hdisplay, DC_WINC_A_SIZE_H)); + DC_WRITE(sc, DC_WINC_A_PRESCALED_SIZE_REG, + __SHIFTIN(mode->vdisplay, DC_WINC_A_PRESCALED_SIZE_V) | + __SHIFTIN(mode->hdisplay * (TEGRA_DC_DEPTH / 8), + DC_WINC_A_PRESCALED_SIZE_H)); + DC_WRITE(sc, DC_WINC_A_LINE_STRIDE_REG, + __SHIFTIN(mode->hdisplay * (TEGRA_DC_DEPTH / 8), + DC_WINC_A_LINE_STRIDE_LINE_STRIDE)); + + /* Framebuffer start address */ + DC_WRITE(sc, DC_WINBUF_A_START_ADDR_REG, + (uint32_t)sc->sc_dmamap->dm_segs[0].ds_addr); + + /* Surface kind */ + DC_WRITE(sc, DC_WINBUF_A_SURFACE_KIND_REG, + __SHIFTIN(DC_WINBUF_A_SURFACE_KIND_SURFACE_KIND_PITCH, + DC_WINBUF_A_SURFACE_KIND_SURFACE_KIND)); + + /* Enable window A */ + DC_WRITE(sc, DC_WINC_A_WIN_OPTIONS_REG, + DC_WINC_A_WIN_OPTIONS_WIN_ENABLE); +} + +static void +tegra_dc_init_disp(struct tegra_dc_softc *sc, const struct videomode *mode) +{ + const u_int hspw = mode->hsync_end - mode->hsync_start; + const u_int hbp = mode->htotal - mode->hsync_start; + const u_int hfp = mode->hsync_start - mode->hdisplay; + const u_int vspw = mode->vsync_end - mode->vsync_start; + const u_int vbp = mode->vtotal - mode->vsync_start; + const u_int vfp = mode->vsync_start - mode->vdisplay; + + /* Pixel clock */ + DC_WRITE(sc, DC_DISP_DISP_CLOCK_CONTROL_REG, 0); + + /* Mode timings */ + DC_WRITE(sc, DC_DISP_REF_TO_SYNC_REG, + __SHIFTIN(1, DC_DISP_REF_TO_SYNC_V) | + __SHIFTIN(1, DC_DISP_REF_TO_SYNC_H)); + DC_WRITE(sc, DC_DISP_SYNC_WIDTH_REG, + __SHIFTIN(vspw, DC_DISP_SYNC_WIDTH_V) | + __SHIFTIN(hspw, DC_DISP_SYNC_WIDTH_H)); + DC_WRITE(sc, DC_DISP_BACK_PORCH_REG, + __SHIFTIN(vbp, DC_DISP_BACK_PORCH_V) | + __SHIFTIN(hbp, DC_DISP_BACK_PORCH_H)); + DC_WRITE(sc, DC_DISP_FRONT_PORCH_REG, + __SHIFTIN(vfp, DC_DISP_FRONT_PORCH_V) | + __SHIFTIN(hfp, DC_DISP_FRONT_PORCH_H)); + DC_WRITE(sc, DC_DISP_DISP_ACTIVE_REG, + __SHIFTIN(mode->vdisplay, DC_DISP_DISP_ACTIVE_V) | + __SHIFTIN(mode->hdisplay, DC_DISP_DISP_ACTIVE_H)); + + /* Enable continus display mode */ + DC_SET_CLEAR(sc, DC_CMD_DISPLAY_COMMAND_REG, + __SHIFTIN(DC_CMD_DISPLAY_COMMAND_DISPLAY_CTRL_MODE_C_DISPLAY, + DC_CMD_DISPLAY_COMMAND_DISPLAY_CTRL_MODE), + DC_CMD_DISPLAY_COMMAND_DISPLAY_CTRL_MODE); + + /* Enable power */ + DC_SET_CLEAR(sc, DC_CMD_DISPLAY_POWER_CONTROL_REG, + DC_CMD_DISPLAY_POWER_CONTROL_PM1_ENABLE | + DC_CMD_DISPLAY_POWER_CONTROL_PM0_ENABLE | + DC_CMD_DISPLAY_POWER_CONTROL_PW4_ENABLE | + DC_CMD_DISPLAY_POWER_CONTROL_PW3_ENABLE | + DC_CMD_DISPLAY_POWER_CONTROL_PW2_ENABLE | + DC_CMD_DISPLAY_POWER_CONTROL_PW1_ENABLE | + DC_CMD_DISPLAY_POWER_CONTROL_PW0_ENABLE, + 0); +} + +static void +tegra_dc_update(struct tegra_dc_softc *sc) +{ + /* Commit settings */ + DC_WRITE(sc, DC_CMD_STATE_CONTROL_REG, + DC_CMD_STATE_CONTROL_GENERAL_UPDATE); + DC_WRITE(sc, DC_CMD_STATE_CONTROL_REG, + DC_CMD_STATE_CONTROL_GENERAL_ACT_REQ); +} + +int +tegra_dc_port(device_t dev) +{ + struct tegra_dc_softc * const sc = device_private(dev); + + return sc->sc_port; +} + +int +tegra_dc_enable(device_t dev, device_t outputdev, + const struct videomode *mode) +{ + struct tegra_dc_softc * const sc = device_private(dev); + prop_dictionary_t prop = device_properties(dev); + bool is_console = false; + int error; + + KASSERT(sc->sc_fbdev == NULL); + + prop_dictionary_get_bool(prop, "is_console", &is_console); + + const uint32_t depth = TEGRA_DC_DEPTH; + const uint32_t fbsize = mode->vdisplay * mode->hdisplay * (depth / 8); + const bus_size_t dmasize = (fbsize + 3) & ~3; + error = tegra_dc_allocmem(sc, dmasize); + if (error) { + aprint_error_dev(dev, + "failed to allocate %u bytes of video memory: %d\n", + (u_int)dmasize, error); + return error; + } + + error = tegra_dc_init(sc, mode); + if (error) { + aprint_error_dev(dev, + "failed to initialize display controller: %d\n", error); + return error; + } + + struct tegrafb_attach_args tfb = { + .tfb_console = is_console, + .tfb_dmat = sc->sc_dmat, + .tfb_dmamap = sc->sc_dmamap, + .tfb_dmap = sc->sc_dmap, + .tfb_width = mode->hdisplay, + .tfb_height = mode->vdisplay, + .tfb_depth = depth, + .tfb_stride = mode->hdisplay * (depth / 8), + .tfb_outputdev = outputdev, + }; + + sc->sc_fbdev = config_found(sc->sc_dev, &tfb, tegra_dc_print); + + return 0; +} + +void +tegra_dc_hdmi_start(device_t dev) +{ + struct tegra_dc_softc * const sc = device_private(dev); + + DC_SET_CLEAR(sc, DC_DISP_DISP_WIN_OPTIONS_REG, + DC_DISP_DISP_WIN_OPTIONS_HDMI_ENABLE, 0); + + tegra_dc_update(sc); +} Index: src/sys/arch/arm/nvidia/tegra_dcreg.h diff -u /dev/null src/sys/arch/arm/nvidia/tegra_dcreg.h:1.1 --- /dev/null Mon May 18 19:32:48 2015 +++ src/sys/arch/arm/nvidia/tegra_dcreg.h Mon May 18 19:32:48 2015 @@ -0,0 +1,421 @@ +/* $NetBSD: tegra_dcreg.h,v 1.1 2015/05/18 19:32:48 jmcneill Exp $ */ + +/*- + * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. + */ + +#ifndef _ARM_TEGRA_DCREG_H +#define _ARM_TEGRA_DCREG_H + +/* + * Display CMD registers + */ +#define DC_CMD_GENERAL_INCR_SYNCPT_REG 0x000 +#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL_REG 0x004 +#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR_REG 0x008 +#define DC_CMD_WIN_A_INCR_SYNCPT_REG 0x020 +#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL_REG 0x024 +#define DC_CMD_WIN_A_INCR_SYNCPT_ERROR_REG 0x028 +#define DC_CMD_WIN_B_INCR_SYNCPT_REG 0x040 +#define DC_CMD_WIN_B_INCR_SYNCPT_CNTRL_REG 0x044 +#define DC_CMD_WIN_B_INCR_SYNCPT_ERROR_REG 0x048 +#define DC_CMD_WIN_C_INCR_SYNCPT_REG 0x060 +#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL_REG 0x064 +#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR_REG 0x068 +#define DC_CMD_CONT_SYNCPT_VSYNC_REG 0x0a0 +#define DC_CMD_CTXSW_REG 0x0c0 +#define DC_CMD_DISPLAY_COMMAND_OPTION0_REG 0x0c4 + +#define DC_CMD_DISPLAY_COMMAND_REG 0x0c8 +#define DC_CMD_DISPLAY_COMMAND_RAISE_CHANNEL_ID __BITS(30,27) +#define DC_CMD_DISPLAY_COMMAND_RAISE_VECTOR __BITS(26,22) +#define DC_CMD_DISPLAY_COMMAND_DISPLAY_CTRL_MODE __BITS(6,5) +#define DC_CMD_DISPLAY_COMMAND_DISPLAY_CTRL_MODE_STOP 0 +#define DC_CMD_DISPLAY_COMMAND_DISPLAY_CTRL_MODE_C_DISPLAY 1 +#define DC_CMD_DISPLAY_COMMAND_DISPLAY_CTRL_MODE_NC_DISPLAY 2 +#define DC_CMD_DISPLAY_COMMAND_RAISE __BIT(0) + +#define DC_CMD_SIGNAL_RAISE_REG 0x0cc + +#define DC_CMD_DISPLAY_POWER_CONTROL_REG 0x0d8 +#define DC_CMD_DISPLAY_POWER_CONTROL_HSPI_ENABLE __BIT(25) +#define DC_CMD_DISPLAY_POWER_CONTROL_SPI_ENABLE __BIT(24) +#define DC_CMD_DISPLAY_POWER_CONTROL_PM1_ENABLE __BIT(18) +#define DC_CMD_DISPLAY_POWER_CONTROL_PM0_ENABLE __BIT(16) +#define DC_CMD_DISPLAY_POWER_CONTROL_PW4_ENABLE __BIT(8) +#define DC_CMD_DISPLAY_POWER_CONTROL_PW3_ENABLE __BIT(6) +#define DC_CMD_DISPLAY_POWER_CONTROL_PW2_ENABLE __BIT(4) +#define DC_CMD_DISPLAY_POWER_CONTROL_PW1_ENABLE __BIT(2) +#define DC_CMD_DISPLAY_POWER_CONTROL_PW0_ENABLE __BIT(0) + +#define DC_CMD_INT_STATUS_REG 0x0dc +#define DC_CMD_INT_MASK_REG 0x0e0 +#define DC_CMD_INT_ENABLE_REG 0x0e4 +#define DC_CMD_INT_TYPE_REG 0x0e8 +#define DC_CMD_INT_POLARITY_REG 0x0ec +#define DC_CMD_SIGNAL_RAISE1_REG 0x0f0 +#define DC_CMD_SIGNAL_RAISE2_REG 0x0f4 +#define DC_CMD_SIGNAL_RAISE3_REG 0x0f8 +#define DC_CMD_STATE_ACCESS_REG 0x100 + +#define DC_CMD_STATE_CONTROL_REG 0x104 +#define DC_CMD_STATE_CONTROL_NC_HOST_TRIG_ENABLE __BIT(24) +#define DC_CMD_STATE_CONTROL_CURSOR_UPDATE __BIT(15) +#define DC_CMD_STATE_CONTROL_WIN_D_UPDATE __BIT(12) +#define DC_CMD_STATE_CONTROL_WIN_C_UPDATE __BIT(11) +#define DC_CMD_STATE_CONTROL_WIN_B_UPDATE __BIT(10) +#define DC_CMD_STATE_CONTROL_WIN_A_UPDATE __BIT(9) +#define DC_CMD_STATE_CONTROL_GENERAL_UPDATE __BIT(8) +#define DC_CMD_STATE_CONTROL_CURSOR_ACT_REQ __BIT(7) +#define DC_CMD_STATE_CONTROL_WIN_D_ACT_REQ __BIT(4) +#define DC_CMD_STATE_CONTROL_WIN_C_ACT_REQ __BIT(3) +#define DC_CMD_STATE_CONTROL_WIN_B_ACT_REQ __BIT(2) +#define DC_CMD_STATE_CONTROL_WIN_A_ACT_REQ __BIT(1) +#define DC_CMD_STATE_CONTROL_GENERAL_ACT_REQ __BIT(0) + +#define DC_CMD_DISPLAY_WINDOW_HEADER_REG 0x108 +#define DC_CMD_DISPLAY_WINDOW_HEADER_WINDOW_D_SELECT __BIT(7) +#define DC_CMD_DISPLAY_WINDOW_HEADER_WINDOW_C_SELECT __BIT(6) +#define DC_CMD_DISPLAY_WINDOW_HEADER_WINDOW_B_SELECT __BIT(5) +#define DC_CMD_DISPLAY_WINDOW_HEADER_WINDOW_A_SELECT __BIT(4) + +#define DC_CMD_REG_ACT_CONTROL_REG 0x10c +#define DC_CMD_WIN_T_STATE_CONTROL_REG 0x110 +#define DC_CMD_SECURE_CONTROL_REG 0x114 +#define DC_CMD_WIN_D_INCR_SYNCPT_REG 0x130 +#define DC_CMD_WIN_D_INCR_SYNCPT_CNTRL_REG 0x134 +#define DC_CMD_WIN_D_INCR_SYNCPT_ERROR_REG 0x138 + +/* + * Display COM registers + */ +#define DC_COM_CRC_CONTROL_REG 0xc00 +#define DC_COM_CRC_CHECKSUM_REG 0xc04 +#define DC_COM_PIN_MISC_CONTROL_REG 0xc6c +#define DC_COM_PM0_CONTROL_REG 0xc70 +#define DC_COM_PM0_DUTY_CYCLE_REG 0xc74 +#define DC_COM_SCRATCH_REGISTER_A_REG 0xc94 +#define DC_COM_SCRATCH_REGISTER_B_REG 0xc98 +#define DC_COM_CRC_CHECKSUM_LATCHED_REG 0xca4 +#define DC_COM_CMU_CSC_KRR_REG 0xca8 +#define DC_COM_CMU_CSC_KGR_REG 0xcac +#define DC_COM_CMU_CSC_KBR_REG 0xcb0 +#define DC_COM_CMU_CSC_KRG_REG 0xcb4 +#define DC_COM_CMU_CSC_KGG_REG 0xcb8 +#define DC_COM_CMU_CSC_KBG_REG 0xcbc +#define DC_COM_CMU_CSC_KRB_REG 0xcc0 +#define DC_COM_CMU_CSC_KGB_REG 0xcc4 +#define DC_COM_CMU_CSC_KBB_REG 0xcc8 +#define DC_COM_CMU_LUT_MASK_REG 0xccc +#define DC_COM_CMU_LUT1_REG 0xcd8 +#define DC_COM_CMU_LUT2_REG 0xcdc + +/* + * Display DISP registers + */ +#define DC_DISP_DISP_SIGNAL_OPTIONS0_REG 0x1000 + +#define DC_DISP_DISP_WIN_OPTIONS_REG 0x1008 +#define DC_DISP_DISP_WIN_OPTIONS_HDMI_ENABLE __BIT(30) +#define DC_DISP_DISP_WIN_OPTIONS_DSI_ENABLE __BIT(29) +#define DC_DISP_DISP_WIN_OPTIONS_SOR_ENABLE __BIT(28) +#define DC_DISP_DISP_WIN_OPTIONS_CURSOR_ENABLE __BIT(16) + +#define DC_DISP_DISP_TIMING_OPTIONS_REG 0x1014 + +#define DC_DISP_REF_TO_SYNC_REG 0x1018 +#define DC_DISP_REF_TO_SYNC_V __BITS(28,16) +#define DC_DISP_REF_TO_SYNC_H __BITS(12,0) + +#define DC_DISP_SYNC_WIDTH_REG 0x101c +#define DC_DISP_SYNC_WIDTH_V __BITS(28,16) +#define DC_DISP_SYNC_WIDTH_H __BITS(12,0) + +#define DC_DISP_BACK_PORCH_REG 0x1020 +#define DC_DISP_BACK_PORCH_V __BITS(28,16) +#define DC_DISP_BACK_PORCH_H __BITS(12,0) + +#define DC_DISP_DISP_ACTIVE_REG 0x1024 +#define DC_DISP_DISP_ACTIVE_V __BITS(28,16) +#define DC_DISP_DISP_ACTIVE_H __BITS(12,0) + +#define DC_DISP_FRONT_PORCH_REG 0x1028 +#define DC_DISP_FRONT_PORCH_V __BITS(28,16) +#define DC_DISP_FRONT_PORCH_H __BITS(12,0) + +#define DC_DISP_H_PULSE0_CONTROL_REG 0x102c +#define DC_DISP_H_PULSE0_POSITION_A_REG 0x1030 +#define DC_DISP_H_PULSE0_POSITION_B_REG 0x1034 +#define DC_DISP_H_PULSE0_POSITION_C_REG 0x1038 +#define DC_DISP_H_PULSE0_POSITION_D_REG 0x103c +#define DC_DISP_H_PULSE1_CONTROL_REG 0x1040 +#define DC_DISP_H_PULSE1_POSITION_A_REG 0x1044 +#define DC_DISP_H_PULSE1_POSITION_B_REG 0x1048 +#define DC_DISP_H_PULSE1_POSITION_C_REG 0x104c +#define DC_DISP_H_PULSE1_POSITION_D_REG 0x1050 +#define DC_DISP_H_PULSE2_CONTROL_REG 0x1054 +#define DC_DISP_H_PULSE2_POSITION_A_REG 0x1058 +#define DC_DISP_H_PULSE2_POSITION_B_REG 0x105c +#define DC_DISP_H_PULSE2_POSITION_C_REG 0x1060 +#define DC_DISP_H_PULSE2_POSITION_D_REG 0x1064 +#define DC_DISP_V_PULSE0_CONTROL_REG 0x1068 +#define DC_DISP_V_PULSE0_POSITION_A_REG 0x106c +#define DC_DISP_V_PULSE0_POSITION_B_REG 0x1070 +#define DC_DISP_V_PULSE0_POSITION_C_REG 0x1074 +#define DC_DISP_V_PULSE1_CONTROL_REG 0x1078 +#define DC_DISP_V_PULSE1_POSITION_A_REG 0x107c +#define DC_DISP_V_PULSE1_POSITION_B_REG 0x1080 +#define DC_DISP_V_PULSE1_POSITION_C_REG 0x1084 +#define DC_DISP_V_PULSE2_CONTROL_REG 0x1088 +#define DC_DISP_V_PULSE2_POSITION_A_REG 0x108c +#define DC_DISP_V_PULSE3_CONTROL_REG 0x1090 +#define DC_DISP_V_PULSE3_POSITION_A_REG 0x1094 +#define DC_DISP_DISP_CLOCK_CONTROL_REG 0x10b8 +#define DC_DISP_DISP_INTERFACE_CONTROL_REG 0x10bc +#define DC_DISP_DISP_COLOR_CONTROL_REG 0x10c0 +#define DC_DISP_COLOR_KEY0_LOWER_REG 0x10d8 +#define DC_DISP_COLOR_KEY0_UPPER_REG 0x10dc +#define DC_DISP_COLOR_KEY1_LOWER_REG 0x10e0 +#define DC_DISP_COLOR_KEY1_UPPER_REG 0x10e4 +#define DC_DISP_CURSOR_FOREGROUND_REG 0x10f0 +#define DC_DISP_CURSOR_BACKGROUND_REG 0x10f4 +#define DC_DISP_CURSOR_START_ADDR_REG 0x10f8 +#define DC_DISP_CURSOR_START_ADDR_NS_REG 0x10fc +#define DC_DISP_CURSOR_POSITION_REG 0x1100 +#define DC_DISP_CURSOR_POSITION_NS_REG 0x1104 +#define DC_DISP_DC_MCCIF_FIFOCTRL_REG 0x1200 +#define DC_DISP_MCCIF_DISPLAY0A_HYST_REG 0x1204 +#define DC_DISP_MCCIF_DISPLAY0B_HYST_REG 0x1208 +#define DC_DISP_MCCIF_DISPLAY0C_HYST_REG 0x120c +#define DC_DISP_DISP_MISC_CONTROL_REG 0x1304 +#define DC_DISP_SD_CONTROL_REG 0x1308 +#define DC_DISP_SD_CSC_COEFF_REG 0x130c +#define DC_DISP_SD_LUT_REG 0x1310 +#define DC_DISP_SD_FLICKER_CONTROL_REG 0x1334 +#define DC_DISP_SD_PIXEL_COUNT_REG 0x1338 +#define DC_DISP_SD_HISTOGRAM_REG 0x133c +#define DC_DISP_SD_BL_PARAMETERS_REG 0x135c +#define DC_DISP_SD_BL_TF_REG 0x1360 +#define DC_DISP_SD_BL_CONTROL_REG 0x1370 +#define DC_DISP_SD_HW_K_VALUES_REG 0x1374 +#define DC_DISP_SD_MAN_K_VALUES_REG 0x1378 +#define DC_DISP_SD_K_LIMIT_REG 0x137c +#define DC_DISP_SD_WINDOW_POSITION_REG 0x1380 +#define DC_DISP_SD_WINDOW_SIZE_REG 0x1384 +#define DC_DISP_SD_SOFT_CLIPPING_REG 0x1388 +#define DC_DISP_SD_SMOOTH_K_REG 0x138c +#define DC_DISP_BLEND_BACKGROUND_COLOR_REG 0x1390 +#define DC_DISP_INTERLACE_CONTROL_REG 0x1394 +#define DC_DISP_INTERLACE_FIELD2_REF_TO_SYNC_REG 0x1398 +#define DC_DISP_INTERLACE_FIELD2_SYNC_WIDTH_REG 0x139c +#define DC_DISP_INTERLACE_FIELD2_BACK_PORCH_REG 0x13a0 +#define DC_DISP_INTERLACE_FIELD2_FRONT_PORCH_REG 0x13a4 +#define DC_DISP_INTERLACE_FIELD2_DISP_ACTIVE_REG 0x13a8 +#define DC_DISP_CURSOR_UNDERFLOW_CTRL_REG 0x13ac +#define DC_DISP_CURSOR_START_ADDR_HI_REG 0x13b0 +#define DC_DISP_CURSOR_START_ADDR_HI_NS_REG 0x13b4 +#define DC_DISP_CURSOR_INTERLACE_CONTROL_REG 0x13b8 +#define DC_DISP_CSC2_CONTROL_REG 0x13bc +#define DC_DISP_BLEND_CURSOR_CONTROL_REG 0x13c4 +#define DC_DISP_DVFS_CURSOR_CONTROL_REG 0x13c8 +#define DC_DISP_CURSOR_UFLOW_DBG_PIXEL_REG 0x13cc +#define DC_DISP_CURSOR_SPOOLUP_CONTROL_REG 0x13d0 +#define DC_DISP_DISPLAY_CLK_GATE_OVERRIDE_REG 0x13d4 +#define DC_DISP_DISPLAY_DBG_TIMING_REG 0x13d8 +#define DC_DISP_DISPLAY_SPARE0_REG 0x13dc +#define DC_DISP_DISPLAY_SPARE1_REG 0x13e0 + +/* + * Window A registers + */ +#define DC_WINC_A_COLOR_PALETTE_REG 0x1400 +#define DC_WINC_A_PALETTE_COLOR_EXT_REG 0x1800 +#define DC_WINC_A_H_FILTER_P00_REG 0x1804 +#define DC_WINC_A_H_FILTER_P01_REG 0x1808 +#define DC_WINC_A_H_FILTER_P02_REG 0x180c +#define DC_WINC_A_H_FILTER_P03_REG 0x1810 +#define DC_WINC_A_H_FILTER_P04_REG 0x1814 +#define DC_WINC_A_H_FILTER_P05_REG 0x1818 +#define DC_WINC_A_H_FILTER_P06_REG 0x181c +#define DC_WINC_A_H_FILTER_P07_REG 0x1820 +#define DC_WINC_A_H_FILTER_P08_REG 0x1824 +#define DC_WINC_A_H_FILTER_P09_REG 0x1828 +#define DC_WINC_A_H_FILTER_P0A_REG 0x182c +#define DC_WINC_A_H_FILTER_P0B_REG 0x1830 +#define DC_WINC_A_H_FILTER_P0C_REG 0x1834 +#define DC_WINC_A_H_FILTER_P0D_REG 0x1838 +#define DC_WINC_A_H_FILTER_P0E_REG 0x183c +#define DC_WINC_A_H_FILTER_P0F_REG 0x1840 +#define DC_WINC_A_CSC_YOF_REG 0x1844 +#define DC_WINC_A_CSC_KYRGB_REG 0x1848 +#define DC_WINC_A_CSC_KUR_REG 0x184c +#define DC_WINC_A_CSC_KVR_REG 0x1850 +#define DC_WINC_A_CSC_KUG_REG 0x1854 +#define DC_WINC_A_CSC_KVG_REG 0x1858 +#define DC_WINC_A_CSC_KUB_REG 0x185c +#define DC_WINC_A_CSC_KVB_REG 0x1860 +#define DC_WINC_A_V_FILTER_P00_REG 0x1864 +#define DC_WINC_A_V_FILTER_P01_REG 0x1868 +#define DC_WINC_A_V_FILTER_P02_REG 0x186c +#define DC_WINC_A_V_FILTER_P03_REG 0x1870 +#define DC_WINC_A_V_FILTER_P04_REG 0x1874 +#define DC_WINC_A_V_FILTER_P05_REG 0x1878 +#define DC_WINC_A_V_FILTER_P06_REG 0x187c +#define DC_WINC_A_V_FILTER_P07_REG 0x1880 +#define DC_WINC_A_V_FILTER_P08_REG 0x1884 +#define DC_WINC_A_V_FILTER_P09_REG 0x1888 +#define DC_WINC_A_V_FILTER_P0A_REG 0x188c +#define DC_WINC_A_V_FILTER_P0B_REG 0x1890 +#define DC_WINC_A_V_FILTER_P0C_REG 0x1894 +#define DC_WINC_A_V_FILTER_P0D_REG 0x1898 +#define DC_WINC_A_V_FILTER_P0E_REG 0x189c +#define DC_WINC_A_V_FILTER_P0F_REG 0x18a0 +#define DC_WINC_A_H_FILTER_HI_P00_REG 0x18a4 +#define DC_WINC_A_H_FILTER_HI_P01_REG 0x18a8 +#define DC_WINC_A_H_FILTER_HI_P02_REG 0x18ac +#define DC_WINC_A_H_FILTER_HI_P03_REG 0x18b0 +#define DC_WINC_A_H_FILTER_HI_P04_REG 0x18b4 +#define DC_WINC_A_H_FILTER_HI_P05_REG 0x18b8 +#define DC_WINC_A_H_FILTER_HI_P06_REG 0x18bc +#define DC_WINC_A_H_FILTER_HI_P07_REG 0x18c0 +#define DC_WINC_A_H_FILTER_HI_P08_REG 0x18c4 +#define DC_WINC_A_H_FILTER_HI_P09_REG 0x18c8 +#define DC_WINC_A_H_FILTER_HI_P0A_REG 0x18cc +#define DC_WINC_A_H_FILTER_HI_P0B_REG 0x18d0 +#define DC_WINC_A_H_FILTER_HI_P0C_REG 0x18d4 +#define DC_WINC_A_H_FILTER_HI_P0D_REG 0x18d8 +#define DC_WINC_A_H_FILTER_HI_P0E_REG 0x18dc +#define DC_WINC_A_H_FILTER_HI_P0F_REG 0x18e0 + +#define DC_WINC_A_WIN_OPTIONS_REG 0x1c00 +#define DC_WINC_A_WIN_OPTIONS_H_FILTER_MODE __BIT(31) +#define DC_WINC_A_WIN_OPTIONS_WIN_ENABLE __BIT(30) +#define DC_WINC_A_WIN_OPTIONS_INTERLACE_ENABLE __BIT(23) +#define DC_WINC_A_WIN_OPTIONS_YUV_RANGE_EXPAND __BIT(22) +#define DC_WINC_A_WIN_OPTIONS_DV_ENABLE __BIT(20) +#define DC_WINC_A_WIN_OPTIONS_CSC_ENABLE __BIT(18) +#define DC_WINC_A_WIN_OPTIONS_CP_ENABLE __BIT(16) +#define DC_WINC_A_WIN_OPTIONS_V_FILTER_UV_ALIGN __BIT(14) +#define DC_WINC_A_WIN_OPTIONS_V_FILTER_OPTIMIZE __BIT(12) +#define DC_WINC_A_WIN_OPTIONS_V_FILTER_ENABLE __BIT(10) +#define DC_WINC_A_WIN_OPTIONS_H_FILTER_ENABLE __BIT(8) +#define DC_WINC_A_WIN_OPTIONS_COLOR_EXPAND __BIT(6) +#define DC_WINC_A_WIN_OPTIONS_SCAN_COLUMN __BIT(4) +#define DC_WINC_A_WIN_OPTIONS_V_DIRECTION __BIT(2) +#define DC_WINC_A_WIN_OPTIONS_H_DIRECTION __BIT(0) + +#define DC_WINC_A_BYTE_SWAP_REG 0x1c04 +#define DC_WINC_A_BYTE_SWAP_SWAP __BITS(2,0) +#define DC_WINC_A_BYTE_SWAP_SWAP_NOSWAP 0 + +#define DC_WINC_A_COLOR_DEPTH_REG 0x1c0c +#define DC_WINC_A_COLOR_DEPTH_DEPTH __BITS(6,0) +#define DC_WINC_A_COLOR_DEPTH_DEPTH_T_A8R8G8B8 12 + +#define DC_WINC_A_POSITION_REG 0x1c10 +#define DC_WINC_A_POSITION_V __BITS(28,16) +#define DC_WINC_A_POSITION_H __BITS(12,0) + +#define DC_WINC_A_SIZE_REG 0x1c14 +#define DC_WINC_A_SIZE_V __BITS(28,16) +#define DC_WINC_A_SIZE_H __BITS(12,0) + +#define DC_WINC_A_PRESCALED_SIZE_REG 0x1c18 +#define DC_WINC_A_PRESCALED_SIZE_V __BITS(28,16) +#define DC_WINC_A_PRESCALED_SIZE_H __BITS(14,0) + +#define DC_WINC_A_H_INITIAL_DDA_REG 0x1c1c +#define DC_WINC_A_V_INITIAL_DDA_REG 0x1c20 +#define DC_WINC_A_DDA_INCREMENT_REG 0x1c24 + +#define DC_WINC_A_LINE_STRIDE_REG 0x1c28 +#define DC_WINC_A_LINE_STRIDE_UV_LINE_STRIDE __BITS(31,16) +#define DC_WINC_A_LINE_STRIDE_LINE_STRIDE __BITS(15,0) + +#define DC_WINC_A_DV_CONTROL_REG 0x1c38 +#define DC_WINC_A_BLEND_LAYER_CONTROL_REG 0x1c58 +#define DC_WINC_A_BLEND_MATCH_SELECT_REG 0x1c5c +#define DC_WINC_A_BLEND_NOMATCH_SELECT_REG 0x1c60 +#define DC_WINC_A_BLEND_ALPHA_1BIT_REG 0x1c64 + +/* + * WINBUF_A registers + */ +#define DC_WINBUF_A_START_ADDR_REG 0x2000 +#define DC_WINBUF_A_START_ADDR_NS_REG 0x2004 +#define DC_WINBUF_A_START_ADDR_U_REG 0x2008 +#define DC_WINBUF_A_START_ADDR_U_NS_REG 0x200c +#define DC_WINBUF_A_START_ADDR_V_REG 0x2010 +#define DC_WINBUF_A_START_ADDR_V_NS_REG 0x2014 +#define DC_WINBUF_A_ADDR_H_OFFSET_REG 0x2018 +#define DC_WINBUF_A_ADDR_H_OFFSET_NS_REG 0x201c +#define DC_WINBUF_A_ADDR_V_OFFSET_REG 0x2020 +#define DC_WINBUF_A_ADDR_V_OFFSET_NS_REG 0x2024 +#define DC_WINBUF_A_UFLOW_STATUS_REG 0x2028 + +#define DC_WINBUF_A_SURFACE_KIND_REG 0x202c +#define DC_WINBUF_A_SURFACE_KIND_BLOCK_HEIGHT __BITS(6,4) +#define DC_WINBUF_A_SURFACE_KIND_SURFACE_KIND __BITS(1,0) +#define DC_WINBUF_A_SURFACE_KIND_SURFACE_KIND_PITCH 0 +#define DC_WINBUF_A_SURFACE_KIND_SURFACE_KIND_TILED 1 +#define DC_WINBUF_A_SURFACE_KIND_SURFACE_KIND_BL_16B2 2 + +#define DC_WINBUF_A_SURFACE_WEIGHT_REG 0x2030 +#define DC_WINBUF_A_START_ADDR_HI_REG 0x2034 +#define DC_WINBUF_A_START_ADDR_HI_NS_REG 0x2038 +#define DC_WINBUF_A_START_ADDR_HI_U_REG 0x203c +#define DC_WINBUF_A_START_ADDR_HI_U_NS_REG 0x2040 +#define DC_WINBUF_A_START_ADDR_HI_V_REG 0x2044 +#define DC_WINBUF_A_START_ADDR_HI_V_NS_REG 0x2048 +#define DC_WINBUF_A_START_ADDR_FIELD2_REG 0x204c +#define DC_WINBUF_A_START_ADDR_FIELD2_NS_REG 0x2050 +#define DC_WINBUF_A_START_ADDR_FIELD2_U_REG 0x2054 +#define DC_WINBUF_A_START_ADDR_FIELD2_U_NS_REG 0x2058 +#define DC_WINBUF_A_START_ADDR_FIELD2_V_REG 0x205c +#define DC_WINBUF_A_START_ADDR_FIELD2_V_NS_REG 0x2060 +#define DC_WINBUF_A_START_ADDR_FIELD2_HI_REG 0x2064 +#define DC_WINBUF_A_START_ADDR_FIELD2_HI_NS_REG 0x2068 +#define DC_WINBUF_A_START_ADDR_FIELD2_HI_U_REG 0x206c +#define DC_WINBUF_A_START_ADDR_FIELD2_HI_U_NS_REG 0x2070 +#define DC_WINBUF_A_START_ADDR_FIELD2_HI_V_REG 0x2074 +#define DC_WINBUF_A_START_ADDR_FIELD2_HI_V_NS_REG 0x2078 +#define DC_WINBUF_A_ADDR_H_OFFSET_FIELD2_REG 0x207c +#define DC_WINBUF_A_ADDR_H_OFFSET_FIELD2_NS_REG 0x2080 +#define DC_WINBUF_A_ADDR_V_OFFSET_FIELD2_REG 0x2084 +#define DC_WINBUF_A_ADDR_V_OFFSET_FIELD2_NS_REG 0x2088 +#define DC_WINBUF_A_UFLOW_CTRL_REG 0x2090 +#define DC_WINBUF_A_UFLOW_DBG_PIXEL_REG 0x2094 +#define DC_WINBUF_A_UFLOW_THRESHOLD_REG 0x2098 +#define DC_WINBUF_A_SPOOL_UP_REG 0x209c +#define DC_WINBUF_A_SCALEFACTOR_THRESHOLD_REG 0x20a0 +#define DC_WINBUF_A_LATENCY_THRESHOLD_REG 0x20a4 +#define DC_WINBUF_A_MEMFETCH_DEBUG_STATUS_REG 0x20a8 +#define DC_WINBUF_A_MEMFETCH_CONTROL_REG 0x20ac +#define DC_WINBUF_A_OCCUPANCY_THROTTLE_REG 0x20b0 +#define DC_WINBUF_A_SCRATCH_REGISTER_0_REG 0x20b4 +#define DC_WINBUF_A_SCRATCH_REGISTER_1_REG 0x20b8 + + +#endif /* _ARM_TEGRA_DCREG_H */ Index: src/sys/arch/arm/nvidia/tegra_genfb.c diff -u /dev/null src/sys/arch/arm/nvidia/tegra_genfb.c:1.1 --- /dev/null Mon May 18 19:32:48 2015 +++ src/sys/arch/arm/nvidia/tegra_genfb.c Mon May 18 19:32:48 2015 @@ -0,0 +1,191 @@ +/* $NetBSD: tegra_genfb.c,v 1.1 2015/05/18 19:32:48 jmcneill Exp $ */ + +/*- + * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. + */ + +#include "locators.h" + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: tegra_genfb.c,v 1.1 2015/05/18 19:32:48 jmcneill Exp $"); + +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/kernel.h> + +#if defined(DDB) +#include <machine/db_machdep.h> +#include <ddb/db_extern.h> +#endif + +#include <dev/wsfb/genfbvar.h> + +#include <arm/nvidia/tegra_reg.h> +#include <arm/nvidia/tegra_var.h> + +static int tegra_genfb_match(device_t, cfdata_t, void *); +static void tegra_genfb_attach(device_t, device_t, void *); + +struct tegra_genfb_softc { + struct genfb_softc sc_gen; + bus_dma_tag_t sc_dmat; + bus_dmamap_t sc_dmamap; +}; + +static int tegra_genfb_ioctl(void *, void *, u_long, void *, int, lwp_t *); +static paddr_t tegra_genfb_mmap(void *, void *, off_t, int); +static bool tegra_genfb_shutdown(device_t, int); + +#if defined(DDB) +static void tegra_genfb_ddb_trap_callback(int); +static device_t tegra_genfb_consoledev = NULL; +#endif + +CFATTACH_DECL_NEW(tegra_genfb, sizeof(struct tegra_genfb_softc), + tegra_genfb_match, tegra_genfb_attach, NULL, NULL); + +static int +tegra_genfb_match(device_t parent, cfdata_t cf, void *aux) +{ + return 1; +} + +static void +tegra_genfb_attach(device_t parent, device_t self, void *aux) +{ + struct tegra_genfb_softc * const sc = device_private(self); + struct tegrafb_attach_args * const tfb = aux; + prop_dictionary_t prop = device_properties(self); + const bool is_console = tfb->tfb_console; + struct genfb_ops ops; + + sc->sc_gen.sc_dev = self; + sc->sc_dmat = tfb->tfb_dmat; + sc->sc_dmamap = tfb->tfb_dmamap; + + prop_dictionary_set_bool(prop, "is_console", is_console); + prop_dictionary_set_uint32(prop, "width", tfb->tfb_width); + prop_dictionary_set_uint32(prop, "height", tfb->tfb_height); + prop_dictionary_set_uint8(prop, "depth", tfb->tfb_depth); + prop_dictionary_set_uint32(prop, "linebytes", tfb->tfb_stride); + prop_dictionary_set_uint64(prop, "address", + tfb->tfb_dmamap->dm_segs[0].ds_addr); + prop_dictionary_set_uint64(prop, "virtual_address", + (uintptr_t)tfb->tfb_dmap); + + genfb_init(&sc->sc_gen); + if (sc->sc_gen.sc_width == 0 || sc->sc_gen.sc_fbsize == 0) { + aprint_error(": disabled\n"); + return; + } + + pmf_device_register1(self, NULL, NULL, tegra_genfb_shutdown); + + aprint_naive("\n"); + if (is_console) { + aprint_normal(": switching to framebuffer console\n"); + } else { + aprint_normal("\n"); + } + + memset(&ops, 0, sizeof(ops)); + ops.genfb_ioctl = tegra_genfb_ioctl; + ops.genfb_mmap = tegra_genfb_mmap; + genfb_attach(&sc->sc_gen, &ops); + +#if defined(DDB) + if (is_console) { + tegra_genfb_consoledev = self; + db_trap_callback = tegra_genfb_ddb_trap_callback; + } +#endif + +} + +static int +tegra_genfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l) +{ + struct tegra_genfb_softc * const sc = v; + struct wsdisplayio_bus_id *busid; + struct wsdisplayio_fbinfo *fbi; + struct rasops_info *ri = &sc->sc_gen.vd.active->scr_ri; + int error; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_TEGRA; + return 0; + case WSDISPLAYIO_GET_BUSID: + busid = data; + busid->bus_type = WSDISPLAYIO_BUS_SOC; + return 0; + case WSDISPLAYIO_GET_FBINFO: + fbi = data; + error = wsdisplayio_get_fbinfo(ri, fbi); + fbi->fbi_flags |= WSFB_VRAM_IS_RAM; + return error; + default: + return EPASSTHROUGH; + } +} + +static paddr_t +tegra_genfb_mmap(void *v, void *vs, off_t off, int prot) +{ + struct tegra_genfb_softc * const sc = v; + + if (off < 0 || off >= sc->sc_dmamap->dm_segs[0].ds_len) + return -1; + + return bus_dmamem_mmap(sc->sc_dmat, sc->sc_dmamap->dm_segs, 1, + off, prot, BUS_DMA_PREFETCHABLE); +} + +static bool +tegra_genfb_shutdown(device_t self, int flags) +{ + genfb_enable_polling(self); + return true; +} + +#if defined(DDB) +static void +tegra_genfb_ddb_trap_callback(int where) +{ + if (tegra_genfb_consoledev == NULL) + return; + + if (where) { + genfb_enable_polling(tegra_genfb_consoledev); + } else { + genfb_disable_polling(tegra_genfb_consoledev); + } +} +#endif Index: src/sys/arch/arm/nvidia/tegra_hdmi.c diff -u /dev/null src/sys/arch/arm/nvidia/tegra_hdmi.c:1.1 --- /dev/null Mon May 18 19:32:48 2015 +++ src/sys/arch/arm/nvidia/tegra_hdmi.c Mon May 18 19:32:48 2015 @@ -0,0 +1,352 @@ +/* $NetBSD: tegra_hdmi.c,v 1.1 2015/05/18 19:32:48 jmcneill Exp $ */ + +/*- + * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. + */ + +#include "locators.h" + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: tegra_hdmi.c,v 1.1 2015/05/18 19:32:48 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/kernel.h> + +#include <dev/i2c/i2cvar.h> +#include <dev/i2c/ddcvar.h> +#include <dev/videomode/videomode.h> +#include <dev/videomode/edidvar.h> + +#include <arm/nvidia/tegra_reg.h> +#include <arm/nvidia/tegra_hdmireg.h> +#include <arm/nvidia/tegra_var.h> + +static int tegra_hdmi_match(device_t, cfdata_t, void *); +static void tegra_hdmi_attach(device_t, device_t, void *); + +static const struct tegra_hdmi_tmds_config { + u_int dot_clock; + uint32_t sor_pll0; + uint32_t sor_pll1; + uint32_t sor_lane_drive_current; + uint32_t pe_current; + uint32_t sor_io_peak_current; + uint32_t sor_pad_ctls0; + uint32_t car_plld_misc; /* XXX unused? */ +} tegra_hdmi_tmds_config[] = { + /* 480p */ + { 27000, 0x01003010, 0x00301b00, 0x1f1f1f1f, + 0x00000000, 0x03030303, 0x800034bb, 0x40400820 }, + /* 720p / 1080i */ + { 74250, 0x01003110, 0x00301500, 0x2c2c2c2c, + 0x00000000, 0x07070707, 0x800034bb, 0x40400820 }, + /* 1080p */ + { 148500, 0x01003310, 0300301500, 0x33333333, + 0x00000000, 0x0c0c0c0c, 0x800034bb, 0x40400820 }, + /* 2160p */ + { 297000, 0x01003f10, 0x00300f00, 0x37373737, + 0x00000000, 0x17171717, 0x800036bb, 0x40400f20 }, +}; + +struct tegra_hdmi_softc { + device_t sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + + device_t sc_displaydev; + device_t sc_ddcdev; + struct tegra_gpio_pin *sc_pin_hpd; + struct tegra_gpio_pin *sc_pin_pll; + struct tegra_gpio_pin *sc_pin_power; + + bool sc_connected; + const struct videomode *sc_curmode; +}; + +static void tegra_hdmi_hpd(struct tegra_hdmi_softc *); +static void tegra_hdmi_connect(struct tegra_hdmi_softc *); +static void tegra_hdmi_disconnect(struct tegra_hdmi_softc *); +static void tegra_hdmi_enable(struct tegra_hdmi_softc *); +static int tegra_hdmi_sor_start(struct tegra_hdmi_softc *); + +CFATTACH_DECL_NEW(tegra_hdmi, sizeof(struct tegra_hdmi_softc), + tegra_hdmi_match, tegra_hdmi_attach, NULL, NULL); + +#define HDMI_READ(sc, reg) \ + bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) +#define HDMI_WRITE(sc, reg, val) \ + bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) +#define HDMI_SET_CLEAR(sc, reg, set, clr) \ + tegra_reg_set_clear((sc)->sc_bst, (sc)->sc_bsh, (reg), (set), (clr)) + +static int +tegra_hdmi_match(device_t parent, cfdata_t cf, void *aux) +{ + return 1; +} + +static void +tegra_hdmi_attach(device_t parent, device_t self, void *aux) +{ + struct tegra_hdmi_softc * const sc = device_private(self); + struct tegraio_attach_args * const tio = aux; + const struct tegra_locators * const loc = &tio->tio_loc; + prop_dictionary_t prop = device_properties(self); + const char *pin, *dev; + + sc->sc_dev = self; + sc->sc_bst = tio->tio_bst; + if (bus_space_map(sc->sc_bst, TEGRA_GHOST_BASE + loc->loc_offset, + loc->loc_size, 0, &sc->sc_bsh) != 0) { + aprint_error(": couldn't map HDMI\n"); + return; + } + + if (prop_dictionary_get_cstring_nocopy(prop, "hpd-gpio", &pin)) { + sc->sc_pin_hpd = tegra_gpio_acquire(pin, GPIO_PIN_INPUT); + } + if (prop_dictionary_get_cstring_nocopy(prop, "pll-gpio", &pin)) { + sc->sc_pin_pll = tegra_gpio_acquire(pin, GPIO_PIN_OUTPUT); + if (sc->sc_pin_pll) { + tegra_gpio_write(sc->sc_pin_pll, 0); + } + } + if (prop_dictionary_get_cstring_nocopy(prop, "power-gpio", &pin)) { + sc->sc_pin_power = tegra_gpio_acquire(pin, GPIO_PIN_OUTPUT); + if (sc->sc_pin_power) { + tegra_gpio_write(sc->sc_pin_power, 1); + } + } + if (prop_dictionary_get_cstring_nocopy(prop, "ddc-device", &dev)) { + sc->sc_ddcdev = device_find_by_xname(dev); + } + if (prop_dictionary_get_cstring_nocopy(prop, "display-device", &dev)) { + sc->sc_displaydev = device_find_by_xname(dev); + } + + if (sc->sc_displaydev == NULL) { + aprint_error(": no display-device property\n"); + return; + } + + aprint_naive("\n"); + aprint_normal(": HDMI\n"); + + tegra_hdmi_hpd(sc); +} + +static void +tegra_hdmi_hpd(struct tegra_hdmi_softc *sc) +{ + bool con; + + if (sc->sc_pin_hpd) { + con = tegra_gpio_read(sc->sc_pin_hpd); + } else { + con = true; + } + + if (sc->sc_connected == con) + return; + + if (con) { + device_printf(sc->sc_dev, "display connected\n"); + tegra_hdmi_connect(sc); + } else { + device_printf(sc->sc_dev, "display disconnected\n"); + tegra_hdmi_disconnect(sc); + } + + sc->sc_connected = con; +} + +static void +tegra_hdmi_connect(struct tegra_hdmi_softc *sc) +{ + const struct videomode *mode; + char edid[128]; + struct edid_info ei; + int retry = 4, error; + + if (sc->sc_ddcdev) { + memset(edid, 0, sizeof(edid)); + memset(&ei, 0, sizeof(ei)); + + while (--retry > 0) { + error = ddc_dev_read_edid(sc->sc_ddcdev, edid, + sizeof(edid)); + if (error == 0) { + break; + } + } + if (retry == 0) { + device_printf(sc->sc_dev, "failed to read EDID (%d)\n", + error); + } else { + if (edid_parse(edid, &ei) != 0) { + device_printf(sc->sc_dev, + "failed to parse EDID\n"); +#ifdef TEGRA_HDMI_DEBUG + } else { + edid_print(&ei); +#endif + } + } + } + + mode = ei.edid_preferred_mode; + if (mode == NULL) { + mode = pick_mode_by_ref(640, 480, 60); + } + + sc->sc_curmode = mode; + tegra_hdmi_enable(sc); +} + +static void +tegra_hdmi_disconnect(struct tegra_hdmi_softc *sc) +{ +} + +static void +tegra_hdmi_enable(struct tegra_hdmi_softc *sc) +{ + const struct tegra_hdmi_tmds_config *tmds = NULL; + const struct videomode *mode = sc->sc_curmode; + uint32_t input_ctrl; + u_int n; + + KASSERT(sc->sc_curmode != NULL); + + tegra_car_hdmi_enable(mode->dot_clock * 1000); + + for (n = 0; n < __arraycount(tegra_hdmi_tmds_config); n++) { + if (tegra_hdmi_tmds_config[n].dot_clock == mode->dot_clock) { + tmds = &tegra_hdmi_tmds_config[n]; + break; + } + } + if (tmds != NULL) { + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_PLL0_REG, tmds->sor_pll0); + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_PLL1_REG, tmds->sor_pll1); + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT_REG, + tmds->sor_lane_drive_current); + HDMI_WRITE(sc, HDMI_NV_PDISP_PE_CURRENT_REG, tmds->pe_current); + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT_REG, + tmds->sor_io_peak_current); + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_PAD_CTLS0_REG, + tmds->sor_pad_ctls0); + } + + tegra_dc_enable(sc->sc_displaydev, sc->sc_dev, mode); + + const u_int div = (mode->dot_clock / 1000) * 4; + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_REFCLK_REG, + __SHIFTIN(div >> 2, HDMI_NV_PDISP_SOR_REFCLK_DIV_INT) | + __SHIFTIN(div & 3, HDMI_NV_PDISP_SOR_REFCLK_DIV_FRAC)); + + HDMI_SET_CLEAR(sc, HDMI_NV_PDISP_SOR_CSTM_REG, + __SHIFTIN(HDMI_NV_PDISP_SOR_CSTM_MODE_TMDS, + HDMI_NV_PDISP_SOR_CSTM_MODE) | + HDMI_NV_PDISP_SOR_CSTM_PLLDIV, + HDMI_NV_PDISP_SOR_CSTM_MODE); + + input_ctrl = __SHIFTIN(tegra_dc_port(sc->sc_displaydev), + HDMI_NV_PDISP_INPUT_CONTROL_HDMI_SRC_SELECT); + if (mode->hdisplay != 640 || mode->vdisplay != 480) + input_ctrl |= HDMI_NV_PDISP_INPUT_CONTROL_ARM_VIDEO_RANGE; + HDMI_WRITE(sc, HDMI_NV_PDISP_INPUT_CONTROL_REG, input_ctrl); + + if (tegra_hdmi_sor_start(sc) != 0) + return; + + /* Start HDMI output */ + tegra_dc_hdmi_start(sc->sc_displaydev); +} + +static int +tegra_hdmi_sor_start(struct tegra_hdmi_softc *sc) +{ + int retry; + + HDMI_SET_CLEAR(sc, HDMI_NV_PDISP_SOR_PLL0_REG, + 0, + HDMI_NV_PDISP_SOR_PLL0_PWR | + HDMI_NV_PDISP_SOR_PLL0_VCOPD | + HDMI_NV_PDISP_SOR_PLL0_PULLDOWN); + delay(10); + HDMI_SET_CLEAR(sc, HDMI_NV_PDISP_SOR_PLL0_REG, + 0, + HDMI_NV_PDISP_SOR_PLL0_PDBG); + + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_PWR_REG, + HDMI_NV_PDISP_SOR_PWR_NORMAL_STATE | + HDMI_NV_PDISP_SOR_PWR_SETTING_NEW); + + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_PWR_REG, + HDMI_NV_PDISP_SOR_PWR_NORMAL_STATE); + + for (retry = 10000; retry > 0; retry--) { + const uint32_t pwr = HDMI_READ(sc, HDMI_NV_PDISP_SOR_PWR_REG); + if ((pwr & HDMI_NV_PDISP_SOR_PWR_SETTING_NEW) == 0) + break; + delay(10); + } + if (retry == 0) { + device_printf(sc->sc_dev, "timeout enabling SOR power\n"); + return ETIMEDOUT; + } + + uint32_t state2 = + __SHIFTIN(1, HDMI_NV_PDISP_SOR_STATE2_ASY_OWNER) | + __SHIFTIN(3, HDMI_NV_PDISP_SOR_STATE2_ASY_SUBOWNER) | + __SHIFTIN(1, HDMI_NV_PDISP_SOR_STATE2_ASY_PROTOCOL); + if (sc->sc_curmode->flags & VID_NHSYNC) + state2 |= HDMI_NV_PDISP_SOR_STATE2_ASY_HSYNCPOL; + if (sc->sc_curmode->flags & VID_NVSYNC) + state2 |= HDMI_NV_PDISP_SOR_STATE2_ASY_VSYNCPOL; + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_STATE2_REG, state2); + + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_STATE1_REG, + __SHIFTIN(HDMI_NV_PDISP_SOR_STATE1_ASY_HEAD_OPMODE_AWAKE, + HDMI_NV_PDISP_SOR_STATE1_ASY_HEAD_OPMODE) | + HDMI_NV_PDISP_SOR_STATE1_ASY_ORMODE); + + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_STATE0_REG, 0); + + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_STATE0_REG, + HDMI_NV_PDISP_SOR_STATE0_UPDATE); + + HDMI_SET_CLEAR(sc, HDMI_NV_PDISP_SOR_STATE1_REG, + HDMI_NV_PDISP_SOR_STATE1_ATTACHED, 0); + + HDMI_WRITE(sc, HDMI_NV_PDISP_SOR_STATE0_REG, 0); + + return 0; +} Index: src/sys/arch/arm/nvidia/tegra_hdmireg.h diff -u /dev/null src/sys/arch/arm/nvidia/tegra_hdmireg.h:1.1 --- /dev/null Mon May 18 19:32:48 2015 +++ src/sys/arch/arm/nvidia/tegra_hdmireg.h Mon May 18 19:32:48 2015 @@ -0,0 +1,280 @@ +/* $NetBSD: tegra_hdmireg.h,v 1.1 2015/05/18 19:32:48 jmcneill Exp $ */ + +/*- + * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. + */ + +#ifndef _ARM_TEGRA_HDMIREG_H +#define _ARM_TEGRA_HDMIREG_H + +/* + * HDMI Registers + */ +#define HDMI_CTXSW_REG 0x000 + +#define HDMI_NV_PDISP_SOR_STATE0_REG 0x004 +#define HDMI_NV_PDISP_SOR_STATE0_UPDATE __BIT(0) + +#define HDMI_NV_PDISP_SOR_STATE1_REG 0x008 +#define HDMI_NV_PDISP_SOR_STATE1_ARM_SHOW_VGA __BIT(4) +#define HDMI_NV_PDISP_SOR_STATE1_ATTACHED __BIT(3) +#define HDMI_NV_PDISP_SOR_STATE1_ASY_ORMODE __BIT(2) +#define HDMI_NV_PDISP_SOR_STATE1_ASY_HEAD_OPMODE __BITS(1,0) +#define HDMI_NV_PDISP_SOR_STATE1_ASY_HEAD_OPMODE_SLEEP 0 +#define HDMI_NV_PDISP_SOR_STATE1_ASY_HEAD_OPMODE_SNOOZE 1 +#define HDMI_NV_PDISP_SOR_STATE1_ASY_HEAD_OPMODE_AWAKE 2 + +#define HDMI_NV_PDISP_SOR_STATE2_REG 0x00c +#define HDMI_NV_PDISP_SOR_STATE2_ASY_DEPOL __BIT(14) +#define HDMI_NV_PDISP_SOR_STATE2_ASY_VSYNCPOL __BIT(13) +#define HDMI_NV_PDISP_SOR_STATE2_ASY_HSYNCPOL __BIT(12) +#define HDMI_NV_PDISP_SOR_STATE2_ASY_PROTOCOL __BITS(11,8) +#define HDMI_NV_PDISP_SOR_STATE2_ASY_CRCMODE __BITS(7,6) +#define HDMI_NV_PDISP_SOR_STATE2_ASY_SUBOWNER __BITS(5,4) +#define HDMI_NV_PDISP_SOR_STATE2_ASY_OWNER __BITS(3,0) + +#define HDMI_NV_PDISP_HDMI_AUDIO_EMU0_REG 0x068 +#define HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0_REG 0x06c +#define HDMI_NV_PDISP_HDMI_AUDIO_EMU1_REG 0x070 +#define HDMI_NV_PDISP_HDMI_AUDIO_EMU2_REG 0x074 +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL_REG 0x078 +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS_REG 0x07c +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER_REG 0x080 +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW_REG 0x084 +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH_REG 0x088 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL_REG 0x08c +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS_REG 0x090 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER_REG 0x094 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW_REG 0x098 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH_REG 0x09c +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW_REG 0x0a0 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH_REG 0x0a4 +#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL_REG 0x0a8 +#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS_REG 0x0ac +#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER_REG 0x0b0 +#define HDMI_NV_PDISP_HDMI_GENERIC_INFOFRAME_SUBPACK0_LOW_REG 0x0b4 +#define HDMI_NV_PDISP_HDMI_GENERIC_INFOFRAME_SUBPACK0_HIGH_REG 0x0b8 +#define HDMI_NV_PDISP_HDMI_GENERIC_INFOFRAME_SUBPACK1_LOW_REG 0x0bc +#define HDMI_NV_PDISP_HDMI_GENERIC_INFOFRAME_SUBPACK1_HIGH_REG 0x0c0 +#define HDMI_NV_PDISP_HDMI_GENERIC_INFOFRAME_SUBPACK2_LOW_REG 0x0c4 +#define HDMI_NV_PDISP_HDMI_GENERIC_INFOFRAME_SUBPACK2_HIGH_REG 0x0c8 +#define HDMI_NV_PDISP_HDMI_GENERIC_INFOFRAME_SUBPACK3_LOW_REG 0x0cc +#define HDMI_NV_PDISP_HDMI_GENERIC_INFOFRAME_SUBPACK3_HIGH_REG 0x0d0 +#define HDMI_NV_PDISP_HDMI_ACR_CTRL_REG 0x0d4 +#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW_REG 0x0d8 +#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH_REG 0x0dc +#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW_REG 0x0e0 +#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH_REG 0x0e4 +#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW_REG 0x0e8 +#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH_REG 0x0ec +#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW_REG 0x0f0 +#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH_REG 0x0f4 +#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW_REG 0x0f8 +#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH_REG 0x0fc +#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW_REG 0x100 +#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH_REG 0x104 +#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW_REG 0x108 +#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH_REG 0x10c + +#define HDMI_NV_PDISP_HDMI_CTRL_REG 0x110 +#define HDMI_NV_PDISP_HDMI_CTRL_ENABLE __BIT(30) +#define HDMI_NV_PDISP_HDMI_CTRL_CA_SELECT __BIT(28) +#define HDMI_NV_PDISP_HDMI_CTRL_SS_SELECT __BIT(27) +#define HDMI_NV_PDISP_HDMI_CTRL_SF_SELECT __BIT(26) +#define HDMI_NV_PDISP_HDMI_CTRL_CC_SELECT __BIT(25) +#define HDMI_NV_PDISP_HDMI_CTRL_CT_SELECT __BIT(24) +#define HDMI_NV_PDISP_HDMI_CTRL_MAX_AC_PACKET __BITS(20,16) +#define HDMI_NV_PDISP_HDMI_CTRL_SAMPLE_FLAT __BIT(12) +#define HDMI_NV_PDISP_HDMI_CTRL_AUDIO_LAYOUT_SELECT __BIT(10) +#define HDMI_NV_PDISP_HDMI_CTRL_AUDIO_LAYOUT __BIT(8) +#define HDMI_NV_PDISP_HDMI_CTRL_REKEY __BITS(6,0) + +#define HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT_REG 0x114 +#define HDMI_NV_PDISP_HDMI_VSYNC_WINDOW_REG 0x118 +#define HDMI_NV_PDISP_HDMI_GCP_CTRL_REG 0x11c +#define HDMI_NV_PDISP_HDMI_GCP_STATUS_REG 0x120 +#define HDMI_NV_PDISP_HDMI_GCP_SUBPACK_REG 0x124 +#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1_REG 0x128 +#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2_REG 0x12c +#define HDMI_NV_PDISP_HDMI_EMU0_REG 0x130 +#define HDMI_NV_PDISP_HDMI_EMU1_REG 0x134 +#define HDMI_NV_PDISP_HDMI_EMU1_RDATA_REG 0x138 +#define HDMI_NV_PDISP_HDMI_SPARE_REG 0x13c +#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1_REG 0x140 +#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STAUTS2_REG 0x144 +#define HDMI_NV_PDISP_CRC_CONTROL_REG 0x258 + +#define HDMI_NV_PDISP_INPUT_CONTROL_REG 0x25c +#define HDMI_NV_PDISP_INPUT_CONTROL_ARM_VIDEO_RANGE __BIT(1) +#define HDMI_NV_PDISP_INPUT_CONTROL_HDMI_SRC_SELECT __BIT(0) + +#define HDMI_NV_PDISP_SCRATCH_REG 0x260 +#define HDMI_NV_PDISP_PE_CURRENT_REG 0x264 +#define HDMI_NV_PDISP_KEY_CTRL_REG 0x268 +#define HDMI_NV_PDISP_KEY_DEBUG0_REG 0x26c +#define HDMI_NV_PDISP_KEY_DEBUG1_REG 0x270 +#define HDMI_NV_PDISP_KEY_DEBUG2_REG 0x274 +#define HDMI_NV_PDISP_KEY_HDCP_KEY_0_REG 0x278 +#define HDMI_NV_PDISP_KEY_HDCP_KEY_1_REG 0x27c +#define HDMI_NV_PDISP_KEY_HDCP_KEY_2_REG 0x280 +#define HDMI_NV_PDISP_KEY_HDCP_KEY_3_REG 0x284 +#define HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG_REG 0x288 +#define HDMI_NV_PDISP_KEY_SKEY_INDEX_REG 0x28c +#define HDMI_NV_PDISP_INT_STATUS_REG 0x330 +#define HDMI_NV_PDISP_INT_MASK_REG 0x334 +#define HDMI_NV_PDISP_INT_ENABLE_REG 0x338 +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_CTRL_REG 0x358 +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_STATUS_REG 0x35c +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_HEADER_REG 0x360 +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_SUBPACK0_LOW_REG 0x364 +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_SUBPACK0_HIGH_REG 0x368 +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_SUBPACK1_LOW_REG 0x36c +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_SUBPACK1_HIGH_REG 0x370 +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_SUBPACK2_LOW_REG 0x374 +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_SUBPACK2_HIGH_REG 0x378 +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_SUBPACK3_LOW_REG 0x37c +#define HDMI_NV_PDISP_HDMI_VSI_INFOFRAME_SUBPACK3_HIGH_REG 0x380 + +/* + * Serial Output Resource Registers + */ +#define HDMI_NV_PDISP_SOR_PWR_REG 0x154 +#define HDMI_NV_PDISP_SOR_PWR_SETTING_NEW __BIT(31) +#define HDMI_NV_PDISP_SOR_PWR_MODE __BIT(28) +#define HDMI_NV_PDISP_SOR_PWR_HALT_DELAY __BIT(24) +#define HDMI_NV_PDISP_SOR_PWR_SAFE_START __BIT(17) +#define HDMI_NV_PDISP_SOR_PWR_SAFE_STATE __BIT(16) +#define HDMI_NV_PDISP_SOR_PWR_NORMAL_START __BIT(1) +#define HDMI_NV_PDISP_SOR_PWR_NORMAL_STATE __BIT(0) + +#define HDMI_NV_PDISP_SOR_TEST_REG 0x158 + +#define HDMI_NV_PDISP_SOR_PLL0_REG 0x15c +#define HDMI_NV_PDISP_SOR_PLL0_TX_REG_LOAD __BITS(29,28) +#define HDMI_NV_PDISP_SOR_PLL0_ICHPMP __BITS(27,24) +#define HDMI_NV_PDISP_SOR_PLL0_FILTER __BITS(19,16) +#define HDMI_NV_PDISP_SOR_PLL0_BG_V17_S __BITS(15,12) +#define HDMI_NV_PDISP_SOR_PLL0_VCOCAP __BITS(11,8) +#define HDMI_NV_PDISP_SOR_PLL0_PULLDOWN __BIT(5) +#define HDMI_NV_PDISP_SOR_PLL0_RESISTORSEL __BIT(4) +#define HDMI_NV_PDISP_SOR_PLL0_PDPORT __BIT(3) +#define HDMI_NV_PDISP_SOR_PLL0_VCOPD __BIT(2) +#define HDMI_NV_PDISP_SOR_PLL0_PDBG __BIT(1) +#define HDMI_NV_PDISP_SOR_PLL0_PWR __BIT(0) + +#define HDMI_NV_PDISP_SOR_PLL1_REG 0x160 +#define HDMI_NV_PDISP_SOR_PLL2_REG 0x164 + +#define HDMI_NV_PDISP_SOR_CSTM_REG 0x168 +#define HDMI_NV_PDISP_SOR_CSTM_ROTDAT __BITS(30,28) +#define HDMI_NV_PDISP_SOR_CSTM_ROTCLK __BITS(27,24) +#define HDMI_NV_PDISP_SOR_CSTM_PLLDIV __BIT(21) +#define HDMI_NV_PDISP_SOR_CSTM_BALANCED __BIT(19) +#define HDMI_NV_PDISP_SOR_CSTM_NEW_MODE __BIT(18) +#define HDMI_NV_PDISP_SOR_CSTM_DUP_SYNC __BIT(17) +#define HDMI_NV_PDISP_SOR_CSTM_LVDS_EN __BIT(16) +#define HDMI_NV_PDISP_SOR_CSTM_LINKACTB __BIT(15) +#define HDMI_NV_PDISP_SOR_CSTM_LINKACTA __BIT(14) +#define HDMI_NV_PDISP_SOR_CSTM_MODE __BITS(13,12) +#define HDMI_NV_PDISP_SOR_CSTM_MODE_LVDS 0 +#define HDMI_NV_PDISP_SOR_CSTM_MODE_TMDS 1 +#define HDMI_NV_PDISP_SOR_CSTM_UPPER __BIT(11) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXCB __BIT(9) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXCA __BIT(8) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXDB_3 __BIT(7) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXDB_2 __BIT(6) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXDB_1 __BIT(5) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXDB_0 __BIT(4) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXDA_3 __BIT(3) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXDA_2 __BIT(2) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXDA_1 __BIT(1) +#define HDMI_NV_PDISP_SOR_CSTM_PD_TXDA_0 __BIT(0) + +#define HDMI_NV_PDISP_SOR_LVDS_REG 0x16c +#define HDMI_NV_PDISP_SOR_CRCA_REG 0x170 +#define HDMI_NV_PDISP_SOR_CRCB_REG 0x174 +#define HDMI_NV_PDISP_SOR_BLANK_REG 0x178 +#define HDMI_NV_PDISP_SOR_SEQ_CTL_REG 0x17c +#define HDMI_NV_PDISP_SOR_SEQ_INST0_REG 0x180 +#define HDMI_NV_PDISP_SOR_SEQ_INST1_REG 0x184 +#define HDMI_NV_PDISP_SOR_SEQ_INST2_REG 0x188 +#define HDMI_NV_PDISP_SOR_SEQ_INST3_REG 0x18c +#define HDMI_NV_PDISP_SOR_SEQ_INST4_REG 0x190 +#define HDMI_NV_PDISP_SOR_SEQ_INST5_REG 0x194 +#define HDMI_NV_PDISP_SOR_SEQ_INST6_REG 0x198 +#define HDMI_NV_PDISP_SOR_SEQ_INST7_REG 0x19c +#define HDMI_NV_PDISP_SOR_SEQ_INST8_REG 0x1a0 +#define HDMI_NV_PDISP_SOR_SEQ_INST9_REG 0x1a4 +#define HDMI_NV_PDISP_SOR_SEQ_INSTA_REG 0x1a8 +#define HDMI_NV_PDISP_SOR_SEQ_INSTB_REG 0x1ac +#define HDMI_NV_PDISP_SOR_SEQ_INSTC_REG 0x1b0 +#define HDMI_NV_PDISP_SOR_SEQ_INSTD_REG 0x1b4 +#define HDMI_NV_PDISP_SOR_SEQ_INSTE_REG 0x1b8 +#define HDMI_NV_PDISP_SOR_SEQ_INSTF_REG 0x1bc +#define HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT_REG 0x1f8 + +#define HDMI_NV_PDISP_SOR_REFCLK_REG 0x254 +#define HDMI_NV_PDISP_SOR_REFCLK_DIV_INT __BITS(15,8) +#define HDMI_NV_PDISP_SOR_REFCLK_DIV_FRAC __BITS(7,6) + +#define HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT_REG 0x344 +#define HDMI_NV_PDISP_SOR_PAD_CTLS0_REG 0x348 +#define HDMI_NV_PDISP_SOR_PAD_CTLS1_REG 0x34c + +/* + * Audio Registers + */ +#define HDMI_NV_PDISP_AUDIO_N_REG 0x230 +#define HDMI_NV_PDISP_SOR_AUDIO_CNTRL0_REG 0x2b0 +#define HDMI_NV_PDISP_SOR_AUDIO_DEBUG_REG 0x2b4 +#define HDMI_NV_PDISP_SOR_AUDIO_SPARE0_REG 0x2b8 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0320_REG 0x2bc +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0441_REG 0x2c0 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0882_REG 0x2c4 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_1764_REG 0x2c8 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0480_REG 0x2cc +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0960_REG 0x2d0 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_1920_REG 0x2d4 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_SCRATCH0_REG 0x2d8 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_SCRATCH1_REG 0x2dc +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_SCRATCH2_REG 0x2e0 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_SCRATCH3_REG 0x2e4 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH0_REG 0x2e8 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH1_REG 0x2ec +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_ELF_BUFWR_REG 0x2f0 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE_REG 0x2f4 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_CP_REG 0x2f8 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320_REG 0x2fc +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441_REG 0x300 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882_REG 0x304 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764_REG 0x308 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480_REG 0x30c +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960_REG 0x310 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920_REG 0x314 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT_REG 0x318 +#define HDMI_NV_PDISP_SOR_AUDIO_GEN_CTRL_REG 0x31c +#define HDMI_NV_HDACODEC_AUDIO_GEN_CTL_REG 0x354 + +#endif /* _ARM_TEGRA_HDMIREG_H */