diff options
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | drivers/video/fsl-diu-fb.c | 201 | ||||
-rw-r--r-- | include/linux/fsl-diu-fb.h | 9 |
3 files changed, 135 insertions, 81 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 9386a63ea8f6..477a20fc3436 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3108,6 +3108,12 @@ F: drivers/video/ | |||
3108 | F: include/video/ | 3108 | F: include/video/ |
3109 | F: include/linux/fb.h | 3109 | F: include/linux/fb.h |
3110 | 3110 | ||
3111 | FREESCALE DIU FRAMEBUFFER DRIVER | ||
3112 | M: Timur Tabi <timur@freescale.com> | ||
3113 | L: linux-fbdev@vger.kernel.org | ||
3114 | S: Supported | ||
3115 | F: drivers/video/fsl-diu-fb.* | ||
3116 | |||
3111 | FREESCALE DMA DRIVER | 3117 | FREESCALE DMA DRIVER |
3112 | M: Li Yang <leoli@freescale.com> | 3118 | M: Li Yang <leoli@freescale.com> |
3113 | M: Zhang Wei <zw@zh-kernel.org> | 3119 | M: Zhang Wei <zw@zh-kernel.org> |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index ede9e55413f8..d3fc92eaee89 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -337,13 +337,11 @@ struct mfb_info { | |||
337 | int registered; | 337 | int registered; |
338 | unsigned long pseudo_palette[16]; | 338 | unsigned long pseudo_palette[16]; |
339 | struct diu_ad *ad; | 339 | struct diu_ad *ad; |
340 | int cursor_reset; | ||
341 | unsigned char g_alpha; | 340 | unsigned char g_alpha; |
342 | unsigned int count; | 341 | unsigned int count; |
343 | int x_aoi_d; /* aoi display x offset to physical screen */ | 342 | int x_aoi_d; /* aoi display x offset to physical screen */ |
344 | int y_aoi_d; /* aoi display y offset to physical screen */ | 343 | int y_aoi_d; /* aoi display y offset to physical screen */ |
345 | struct fsl_diu_data *parent; | 344 | struct fsl_diu_data *parent; |
346 | u8 *edid_data; | ||
347 | }; | 345 | }; |
348 | 346 | ||
349 | /** | 347 | /** |
@@ -378,6 +376,8 @@ struct fsl_diu_data { | |||
378 | struct diu_ad ad[NUM_AOIS] __aligned(8); | 376 | struct diu_ad ad[NUM_AOIS] __aligned(8); |
379 | u8 gamma[256 * 3] __aligned(32); | 377 | u8 gamma[256 * 3] __aligned(32); |
380 | u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32); | 378 | u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32); |
379 | uint8_t edid_data[EDID_LENGTH]; | ||
380 | bool has_edid; | ||
381 | } __aligned(32); | 381 | } __aligned(32); |
382 | 382 | ||
383 | /* Determine the DMA address of a member of the fsl_diu_data structure */ | 383 | /* Determine the DMA address of a member of the fsl_diu_data structure */ |
@@ -430,6 +430,22 @@ static struct mfb_info mfb_template[] = { | |||
430 | }, | 430 | }, |
431 | }; | 431 | }; |
432 | 432 | ||
433 | #ifdef DEBUG | ||
434 | static void __attribute__ ((unused)) fsl_diu_dump(struct diu __iomem *hw) | ||
435 | { | ||
436 | mb(); | ||
437 | pr_debug("DIU: desc=%08x,%08x,%08x, gamma=%08x pallete=%08x " | ||
438 | "cursor=%08x curs_pos=%08x diu_mode=%08x bgnd=%08x " | ||
439 | "disp_size=%08x hsyn_para=%08x vsyn_para=%08x syn_pol=%08x " | ||
440 | "thresholds=%08x int_mask=%08x plut=%08x\n", | ||
441 | hw->desc[0], hw->desc[1], hw->desc[2], hw->gamma, | ||
442 | hw->pallete, hw->cursor, hw->curs_pos, hw->diu_mode, | ||
443 | hw->bgnd, hw->disp_size, hw->hsyn_para, hw->vsyn_para, | ||
444 | hw->syn_pol, hw->thresholds, hw->int_mask, hw->plut); | ||
445 | rmb(); | ||
446 | } | ||
447 | #endif | ||
448 | |||
433 | /** | 449 | /** |
434 | * fsl_diu_name_to_port - convert a port name to a monitor port enum | 450 | * fsl_diu_name_to_port - convert a port name to a monitor port enum |
435 | * | 451 | * |
@@ -481,8 +497,7 @@ static void fsl_diu_enable_panel(struct fb_info *info) | |||
481 | 497 | ||
482 | switch (mfbi->index) { | 498 | switch (mfbi->index) { |
483 | case PLANE0: | 499 | case PLANE0: |
484 | if (hw->desc[0] != ad->paddr) | 500 | wr_reg_wa(&hw->desc[0], ad->paddr); |
485 | wr_reg_wa(&hw->desc[0], ad->paddr); | ||
486 | break; | 501 | break; |
487 | case PLANE1_AOI0: | 502 | case PLANE1_AOI0: |
488 | cmfbi = &data->mfb[2]; | 503 | cmfbi = &data->mfb[2]; |
@@ -534,8 +549,7 @@ static void fsl_diu_disable_panel(struct fb_info *info) | |||
534 | 549 | ||
535 | switch (mfbi->index) { | 550 | switch (mfbi->index) { |
536 | case PLANE0: | 551 | case PLANE0: |
537 | if (hw->desc[0] != data->dummy_ad.paddr) | 552 | wr_reg_wa(&hw->desc[0], 0); |
538 | wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr); | ||
539 | break; | 553 | break; |
540 | case PLANE1_AOI0: | 554 | case PLANE1_AOI0: |
541 | cmfbi = &data->mfb[2]; | 555 | cmfbi = &data->mfb[2]; |
@@ -792,7 +806,8 @@ static void update_lcdc(struct fb_info *info) | |||
792 | 806 | ||
793 | hw = data->diu_reg; | 807 | hw = data->diu_reg; |
794 | 808 | ||
795 | diu_ops.set_monitor_port(data->monitor_port); | 809 | if (diu_ops.set_monitor_port) |
810 | diu_ops.set_monitor_port(data->monitor_port); | ||
796 | gamma_table_base = data->gamma; | 811 | gamma_table_base = data->gamma; |
797 | 812 | ||
798 | /* Prep for DIU init - gamma table, cursor table */ | 813 | /* Prep for DIU init - gamma table, cursor table */ |
@@ -811,12 +826,8 @@ static void update_lcdc(struct fb_info *info) | |||
811 | out_be32(&hw->gamma, DMA_ADDR(data, gamma)); | 826 | out_be32(&hw->gamma, DMA_ADDR(data, gamma)); |
812 | out_be32(&hw->cursor, DMA_ADDR(data, cursor)); | 827 | out_be32(&hw->cursor, DMA_ADDR(data, cursor)); |
813 | 828 | ||
814 | out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ | 829 | out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */ |
815 | out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ | 830 | out_be32(&hw->disp_size, (var->yres << 16) | var->xres); |
816 | out_be32(&hw->disp_size, (var->yres << 16 | var->xres)); | ||
817 | /* DISP SIZE */ | ||
818 | out_be32(&hw->wb_size, 0); /* WB SIZE */ | ||
819 | out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ | ||
820 | 831 | ||
821 | /* Horizontal and vertical configuration register */ | 832 | /* Horizontal and vertical configuration register */ |
822 | temp = var->left_margin << 22 | /* BP_H */ | 833 | temp = var->left_margin << 22 | /* BP_H */ |
@@ -833,9 +844,20 @@ static void update_lcdc(struct fb_info *info) | |||
833 | 844 | ||
834 | diu_ops.set_pixel_clock(var->pixclock); | 845 | diu_ops.set_pixel_clock(var->pixclock); |
835 | 846 | ||
836 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ | 847 | #ifndef CONFIG_PPC_MPC512x |
837 | out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */ | 848 | /* |
849 | * The PLUT register is defined differently on the MPC5121 than it | ||
850 | * is on other SOCs. Unfortunately, there's no documentation that | ||
851 | * explains how it's supposed to be programmed, so for now, we leave | ||
852 | * it at the default value on the MPC5121. | ||
853 | * | ||
854 | * For other SOCs, program it for the highest priority, which will | ||
855 | * reduce the chance of underrun. Technically, we should scale the | ||
856 | * priority to match the screen resolution, but doing that properly | ||
857 | * requires delicate fine-tuning for each use-case. | ||
858 | */ | ||
838 | out_be32(&hw->plut, 0x01F5F666); | 859 | out_be32(&hw->plut, 0x01F5F666); |
860 | #endif | ||
839 | 861 | ||
840 | /* Enable the DIU */ | 862 | /* Enable the DIU */ |
841 | enable_lcdc(info); | 863 | enable_lcdc(info); |
@@ -965,7 +987,6 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
965 | hw = data->diu_reg; | 987 | hw = data->diu_reg; |
966 | 988 | ||
967 | set_fix(info); | 989 | set_fix(info); |
968 | mfbi->cursor_reset = 1; | ||
969 | 990 | ||
970 | len = info->var.yres_virtual * info->fix.line_length; | 991 | len = info->var.yres_virtual * info->fix.line_length; |
971 | /* Alloc & dealloc each time resolution/bpp change */ | 992 | /* Alloc & dealloc each time resolution/bpp change */ |
@@ -1107,6 +1128,12 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
1107 | 1128 | ||
1108 | if (!arg) | 1129 | if (!arg) |
1109 | return -EINVAL; | 1130 | return -EINVAL; |
1131 | |||
1132 | dev_dbg(info->dev, "ioctl %08x (dir=%s%s type=%u nr=%u size=%u)\n", cmd, | ||
1133 | _IOC_DIR(cmd) & _IOC_READ ? "R" : "", | ||
1134 | _IOC_DIR(cmd) & _IOC_WRITE ? "W" : "", | ||
1135 | _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd)); | ||
1136 | |||
1110 | switch (cmd) { | 1137 | switch (cmd) { |
1111 | case MFB_SET_PIXFMT_OLD: | 1138 | case MFB_SET_PIXFMT_OLD: |
1112 | dev_warn(info->dev, | 1139 | dev_warn(info->dev, |
@@ -1180,6 +1207,23 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
1180 | ad->ckmin_b = ck.blue_min; | 1207 | ad->ckmin_b = ck.blue_min; |
1181 | } | 1208 | } |
1182 | break; | 1209 | break; |
1210 | #ifdef CONFIG_PPC_MPC512x | ||
1211 | case MFB_SET_GAMMA: { | ||
1212 | struct fsl_diu_data *data = mfbi->parent; | ||
1213 | |||
1214 | if (copy_from_user(data->gamma, buf, sizeof(data->gamma))) | ||
1215 | return -EFAULT; | ||
1216 | setbits32(&data->diu_reg->gamma, 0); /* Force table reload */ | ||
1217 | break; | ||
1218 | } | ||
1219 | case MFB_GET_GAMMA: { | ||
1220 | struct fsl_diu_data *data = mfbi->parent; | ||
1221 | |||
1222 | if (copy_to_user(buf, data->gamma, sizeof(data->gamma))) | ||
1223 | return -EFAULT; | ||
1224 | break; | ||
1225 | } | ||
1226 | #endif | ||
1183 | default: | 1227 | default: |
1184 | dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd); | 1228 | dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd); |
1185 | return -ENOIOCTLCMD; | 1229 | return -ENOIOCTLCMD; |
@@ -1206,8 +1250,22 @@ static int fsl_diu_open(struct fb_info *info, int user) | |||
1206 | res = fsl_diu_set_par(info); | 1250 | res = fsl_diu_set_par(info); |
1207 | if (res < 0) | 1251 | if (res < 0) |
1208 | mfbi->count--; | 1252 | mfbi->count--; |
1209 | else | 1253 | else { |
1254 | struct fsl_diu_data *data = mfbi->parent; | ||
1255 | |||
1256 | #ifdef CONFIG_NOT_COHERENT_CACHE | ||
1257 | /* | ||
1258 | * Enable underrun detection and vertical sync | ||
1259 | * interrupts. | ||
1260 | */ | ||
1261 | clrbits32(&data->diu_reg->int_mask, | ||
1262 | INT_UNDRUN | INT_VSYNC); | ||
1263 | #else | ||
1264 | /* Enable underrun detection */ | ||
1265 | clrbits32(&data->diu_reg->int_mask, INT_UNDRUN); | ||
1266 | #endif | ||
1210 | fsl_diu_enable_panel(info); | 1267 | fsl_diu_enable_panel(info); |
1268 | } | ||
1211 | } | 1269 | } |
1212 | 1270 | ||
1213 | spin_unlock(&diu_lock); | 1271 | spin_unlock(&diu_lock); |
@@ -1223,8 +1281,13 @@ static int fsl_diu_release(struct fb_info *info, int user) | |||
1223 | 1281 | ||
1224 | spin_lock(&diu_lock); | 1282 | spin_lock(&diu_lock); |
1225 | mfbi->count--; | 1283 | mfbi->count--; |
1226 | if (mfbi->count == 0) | 1284 | if (mfbi->count == 0) { |
1285 | struct fsl_diu_data *data = mfbi->parent; | ||
1286 | |||
1287 | /* Disable interrupts */ | ||
1288 | out_be32(&data->diu_reg->int_mask, 0xffffffff); | ||
1227 | fsl_diu_disable_panel(info); | 1289 | fsl_diu_disable_panel(info); |
1290 | } | ||
1228 | 1291 | ||
1229 | spin_unlock(&diu_lock); | 1292 | spin_unlock(&diu_lock); |
1230 | return res; | 1293 | return res; |
@@ -1248,6 +1311,7 @@ static int __devinit install_fb(struct fb_info *info) | |||
1248 | { | 1311 | { |
1249 | int rc; | 1312 | int rc; |
1250 | struct mfb_info *mfbi = info->par; | 1313 | struct mfb_info *mfbi = info->par; |
1314 | struct fsl_diu_data *data = mfbi->parent; | ||
1251 | const char *aoi_mode, *init_aoi_mode = "320x240"; | 1315 | const char *aoi_mode, *init_aoi_mode = "320x240"; |
1252 | struct fb_videomode *db = fsl_diu_mode_db; | 1316 | struct fb_videomode *db = fsl_diu_mode_db; |
1253 | unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db); | 1317 | unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db); |
@@ -1264,9 +1328,9 @@ static int __devinit install_fb(struct fb_info *info) | |||
1264 | return rc; | 1328 | return rc; |
1265 | 1329 | ||
1266 | if (mfbi->index == PLANE0) { | 1330 | if (mfbi->index == PLANE0) { |
1267 | if (mfbi->edid_data) { | 1331 | if (data->has_edid) { |
1268 | /* Now build modedb from EDID */ | 1332 | /* Now build modedb from EDID */ |
1269 | fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs); | 1333 | fb_edid_to_monspecs(data->edid_data, &info->monspecs); |
1270 | fb_videomode_to_modelist(info->monspecs.modedb, | 1334 | fb_videomode_to_modelist(info->monspecs.modedb, |
1271 | info->monspecs.modedb_len, | 1335 | info->monspecs.modedb_len, |
1272 | &info->modelist); | 1336 | &info->modelist); |
@@ -1284,7 +1348,7 @@ static int __devinit install_fb(struct fb_info *info) | |||
1284 | * For plane 0 we continue and look into | 1348 | * For plane 0 we continue and look into |
1285 | * driver's internal modedb. | 1349 | * driver's internal modedb. |
1286 | */ | 1350 | */ |
1287 | if ((mfbi->index == PLANE0) && mfbi->edid_data) | 1351 | if ((mfbi->index == PLANE0) && data->has_edid) |
1288 | has_default_mode = 0; | 1352 | has_default_mode = 0; |
1289 | else | 1353 | else |
1290 | return -EINVAL; | 1354 | return -EINVAL; |
@@ -1348,9 +1412,6 @@ static void uninstall_fb(struct fb_info *info) | |||
1348 | if (!mfbi->registered) | 1412 | if (!mfbi->registered) |
1349 | return; | 1413 | return; |
1350 | 1414 | ||
1351 | if (mfbi->index == PLANE0) | ||
1352 | kfree(mfbi->edid_data); | ||
1353 | |||
1354 | unregister_framebuffer(info); | 1415 | unregister_framebuffer(info); |
1355 | unmap_video_memory(info); | 1416 | unmap_video_memory(info); |
1356 | if (&info->cmap) | 1417 | if (&info->cmap) |
@@ -1362,7 +1423,7 @@ static void uninstall_fb(struct fb_info *info) | |||
1362 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) | 1423 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) |
1363 | { | 1424 | { |
1364 | struct diu __iomem *hw = dev_id; | 1425 | struct diu __iomem *hw = dev_id; |
1365 | unsigned int status = in_be32(&hw->int_status); | 1426 | uint32_t status = in_be32(&hw->int_status); |
1366 | 1427 | ||
1367 | if (status) { | 1428 | if (status) { |
1368 | /* This is the workaround for underrun */ | 1429 | /* This is the workaround for underrun */ |
@@ -1387,40 +1448,6 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id) | |||
1387 | return IRQ_NONE; | 1448 | return IRQ_NONE; |
1388 | } | 1449 | } |
1389 | 1450 | ||
1390 | static int request_irq_local(struct fsl_diu_data *data) | ||
1391 | { | ||
1392 | struct diu __iomem *hw = data->diu_reg; | ||
1393 | u32 ints; | ||
1394 | int ret; | ||
1395 | |||
1396 | /* Read to clear the status */ | ||
1397 | in_be32(&hw->int_status); | ||
1398 | |||
1399 | ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw); | ||
1400 | if (!ret) { | ||
1401 | ints = INT_PARERR | INT_LS_BF_VS; | ||
1402 | #if !defined(CONFIG_NOT_COHERENT_CACHE) | ||
1403 | ints |= INT_VSYNC; | ||
1404 | #endif | ||
1405 | |||
1406 | /* Read to clear the status */ | ||
1407 | in_be32(&hw->int_status); | ||
1408 | out_be32(&hw->int_mask, ints); | ||
1409 | } | ||
1410 | |||
1411 | return ret; | ||
1412 | } | ||
1413 | |||
1414 | static void free_irq_local(struct fsl_diu_data *data) | ||
1415 | { | ||
1416 | struct diu __iomem *hw = data->diu_reg; | ||
1417 | |||
1418 | /* Disable all LCDC interrupt */ | ||
1419 | out_be32(&hw->int_mask, 0x1f); | ||
1420 | |||
1421 | free_irq(data->irq, NULL); | ||
1422 | } | ||
1423 | |||
1424 | #ifdef CONFIG_PM | 1451 | #ifdef CONFIG_PM |
1425 | /* | 1452 | /* |
1426 | * Power management hooks. Note that we won't be called from IRQ context, | 1453 | * Power management hooks. Note that we won't be called from IRQ context, |
@@ -1496,8 +1523,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1496 | struct device_node *np = pdev->dev.of_node; | 1523 | struct device_node *np = pdev->dev.of_node; |
1497 | struct mfb_info *mfbi; | 1524 | struct mfb_info *mfbi; |
1498 | struct fsl_diu_data *data; | 1525 | struct fsl_diu_data *data; |
1499 | int diu_mode; | ||
1500 | dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */ | 1526 | dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */ |
1527 | const void *prop; | ||
1501 | unsigned int i; | 1528 | unsigned int i; |
1502 | int ret; | 1529 | int ret; |
1503 | 1530 | ||
@@ -1541,17 +1568,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1541 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); | 1568 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); |
1542 | mfbi->parent = data; | 1569 | mfbi->parent = data; |
1543 | mfbi->ad = &data->ad[i]; | 1570 | mfbi->ad = &data->ad[i]; |
1571 | } | ||
1544 | 1572 | ||
1545 | if (mfbi->index == PLANE0) { | 1573 | /* Get the EDID data from the device tree, if present */ |
1546 | const u8 *prop; | 1574 | prop = of_get_property(np, "edid", &ret); |
1547 | int len; | 1575 | if (prop && ret == EDID_LENGTH) { |
1548 | 1576 | memcpy(data->edid_data, prop, EDID_LENGTH); | |
1549 | /* Get EDID */ | 1577 | data->has_edid = true; |
1550 | prop = of_get_property(np, "edid", &len); | ||
1551 | if (prop && len == EDID_LENGTH) | ||
1552 | mfbi->edid_data = kmemdup(prop, EDID_LENGTH, | ||
1553 | GFP_KERNEL); | ||
1554 | } | ||
1555 | } | 1578 | } |
1556 | 1579 | ||
1557 | data->diu_reg = of_iomap(np, 0); | 1580 | data->diu_reg = of_iomap(np, 0); |
@@ -1561,10 +1584,6 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1561 | goto error; | 1584 | goto error; |
1562 | } | 1585 | } |
1563 | 1586 | ||
1564 | diu_mode = in_be32(&data->diu_reg->diu_mode); | ||
1565 | if (diu_mode == MFB_MODE0) | ||
1566 | out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */ | ||
1567 | |||
1568 | /* Get the IRQ of the DIU */ | 1587 | /* Get the IRQ of the DIU */ |
1569 | data->irq = irq_of_parse_and_map(np, 0); | 1588 | data->irq = irq_of_parse_and_map(np, 0); |
1570 | 1589 | ||
@@ -1586,11 +1605,11 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1586 | data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad); | 1605 | data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad); |
1587 | 1606 | ||
1588 | /* | 1607 | /* |
1589 | * Let DIU display splash screen if it was pre-initialized | 1608 | * Let DIU continue to display splash screen if it was pre-initialized |
1590 | * by the bootloader, set dummy area descriptor otherwise. | 1609 | * by the bootloader; otherwise, clear the display. |
1591 | */ | 1610 | */ |
1592 | if (diu_mode == MFB_MODE0) | 1611 | if (in_be32(&data->diu_reg->diu_mode) == MFB_MODE0) |
1593 | out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr); | 1612 | out_be32(&data->diu_reg->desc[0], 0); |
1594 | 1613 | ||
1595 | out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr); | 1614 | out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr); |
1596 | out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr); | 1615 | out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr); |
@@ -1603,7 +1622,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev) | |||
1603 | } | 1622 | } |
1604 | } | 1623 | } |
1605 | 1624 | ||
1606 | if (request_irq_local(data)) { | 1625 | /* |
1626 | * Older versions of U-Boot leave interrupts enabled, so disable | ||
1627 | * all of them and clear the status register. | ||
1628 | */ | ||
1629 | out_be32(&data->diu_reg->int_mask, 0xffffffff); | ||
1630 | in_be32(&data->diu_reg->int_status); | ||
1631 | |||
1632 | ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", | ||
1633 | &data->diu_reg); | ||
1634 | if (ret) { | ||
1607 | dev_err(&pdev->dev, "could not claim irq\n"); | 1635 | dev_err(&pdev->dev, "could not claim irq\n"); |
1608 | goto error; | 1636 | goto error; |
1609 | } | 1637 | } |
@@ -1638,7 +1666,8 @@ static int fsl_diu_remove(struct platform_device *pdev) | |||
1638 | 1666 | ||
1639 | data = dev_get_drvdata(&pdev->dev); | 1667 | data = dev_get_drvdata(&pdev->dev); |
1640 | disable_lcdc(&data->fsl_diu_info[0]); | 1668 | disable_lcdc(&data->fsl_diu_info[0]); |
1641 | free_irq_local(data); | 1669 | |
1670 | free_irq(data->irq, &data->diu_reg); | ||
1642 | 1671 | ||
1643 | for (i = 0; i < NUM_AOIS; i++) | 1672 | for (i = 0; i < NUM_AOIS; i++) |
1644 | uninstall_fb(&data->fsl_diu_info[i]); | 1673 | uninstall_fb(&data->fsl_diu_info[i]); |
@@ -1741,6 +1770,9 @@ static int __init fsl_diu_init(void) | |||
1741 | coherence_data_size = be32_to_cpup(prop) * 13; | 1770 | coherence_data_size = be32_to_cpup(prop) * 13; |
1742 | coherence_data_size /= 8; | 1771 | coherence_data_size /= 8; |
1743 | 1772 | ||
1773 | pr_debug("fsl-diu-fb: coherence data size is %zu bytes\n", | ||
1774 | coherence_data_size); | ||
1775 | |||
1744 | prop = of_get_property(np, "d-cache-line-size", NULL); | 1776 | prop = of_get_property(np, "d-cache-line-size", NULL); |
1745 | if (prop == NULL) { | 1777 | if (prop == NULL) { |
1746 | pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' " | 1778 | pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' " |
@@ -1750,10 +1782,17 @@ static int __init fsl_diu_init(void) | |||
1750 | } | 1782 | } |
1751 | d_cache_line_size = be32_to_cpup(prop); | 1783 | d_cache_line_size = be32_to_cpup(prop); |
1752 | 1784 | ||
1785 | pr_debug("fsl-diu-fb: cache lines size is %u bytes\n", | ||
1786 | d_cache_line_size); | ||
1787 | |||
1753 | of_node_put(np); | 1788 | of_node_put(np); |
1754 | coherence_data = vmalloc(coherence_data_size); | 1789 | coherence_data = vmalloc(coherence_data_size); |
1755 | if (!coherence_data) | 1790 | if (!coherence_data) { |
1791 | pr_err("fsl-diu-fb: could not allocate coherence data " | ||
1792 | "(size=%zu)\n", coherence_data_size); | ||
1756 | return -ENOMEM; | 1793 | return -ENOMEM; |
1794 | } | ||
1795 | |||
1757 | #endif | 1796 | #endif |
1758 | 1797 | ||
1759 | ret = platform_driver_register(&fsl_diu_driver); | 1798 | ret = platform_driver_register(&fsl_diu_driver); |
diff --git a/include/linux/fsl-diu-fb.h b/include/linux/fsl-diu-fb.h index 11c16a1fb9e3..a1e8277120c7 100644 --- a/include/linux/fsl-diu-fb.h +++ b/include/linux/fsl-diu-fb.h | |||
@@ -47,6 +47,15 @@ struct aoi_display_offset { | |||
47 | #define MFB_GET_PIXFMT _IOR('M', 8, __u32) | 47 | #define MFB_GET_PIXFMT _IOR('M', 8, __u32) |
48 | 48 | ||
49 | /* | 49 | /* |
50 | * The MPC5121 BSP comes with a gamma_set utility that initializes the | ||
51 | * gamma table. Unfortunately, it uses bad values for the IOCTL commands, | ||
52 | * but there's nothing we can do about it now. These ioctls are only | ||
53 | * supported on the MPC5121. | ||
54 | */ | ||
55 | #define MFB_SET_GAMMA _IOW('M', 1, __u8) | ||
56 | #define MFB_GET_GAMMA _IOR('M', 1, __u8) | ||
57 | |||
58 | /* | ||
50 | * The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the | 59 | * The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the |
51 | * wrong value for 'size' field of the ioctl. The current macros above use the | 60 | * wrong value for 'size' field of the ioctl. The current macros above use the |
52 | * right size, but we still need to provide backwards compatibility, at least | 61 | * right size, but we still need to provide backwards compatibility, at least |