Lines Matching +full:hw +full:- +full:monitor
1 // SPDX-License-Identifier: GPL-2.0-or-later
7 * Authors: Hongjun Chen <hong-jun.chen@freescale.com>
22 #include <linux/dma-mapping.h>
33 #include <linux/fsl-diu-fb.h>
38 /* HW cursor parameters */
52 * order if increasing resolution and frequency. The 320x240-60 mode is
345 * struct fsl_diu_data - per-DIU data structure
350 * @monitor_port: the monitor port this DIU is connected to
353 * @dummy_aoi: video buffer for the 4x4 32-bit dummy AOI
363 * This data structure must be allocated with 32-byte alignment, so that the
379 /* It's easier to parse the cursor data as little-endian */
381 /* Blank cursor data -- used to hide the cursor */
383 /* Scratch cursor data -- used to build new cursor */
390 #define DMA_ADDR(p, f) ((p)->dma_addr + offsetof(struct fsl_diu_data, f))
440 static void __attribute__ ((unused)) fsl_diu_dump(struct diu __iomem *hw)
447 hw->desc[0], hw->desc[1], hw->desc[2], hw->gamma,
448 hw->palette, hw->cursor, hw->curs_pos, hw->diu_mode,
449 hw->bgnd, hw->disp_size, hw->hsyn_para, hw->vsyn_para,
450 hw->syn_pol, hw->thresholds, hw->int_mask, hw->plut);
456 * fsl_diu_name_to_port - convert a port name to a monitor port enum
458 * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns
467 * (platform-specific) is chosen instead.
502 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
503 struct diu_ad *ad = mfbi->ad;
504 struct fsl_diu_data *data = mfbi->parent;
505 struct diu __iomem *hw = data->diu_reg;
507 switch (mfbi->index) {
509 wr_reg_wa(&hw->desc[0], ad->paddr);
512 cmfbi = &data->mfb[2];
513 if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
514 if (cmfbi->count > 0) /* AOI1 open */
515 ad->next_ad =
516 cpu_to_le32(cmfbi->ad->paddr);
518 ad->next_ad = 0;
519 wr_reg_wa(&hw->desc[1], ad->paddr);
523 cmfbi = &data->mfb[4];
524 if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
525 if (cmfbi->count > 0) /* AOI1 open */
526 ad->next_ad =
527 cpu_to_le32(cmfbi->ad->paddr);
529 ad->next_ad = 0;
530 wr_reg_wa(&hw->desc[2], ad->paddr);
534 pmfbi = &data->mfb[1];
535 ad->next_ad = 0;
536 if (hw->desc[1] == data->dummy_ad.paddr)
537 wr_reg_wa(&hw->desc[1], ad->paddr);
539 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
542 pmfbi = &data->mfb[3];
543 ad->next_ad = 0;
544 if (hw->desc[2] == data->dummy_ad.paddr)
545 wr_reg_wa(&hw->desc[2], ad->paddr);
547 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
554 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
555 struct diu_ad *ad = mfbi->ad;
556 struct fsl_diu_data *data = mfbi->parent;
557 struct diu __iomem *hw = data->diu_reg;
559 switch (mfbi->index) {
561 wr_reg_wa(&hw->desc[0], 0);
564 cmfbi = &data->mfb[2];
565 if (cmfbi->count > 0) /* AOI1 is open */
566 wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
569 wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
573 cmfbi = &data->mfb[4];
574 if (cmfbi->count > 0) /* AOI1 is open */
575 wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
578 wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
582 pmfbi = &data->mfb[1];
583 if (hw->desc[1] != ad->paddr) {
585 if (pmfbi->count > 0)
587 pmfbi->ad->next_ad = 0;
589 wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
593 pmfbi = &data->mfb[3];
594 if (hw->desc[2] != ad->paddr) {
596 if (pmfbi->count > 0)
598 pmfbi->ad->next_ad = 0;
600 wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
608 struct mfb_info *mfbi = info->par;
609 struct fsl_diu_data *data = mfbi->parent;
610 struct diu __iomem *hw = data->diu_reg;
612 out_be32(&hw->diu_mode, MFB_MODE1);
617 struct mfb_info *mfbi = info->par;
618 struct fsl_diu_data *data = mfbi->parent;
619 struct diu __iomem *hw = data->diu_reg;
621 out_be32(&hw->diu_mode, 0);
627 struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par;
628 struct fsl_diu_data *data = mfbi->parent;
630 enum mfb_index index = mfbi->index;
634 base_plane_width = data->fsl_diu_info[0].var.xres;
635 base_plane_height = data->fsl_diu_info[0].var.yres;
637 if (mfbi->x_aoi_d < 0)
638 mfbi->x_aoi_d = 0;
639 if (mfbi->y_aoi_d < 0)
640 mfbi->y_aoi_d = 0;
643 if (mfbi->x_aoi_d != 0)
644 mfbi->x_aoi_d = 0;
645 if (mfbi->y_aoi_d != 0)
646 mfbi->y_aoi_d = 0;
650 lower_aoi_mfbi = data->fsl_diu_info[index+1].par;
651 lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
652 if (var->xres > base_plane_width)
653 var->xres = base_plane_width;
654 if ((mfbi->x_aoi_d + var->xres) > base_plane_width)
655 mfbi->x_aoi_d = base_plane_width - var->xres;
658 available_height = lower_aoi_mfbi->y_aoi_d;
661 if (var->yres > available_height)
662 var->yres = available_height;
663 if ((mfbi->y_aoi_d + var->yres) > available_height)
664 mfbi->y_aoi_d = available_height - var->yres;
668 upper_aoi_mfbi = data->fsl_diu_info[index-1].par;
669 upper_aoi_height = data->fsl_diu_info[index-1].var.yres;
670 upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height;
671 upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
672 if (var->xres > base_plane_width)
673 var->xres = base_plane_width;
674 if ((mfbi->x_aoi_d + var->xres) > base_plane_width)
675 mfbi->x_aoi_d = base_plane_width - var->xres;
676 if (mfbi->y_aoi_d < 0)
677 mfbi->y_aoi_d = 0;
679 if (mfbi->y_aoi_d < upper_aoi_bottom)
680 mfbi->y_aoi_d = upper_aoi_bottom;
682 - upper_aoi_bottom;
685 if (var->yres > available_height)
686 var->yres = available_height;
687 if ((mfbi->y_aoi_d + var->yres) > base_plane_height)
688 mfbi->y_aoi_d = base_plane_height - var->yres;
697 * a -EINVAL will be returned by the upper layers.
702 if (var->xres_virtual < var->xres)
703 var->xres_virtual = var->xres;
704 if (var->yres_virtual < var->yres)
705 var->yres_virtual = var->yres;
707 if (var->xoffset + info->var.xres > info->var.xres_virtual)
708 var->xoffset = info->var.xres_virtual - info->var.xres;
710 if (var->yoffset + info->var.yres > info->var.yres_virtual)
711 var->yoffset = info->var.yres_virtual - info->var.yres;
713 if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
714 (var->bits_per_pixel != 16))
715 var->bits_per_pixel = default_bpp;
717 switch (var->bits_per_pixel) {
719 var->red.length = 5;
720 var->red.offset = 11;
721 var->red.msb_right = 0;
723 var->green.length = 6;
724 var->green.offset = 5;
725 var->green.msb_right = 0;
727 var->blue.length = 5;
728 var->blue.offset = 0;
729 var->blue.msb_right = 0;
731 var->transp.length = 0;
732 var->transp.offset = 0;
733 var->transp.msb_right = 0;
736 var->red.length = 8;
737 var->red.offset = 0;
738 var->red.msb_right = 0;
740 var->green.length = 8;
741 var->green.offset = 8;
742 var->green.msb_right = 0;
744 var->blue.length = 8;
745 var->blue.offset = 16;
746 var->blue.msb_right = 0;
748 var->transp.length = 0;
749 var->transp.offset = 0;
750 var->transp.msb_right = 0;
753 var->red.length = 8;
754 var->red.offset = 16;
755 var->red.msb_right = 0;
757 var->green.length = 8;
758 var->green.offset = 8;
759 var->green.msb_right = 0;
761 var->blue.length = 8;
762 var->blue.offset = 0;
763 var->blue.msb_right = 0;
765 var->transp.length = 8;
766 var->transp.offset = 24;
767 var->transp.msb_right = 0;
772 var->height = -1;
773 var->width = -1;
774 var->grayscale = 0;
777 var->sync |= var->nonstd;
778 var->nonstd |= var->sync;
786 struct fb_fix_screeninfo *fix = &info->fix;
787 struct fb_var_screeninfo *var = &info->var;
788 struct mfb_info *mfbi = info->par;
790 strscpy_pad(fix->id, mfbi->id);
791 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
792 fix->type = FB_TYPE_PACKED_PIXELS;
793 fix->accel = FB_ACCEL_NONE;
794 fix->visual = FB_VISUAL_TRUECOLOR;
795 fix->xpanstep = 1;
796 fix->ypanstep = 1;
801 struct fb_var_screeninfo *var = &info->var;
802 struct mfb_info *mfbi = info->par;
803 struct fsl_diu_data *data = mfbi->parent;
804 struct diu __iomem *hw;
810 hw = data->diu_reg;
813 diu_ops.set_monitor_port(data->monitor_port);
814 gamma_table_base = data->gamma;
816 /* Prep for DIU init - gamma table, cursor table */
823 diu_ops.set_gamma_table(data->monitor_port, data->gamma);
829 out_be32(&hw->gamma, DMA_ADDR(data, gamma));
831 out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
832 out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
835 temp = var->left_margin << 22 | /* BP_H */
836 var->hsync_len << 11 | /* PW_H */
837 var->right_margin; /* FP_H */
839 out_be32(&hw->hsyn_para, temp);
841 temp = var->upper_margin << 22 | /* BP_V */
842 var->vsync_len << 11 | /* PW_V */
843 var->lower_margin; /* FP_V */
845 out_be32(&hw->vsyn_para, temp);
847 diu_ops.set_pixel_clock(var->pixclock);
859 * requires delicate fine-tuning for each use-case.
861 out_be32(&hw->plut, 0x01F5F666);
870 u32 smem_len = info->fix.line_length * info->var.yres_virtual;
876 return -ENOMEM;
878 mutex_lock(&info->mm_lock);
879 info->screen_base = p;
880 info->fix.smem_start = virt_to_phys((__force const void *)info->screen_base);
881 info->fix.smem_len = smem_len;
882 mutex_unlock(&info->mm_lock);
883 info->screen_size = info->fix.smem_len;
890 void *p = info->screen_base;
891 size_t l = info->fix.smem_len;
893 mutex_lock(&info->mm_lock);
894 info->screen_base = NULL;
895 info->fix.smem_start = 0;
896 info->fix.smem_len = 0;
897 mutex_unlock(&info->mm_lock);
909 struct fb_var_screeninfo *var = &info->var;
910 struct mfb_info *mfbi = info->par;
911 struct diu_ad *ad = mfbi->ad;
914 ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
915 ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
922 * The pixel format is a 32-bit value that determine which bits in each
967 pr_err("fsl-diu: unsupported color depth %u\n", bits_per_pixel);
983 * simplify our code by using a 32-bit big-endian integer ("line") to read in
987 * This could result in an unaligned 32-bit read. For example, if the cursor
989 * the top line of the cursor. We do a 32-bit read of 'image', but we look
992 * 'image' by 1-3 bytes, but that should not cause any problems.
998 struct mfb_info *mfbi = info->par;
999 struct fsl_diu_data *data = mfbi->parent;
1000 __le16 *cursor = data->cursor;
1025 struct mfb_info *mfbi = info->par;
1026 struct fsl_diu_data *data = mfbi->parent;
1027 struct diu __iomem *hw = data->diu_reg;
1029 if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
1030 return -EINVAL;
1033 if (cursor->set & FB_CUR_SETSIZE) {
1041 memset(data->cursor, 0, sizeof(data->cursor));
1044 /* The cursor position has changed (cursor->image.dx|dy) */
1045 if (cursor->set & FB_CUR_SETPOS) {
1048 yy = (cursor->image.dy - info->var.yoffset) & 0x7ff;
1049 xx = (cursor->image.dx - info->var.xoffset) & 0x7ff;
1051 out_be32(&hw->curs_pos, yy << 16 | xx);
1055 * FB_CUR_SETIMAGE - the cursor image has changed
1056 * FB_CUR_SETCMAP - the cursor colors has changed
1057 * FB_CUR_SETSHAPE - the cursor bitmask has changed
1059 if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
1065 DIV_ROUND_UP(cursor->image.width, 8) *
1066 cursor->image.height;
1069 unsigned int bg_idx = cursor->image.bg_color;
1070 unsigned int fg_idx = cursor->image.fg_color;
1075 if (info->state != FBINFO_STATE_RUNNING)
1078 bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
1079 ((info->cmap.green[bg_idx] & 0xf8) << 2) |
1080 ((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
1083 fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
1084 ((info->cmap.green[fg_idx] & 0xf8) << 2) |
1085 ((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
1088 /* Use 32-bit operations on the data to improve performance */
1089 image = (uint32_t *)data->next_cursor;
1090 source = (uint32_t *)cursor->image.data;
1091 mask = (uint32_t *)cursor->mask;
1093 if (cursor->rop == ROP_XOR)
1101 cursor->image.width, cursor->image.height);
1111 if (cursor->enable)
1112 out_be32(&hw->cursor, DMA_ADDR(data, cursor));
1114 out_be32(&hw->cursor, DMA_ADDR(data, blank_cursor));
1130 struct fb_var_screeninfo *var = &info->var;
1131 struct mfb_info *mfbi = info->par;
1132 struct fsl_diu_data *data = mfbi->parent;
1133 struct diu_ad *ad = mfbi->ad;
1134 struct diu __iomem *hw;
1136 hw = data->diu_reg;
1140 len = info->var.yres_virtual * info->fix.line_length;
1142 if (len != info->fix.smem_len) {
1143 if (info->fix.smem_start)
1149 return -ENOMEM;
1154 ad->pix_fmt = diu_ops.get_pixel_format(data->monitor_port,
1155 var->bits_per_pixel);
1157 ad->pix_fmt = fsl_diu_get_pixel_format(var->bits_per_pixel);
1159 ad->addr = cpu_to_le32(info->fix.smem_start);
1160 ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
1161 var->xres_virtual) | mfbi->g_alpha;
1163 ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres);
1164 ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
1165 ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
1168 ad->ckmax_r = 0;
1169 ad->ckmax_g = 0;
1170 ad->ckmax_b = 0;
1172 ad->ckmin_r = 255;
1173 ad->ckmin_g = 255;
1174 ad->ckmin_b = 255;
1176 if (mfbi->index == PLANE0)
1183 return ((val << width) + 0x7FFF - val) >> 16;
1205 if (info->var.grayscale)
1208 switch (info->fix.visual) {
1211 * 16-bit True Colour. We encode the RGB value
1215 u32 *pal = info->pseudo_palette;
1218 red = CNVT_TOHW(red, info->var.red.length);
1219 green = CNVT_TOHW(green, info->var.green.length);
1220 blue = CNVT_TOHW(blue, info->var.blue.length);
1221 transp = CNVT_TOHW(transp, info->var.transp.length);
1223 v = (red << info->var.red.offset) |
1224 (green << info->var.green.offset) |
1225 (blue << info->var.blue.offset) |
1226 (transp << info->var.transp.offset);
1240 * don't fit, return -EINVAL.
1245 if ((info->var.xoffset == var->xoffset) &&
1246 (info->var.yoffset == var->yoffset))
1249 if (var->xoffset + info->var.xres > info->var.xres_virtual
1250 || var->yoffset + info->var.yres > info->var.yres_virtual)
1251 return -EINVAL;
1253 info->var.xoffset = var->xoffset;
1254 info->var.yoffset = var->yoffset;
1256 if (var->vmode & FB_VMODE_YWRAP)
1257 info->var.vmode |= FB_VMODE_YWRAP;
1259 info->var.vmode &= ~FB_VMODE_YWRAP;
1269 struct mfb_info *mfbi = info->par;
1270 struct diu_ad *ad = mfbi->ad;
1278 return -EINVAL;
1293 return -EFAULT;
1294 ad->pix_fmt = pix_fmt;
1302 pix_fmt = ad->pix_fmt;
1304 return -EFAULT;
1308 return -EFAULT;
1309 mfbi->x_aoi_d = aoi_d.x_aoi_d;
1310 mfbi->y_aoi_d = aoi_d.y_aoi_d;
1311 fsl_diu_check_var(&info->var, info);
1315 aoi_d.x_aoi_d = mfbi->x_aoi_d;
1316 aoi_d.y_aoi_d = mfbi->y_aoi_d;
1318 return -EFAULT;
1321 global_alpha = mfbi->g_alpha;
1323 return -EFAULT;
1328 return -EFAULT;
1329 ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) |
1331 mfbi->g_alpha = global_alpha;
1336 return -EFAULT;
1342 return -EINVAL;
1345 ad->ckmax_r = 0;
1346 ad->ckmax_g = 0;
1347 ad->ckmax_b = 0;
1348 ad->ckmin_r = 255;
1349 ad->ckmin_g = 255;
1350 ad->ckmin_b = 255;
1352 ad->ckmax_r = ck.red_max;
1353 ad->ckmax_g = ck.green_max;
1354 ad->ckmax_b = ck.blue_max;
1355 ad->ckmin_r = ck.red_min;
1356 ad->ckmin_g = ck.green_min;
1357 ad->ckmin_b = ck.blue_min;
1362 struct fsl_diu_data *data = mfbi->parent;
1364 if (copy_from_user(data->gamma, buf, sizeof(data->gamma)))
1365 return -EFAULT;
1366 setbits32(&data->diu_reg->gamma, 0); /* Force table reload */
1370 struct fsl_diu_data *data = mfbi->parent;
1372 if (copy_to_user(buf, data->gamma, sizeof(data->gamma)))
1373 return -EFAULT;
1379 return -ENOIOCTLCMD;
1392 clrbits32(&data->diu_reg->int_mask, int_mask);
1399 struct mfb_info *mfbi = info->par;
1403 if ((mfbi->index == PLANE0) && diu_ops.release_bootmem)
1407 mfbi->count++;
1408 if (mfbi->count == 1) {
1409 fsl_diu_check_var(&info->var, info);
1412 mfbi->count--;
1414 fsl_diu_enable_interrupts(mfbi->parent);
1427 struct mfb_info *mfbi = info->par;
1430 mfbi->count--;
1431 if (mfbi->count == 0) {
1432 struct fsl_diu_data *data = mfbi->parent;
1438 struct mfb_info *mi = data->fsl_diu_info[i].par;
1440 if (mi->count)
1444 out_be32(&data->diu_reg->int_mask, 0xffffffff);
1468 struct mfb_info *mfbi = info->par;
1469 struct fsl_diu_data *data = mfbi->parent;
1475 info->var.activate = FB_ACTIVATE_NOW;
1476 info->fbops = &fsl_diu_ops;
1477 info->flags = FBINFO_VIRTFB | FBINFO_PARTIAL_PAN_OK |
1479 info->pseudo_palette = mfbi->pseudo_palette;
1481 rc = fb_alloc_cmap(&info->cmap, 16, 0);
1485 if (mfbi->index == PLANE0) {
1486 if (data->has_edid) {
1488 fb_edid_to_monspecs(data->edid_data, &info->monspecs);
1489 fb_videomode_to_modelist(info->monspecs.modedb,
1490 info->monspecs.modedb_len,
1491 &info->modelist);
1492 db = info->monspecs.modedb;
1493 dbsize = info->monspecs.modedb_len;
1499 rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, NULL,
1506 if ((mfbi->index == PLANE0) && data->has_edid)
1509 return -EINVAL;
1513 rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
1520 if (!has_default_mode && info->monspecs.modedb) {
1521 struct fb_monspecs *specs = &info->monspecs;
1522 struct fb_videomode *modedb = &specs->modedb[0];
1528 if (specs->misc & FB_MISC_1ST_DETAIL) {
1531 for (i = 0; i < specs->modedb_len; i++) {
1532 if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
1533 modedb = &specs->modedb[i];
1539 info->var.bits_per_pixel = default_bpp;
1540 fb_videomode_to_var(&info->var, modedb);
1543 if (fsl_diu_check_var(&info->var, info)) {
1546 fb_dealloc_cmap(&info->cmap);
1547 return -EINVAL;
1553 fb_dealloc_cmap(&info->cmap);
1554 return -EINVAL;
1557 mfbi->registered = 1;
1558 fb_info(info, "%s registered successfully\n", mfbi->id);
1565 struct mfb_info *mfbi = info->par;
1567 if (!mfbi->registered)
1572 fb_dealloc_cmap(&info->cmap);
1574 mfbi->registered = 0;
1579 struct diu __iomem *hw = dev_id;
1580 uint32_t status = in_be32(&hw->int_status);
1585 out_be32(&hw->diu_mode, 0);
1587 out_be32(&hw->diu_mode, 1);
1614 data = dev_get_drvdata(&ofdev->dev);
1615 disable_lcdc(data->fsl_diu_info);
1625 data = dev_get_drvdata(&ofdev->dev);
1628 update_lcdc(data->fsl_diu_info);
1630 if (data->mfb[i].count)
1631 fsl_diu_enable_panel(&data->fsl_diu_info[i]);
1649 old_monitor_port = data->monitor_port;
1650 data->monitor_port = fsl_diu_name_to_port(buf);
1652 if (old_monitor_port != data->monitor_port) {
1659 fsl_diu_set_par(&data->fsl_diu_info[i]);
1670 switch (data->monitor_port) {
1674 return sprintf(buf, "Single-link LVDS\n");
1676 return sprintf(buf, "Dual-link LVDS\n");
1684 struct device_node *np = pdev->dev.of_node;
1692 data = dmam_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
1695 return -ENOMEM;
1696 data->dma_addr = dma_addr;
1700 * always page-aligned. We need the memory to be 32-byte aligned,
1706 dev_err(&pdev->dev, "misaligned allocation");
1707 ret = -ENOMEM;
1711 spin_lock_init(&data->reg_lock);
1714 struct fb_info *info = &data->fsl_diu_info[i];
1716 info->device = &pdev->dev;
1717 info->par = &data->mfb[i];
1723 data->ad[i].paddr = DMA_ADDR(data, ad[i]);
1725 info->fix.smem_start = 0;
1728 mfbi = info->par;
1730 mfbi->parent = data;
1731 mfbi->ad = &data->ad[i];
1737 memcpy(data->edid_data, prop, EDID_LENGTH);
1738 data->has_edid = true;
1741 data->diu_reg = of_iomap(np, 0);
1742 if (!data->diu_reg) {
1743 dev_err(&pdev->dev, "cannot map DIU registers\n");
1744 ret = -EFAULT;
1749 data->irq = irq_of_parse_and_map(np, 0);
1751 if (!data->irq) {
1752 dev_err(&pdev->dev, "could not get DIU IRQ\n");
1753 ret = -EINVAL;
1756 data->monitor_port = monitor_port;
1759 data->dummy_ad.addr = cpu_to_le32(DMA_ADDR(data, dummy_aoi));
1760 data->dummy_ad.pix_fmt = 0x88882317;
1761 data->dummy_ad.src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
1762 data->dummy_ad.aoi_size = cpu_to_le32((4 << 16) | 2);
1763 data->dummy_ad.offset_xyi = 0;
1764 data->dummy_ad.offset_xyd = 0;
1765 data->dummy_ad.next_ad = 0;
1766 data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
1769 * Let DIU continue to display splash screen if it was pre-initialized
1772 if (in_be32(&data->diu_reg->diu_mode) == MFB_MODE0)
1773 out_be32(&data->diu_reg->desc[0], 0);
1775 out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
1776 out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
1779 * Older versions of U-Boot leave interrupts enabled, so disable
1782 out_be32(&data->diu_reg->int_mask, 0xffffffff);
1783 in_be32(&data->diu_reg->int_status);
1785 ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
1786 data->diu_reg);
1788 dev_err(&pdev->dev, "could not claim irq\n");
1793 ret = install_fb(&data->fsl_diu_info[i]);
1795 dev_err(&pdev->dev, "could not register fb %d\n", i);
1796 free_irq(data->irq, data->diu_reg);
1801 sysfs_attr_init(&data->dev_attr.attr);
1802 data->dev_attr.attr.name = "monitor";
1803 data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
1804 data->dev_attr.show = show_monitor;
1805 data->dev_attr.store = store_monitor;
1806 ret = device_create_file(&pdev->dev, &data->dev_attr);
1808 dev_err(&pdev->dev, "could not create sysfs file %s\n",
1809 data->dev_attr.attr.name);
1812 dev_set_drvdata(&pdev->dev, data);
1817 uninstall_fb(&data->fsl_diu_info[i]);
1819 iounmap(data->diu_reg);
1829 data = dev_get_drvdata(&pdev->dev);
1830 device_remove_file(&pdev->dev, &data->dev_attr);
1831 disable_lcdc(&data->fsl_diu_info[0]);
1833 free_irq(data->irq, data->diu_reg);
1836 uninstall_fb(&data->fsl_diu_info[i]);
1838 iounmap(data->diu_reg);
1853 if (!strncmp(opt, "monitor=", 8)) {
1869 .compatible = "fsl,mpc5121-diu",
1881 .name = "fsl-diu-fb",
1904 return -ENODEV;
1915 return -ENODEV;
1922 pr_err("fsl-diu-fb: can't find 'cpu' device node\n");
1923 return -ENODEV;
1926 prop = of_get_property(np, "d-cache-size", NULL);
1928 pr_err("fsl-diu-fb: missing 'd-cache-size' property' "
1931 return -ENODEV;
1941 pr_debug("fsl-diu-fb: coherence data size is %zu bytes\n",
1944 prop = of_get_property(np, "d-cache-line-size", NULL);
1946 pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
1949 return -ENODEV;
1953 pr_debug("fsl-diu-fb: cache lines size is %u bytes\n",
1959 return -ENOMEM;
1964 pr_err("fsl-diu-fb: failed to register platform driver\n");
1989 "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
1991 MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified in 'mode'");
1992 module_param_named(monitor, monitor_string, charp, 0);
1993 MODULE_PARM_DESC(monitor, "Specify the monitor port "