Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Timur Tabi <timur@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

authored by

Timur Tabi and committed by
Kumar Gala
6597c713 e041013a

+109 -21
+109 -21
arch/powerpc/platforms/85xx/p1022_ds.c
··· 33 33 34 34 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) 35 35 36 + #define PMUXCR_ELBCDIU_MASK 0xc0000000 37 + #define PMUXCR_ELBCDIU_NOR16 0x80000000 38 + #define PMUXCR_ELBCDIU_DIU 0x40000000 39 + 36 40 /* 37 41 * Board-specific initialization of the DIU. This code should probably be 38 42 * executed when the DIU is opened, rather than in arch code, but the DIU ··· 54 50 #define CLKDVDR_PXCLK_MASK 0x00FF0000 55 51 56 52 /* Some ngPIXIS register definitions */ 53 + #define PX_CTL 3 54 + #define PX_BRDCFG0 8 55 + #define PX_BRDCFG1 9 56 + 57 + #define PX_BRDCFG0_ELBC_SPI_MASK 0xc0 58 + #define PX_BRDCFG0_ELBC_SPI_ELBC 0x00 59 + #define PX_BRDCFG0_ELBC_SPI_NULL 0xc0 60 + #define PX_BRDCFG0_ELBC_DIU 0x02 61 + 57 62 #define PX_BRDCFG1_DVIEN 0x80 58 63 #define PX_BRDCFG1_DFPEN 0x40 59 64 #define PX_BRDCFG1_BACKLIGHT 0x20 60 65 #define PX_BRDCFG1_DDCEN 0x10 66 + 67 + #define PX_CTL_ALTACC 0x80 61 68 62 69 /* 63 70 * DIU Area Descriptor ··· 148 133 */ 149 134 static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) 150 135 { 151 - struct device_node *np; 152 - void __iomem *pixis; 153 - u8 __iomem *brdcfg1; 136 + struct device_node *guts_node; 137 + struct device_node *indirect_node = NULL; 138 + struct ccsr_guts_85xx __iomem *guts; 139 + u8 __iomem *lbc_lcs0_ba = NULL; 140 + u8 __iomem *lbc_lcs1_ba = NULL; 141 + u8 b; 154 142 155 - np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga"); 156 - if (!np) 157 - /* older device trees used "fsl,p1022ds-pixis" */ 158 - np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis"); 159 - if (!np) { 160 - pr_err("p1022ds: missing ngPIXIS node\n"); 143 + /* Map the global utilities registers. */ 144 + guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); 145 + if (!guts_node) { 146 + pr_err("p1022ds: missing global utilties device node\n"); 161 147 return; 162 148 } 163 149 164 - pixis = of_iomap(np, 0); 165 - if (!pixis) { 166 - pr_err("p1022ds: could not map ngPIXIS registers\n"); 167 - return; 150 + guts = of_iomap(guts_node, 0); 151 + if (!guts) { 152 + pr_err("p1022ds: could not map global utilties device\n"); 153 + goto exit; 168 154 } 169 - brdcfg1 = pixis + 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */ 155 + 156 + indirect_node = of_find_compatible_node(NULL, NULL, 157 + "fsl,p1022ds-indirect-pixis"); 158 + if (!indirect_node) { 159 + pr_err("p1022ds: missing pixis indirect mode node\n"); 160 + goto exit; 161 + } 162 + 163 + lbc_lcs0_ba = of_iomap(indirect_node, 0); 164 + if (!lbc_lcs0_ba) { 165 + pr_err("p1022ds: could not map localbus chip select 0\n"); 166 + goto exit; 167 + } 168 + 169 + lbc_lcs1_ba = of_iomap(indirect_node, 1); 170 + if (!lbc_lcs1_ba) { 171 + pr_err("p1022ds: could not map localbus chip select 1\n"); 172 + goto exit; 173 + } 174 + 175 + /* Make sure we're in indirect mode first. */ 176 + if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) != 177 + PMUXCR_ELBCDIU_DIU) { 178 + struct device_node *pixis_node; 179 + void __iomem *pixis; 180 + 181 + pixis_node = 182 + of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga"); 183 + if (!pixis_node) { 184 + pr_err("p1022ds: missing pixis node\n"); 185 + goto exit; 186 + } 187 + 188 + pixis = of_iomap(pixis_node, 0); 189 + of_node_put(pixis_node); 190 + if (!pixis) { 191 + pr_err("p1022ds: could not map pixis registers\n"); 192 + goto exit; 193 + } 194 + 195 + /* Enable indirect PIXIS mode. */ 196 + setbits8(pixis + PX_CTL, PX_CTL_ALTACC); 197 + iounmap(pixis); 198 + 199 + /* Switch the board mux to the DIU */ 200 + out_8(lbc_lcs0_ba, PX_BRDCFG0); /* BRDCFG0 */ 201 + b = in_8(lbc_lcs1_ba); 202 + b |= PX_BRDCFG0_ELBC_DIU; 203 + out_8(lbc_lcs1_ba, b); 204 + 205 + /* Set the chip mux to DIU mode. */ 206 + clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK, 207 + PMUXCR_ELBCDIU_DIU); 208 + in_be32(&guts->pmuxcr); 209 + } 210 + 170 211 171 212 switch (port) { 172 213 case FSL_DIU_PORT_DVI: 173 - printk(KERN_INFO "%s:%u\n", __func__, __LINE__); 174 214 /* Enable the DVI port, disable the DFP and the backlight */ 175 - clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT, 176 - PX_BRDCFG1_DVIEN); 215 + out_8(lbc_lcs0_ba, PX_BRDCFG1); 216 + b = in_8(lbc_lcs1_ba); 217 + b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT); 218 + b |= PX_BRDCFG1_DVIEN; 219 + out_8(lbc_lcs1_ba, b); 177 220 break; 178 221 case FSL_DIU_PORT_LVDS: 179 - printk(KERN_INFO "%s:%u\n", __func__, __LINE__); 222 + /* 223 + * LVDS also needs backlight enabled, otherwise the display 224 + * will be blank. 225 + */ 180 226 /* Enable the DFP port, disable the DVI and the backlight */ 181 - clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT, 182 - PX_BRDCFG1_DFPEN); 227 + out_8(lbc_lcs0_ba, PX_BRDCFG1); 228 + b = in_8(lbc_lcs1_ba); 229 + b &= ~PX_BRDCFG1_DVIEN; 230 + b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT; 231 + out_8(lbc_lcs1_ba, b); 183 232 break; 184 233 default: 185 234 pr_err("p1022ds: unsupported monitor port %i\n", port); 186 235 } 187 236 188 - iounmap(pixis); 237 + exit: 238 + if (lbc_lcs1_ba) 239 + iounmap(lbc_lcs1_ba); 240 + if (lbc_lcs0_ba) 241 + iounmap(lbc_lcs0_ba); 242 + if (guts) 243 + iounmap(guts); 244 + 245 + of_node_put(indirect_node); 246 + of_node_put(guts_node); 189 247 } 190 248 191 249 /**