Commit 6597c713 authored by Timur Tabi's avatar Timur Tabi Committed by Kumar Gala

powerpc/85xx: p1022ds: enable monitor switching via pixis indirect mode

When the P1022's DIU video controller is active, the pixis must be accessed
in "indirect" mode, which uses localbus chip select addresses.

Switching between the DVI and LVDS monitor ports is handled by the pixis,
so that switching needs to be done via indirect mode.

This has the side-effect of no longer requiring U-Boot to enable the DIU.
Now Linux can enable the DIU all by itself.
Signed-off-by: default avatarTimur Tabi <timur@freescale.com>
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
parent e041013a
...@@ -33,6 +33,10 @@ ...@@ -33,6 +33,10 @@
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
#define PMUXCR_ELBCDIU_MASK 0xc0000000
#define PMUXCR_ELBCDIU_NOR16 0x80000000
#define PMUXCR_ELBCDIU_DIU 0x40000000
/* /*
* Board-specific initialization of the DIU. This code should probably be * Board-specific initialization of the DIU. This code should probably be
* executed when the DIU is opened, rather than in arch code, but the DIU * executed when the DIU is opened, rather than in arch code, but the DIU
...@@ -50,11 +54,22 @@ ...@@ -50,11 +54,22 @@
#define CLKDVDR_PXCLK_MASK 0x00FF0000 #define CLKDVDR_PXCLK_MASK 0x00FF0000
/* Some ngPIXIS register definitions */ /* Some ngPIXIS register definitions */
#define PX_CTL 3
#define PX_BRDCFG0 8
#define PX_BRDCFG1 9
#define PX_BRDCFG0_ELBC_SPI_MASK 0xc0
#define PX_BRDCFG0_ELBC_SPI_ELBC 0x00
#define PX_BRDCFG0_ELBC_SPI_NULL 0xc0
#define PX_BRDCFG0_ELBC_DIU 0x02
#define PX_BRDCFG1_DVIEN 0x80 #define PX_BRDCFG1_DVIEN 0x80
#define PX_BRDCFG1_DFPEN 0x40 #define PX_BRDCFG1_DFPEN 0x40
#define PX_BRDCFG1_BACKLIGHT 0x20 #define PX_BRDCFG1_BACKLIGHT 0x20
#define PX_BRDCFG1_DDCEN 0x10 #define PX_BRDCFG1_DDCEN 0x10
#define PX_CTL_ALTACC 0x80
/* /*
* DIU Area Descriptor * DIU Area Descriptor
* *
...@@ -133,44 +148,117 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port, ...@@ -133,44 +148,117 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
*/ */
static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
{ {
struct device_node *np; struct device_node *guts_node;
void __iomem *pixis; struct device_node *indirect_node = NULL;
u8 __iomem *brdcfg1; struct ccsr_guts_85xx __iomem *guts;
u8 __iomem *lbc_lcs0_ba = NULL;
np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga"); u8 __iomem *lbc_lcs1_ba = NULL;
if (!np) u8 b;
/* older device trees used "fsl,p1022ds-pixis" */
np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis"); /* Map the global utilities registers. */
if (!np) { guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
pr_err("p1022ds: missing ngPIXIS node\n"); if (!guts_node) {
pr_err("p1022ds: missing global utilties device node\n");
return; return;
} }
pixis = of_iomap(np, 0); guts = of_iomap(guts_node, 0);
if (!pixis) { if (!guts) {
pr_err("p1022ds: could not map ngPIXIS registers\n"); pr_err("p1022ds: could not map global utilties device\n");
return; goto exit;
}
indirect_node = of_find_compatible_node(NULL, NULL,
"fsl,p1022ds-indirect-pixis");
if (!indirect_node) {
pr_err("p1022ds: missing pixis indirect mode node\n");
goto exit;
} }
brdcfg1 = pixis + 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */
lbc_lcs0_ba = of_iomap(indirect_node, 0);
if (!lbc_lcs0_ba) {
pr_err("p1022ds: could not map localbus chip select 0\n");
goto exit;
}
lbc_lcs1_ba = of_iomap(indirect_node, 1);
if (!lbc_lcs1_ba) {
pr_err("p1022ds: could not map localbus chip select 1\n");
goto exit;
}
/* Make sure we're in indirect mode first. */
if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
PMUXCR_ELBCDIU_DIU) {
struct device_node *pixis_node;
void __iomem *pixis;
pixis_node =
of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
if (!pixis_node) {
pr_err("p1022ds: missing pixis node\n");
goto exit;
}
pixis = of_iomap(pixis_node, 0);
of_node_put(pixis_node);
if (!pixis) {
pr_err("p1022ds: could not map pixis registers\n");
goto exit;
}
/* Enable indirect PIXIS mode. */
setbits8(pixis + PX_CTL, PX_CTL_ALTACC);
iounmap(pixis);
/* Switch the board mux to the DIU */
out_8(lbc_lcs0_ba, PX_BRDCFG0); /* BRDCFG0 */
b = in_8(lbc_lcs1_ba);
b |= PX_BRDCFG0_ELBC_DIU;
out_8(lbc_lcs1_ba, b);
/* Set the chip mux to DIU mode. */
clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK,
PMUXCR_ELBCDIU_DIU);
in_be32(&guts->pmuxcr);
}
switch (port) { switch (port) {
case FSL_DIU_PORT_DVI: case FSL_DIU_PORT_DVI:
printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
/* Enable the DVI port, disable the DFP and the backlight */ /* Enable the DVI port, disable the DFP and the backlight */
clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT, out_8(lbc_lcs0_ba, PX_BRDCFG1);
PX_BRDCFG1_DVIEN); b = in_8(lbc_lcs1_ba);
b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
b |= PX_BRDCFG1_DVIEN;
out_8(lbc_lcs1_ba, b);
break; break;
case FSL_DIU_PORT_LVDS: case FSL_DIU_PORT_LVDS:
printk(KERN_INFO "%s:%u\n", __func__, __LINE__); /*
* LVDS also needs backlight enabled, otherwise the display
* will be blank.
*/
/* Enable the DFP port, disable the DVI and the backlight */ /* Enable the DFP port, disable the DVI and the backlight */
clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT, out_8(lbc_lcs0_ba, PX_BRDCFG1);
PX_BRDCFG1_DFPEN); b = in_8(lbc_lcs1_ba);
b &= ~PX_BRDCFG1_DVIEN;
b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT;
out_8(lbc_lcs1_ba, b);
break; break;
default: default:
pr_err("p1022ds: unsupported monitor port %i\n", port); pr_err("p1022ds: unsupported monitor port %i\n", port);
} }
iounmap(pixis); exit:
if (lbc_lcs1_ba)
iounmap(lbc_lcs1_ba);
if (lbc_lcs0_ba)
iounmap(lbc_lcs0_ba);
if (guts)
iounmap(guts);
of_node_put(indirect_node);
of_node_put(guts_node);
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment