static int __devinit milkymistfb_probe(struct platform_device *pdev) { struct milkymistfb *milkymistfb; struct fb_info *info; int ret = -ENOMEM; info = framebuffer_alloc(sizeof(*milkymistfb), &pdev->dev); if (!info) return -ENOMEM; info->fbops = &milkymistfb_ops; milkymistfb = info->par; milkymistfb->fb = info; fb_find_mode(&info->var, info, milkymistfb_mode_option, milkymist_modedb, ARRAY_SIZE(milkymist_modedb), NULL, 16); /* milkymistfb->vidmem = dma_alloc_coherent(&pdev->dev, videomemorysize, &milkymistfb->vidmem_phys, GFP_KERNEL);*/ milkymistfb->vidmem = vmalloc(videomemorysize); milkymistfb->vidmem_phys = (unsigned int)milkymistfb->vidmem; if (!milkymistfb->vidmem) { ret = -ENOMEM; goto err_framebuffer_release; } memset(milkymistfb->vidmem, 0, videomemorysize); info->screen_base = milkymistfb->vidmem; info->fix = milkymistfb_fix; info->pseudo_palette = milkymistfb->pseudo_palette; info->flags = FBINFO_FLAG_DEFAULT; info->fix.smem_start = milkymistfb->vidmem_phys; info->fix.smem_len = videomemorysize; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret < 0) goto err_dma_free; ret = register_framebuffer(info); if (ret < 0) goto err_dealloc_cmap; platform_set_drvdata(pdev, milkymistfb); dev_info(&pdev->dev, "fb%d: Milkymist frame buffer at %p, size %ld k\n", info->node, milkymistfb->vidmem, videomemorysize >> 10); return 0; err_dealloc_cmap: fb_dealloc_cmap(&info->cmap); err_dma_free: /* dma_free_coherent(&pdev->dev, videomemorysize, milkymistfb->vidmem, milkymistfb->vidmem_phys);*/ vfree(milkymistfb->vidmem); err_framebuffer_release: framebuffer_release(info); return ret; }
static int lcdif_init(struct mxc_dispdrv_handle *disp, struct mxc_dispdrv_setting *setting) { int ret, i; struct mxc_lcdif_data *lcdif = mxc_dispdrv_getdata(disp); struct fsl_mxc_lcd_platform_data *plat_data = lcdif->pdev->dev.platform_data; struct fb_videomode *modedb = lcdif_modedb; int modedb_sz = lcdif_modedb_sz; /* use platform defined ipu/di */ setting->dev_id = plat_data->ipu_id; setting->disp_id = plat_data->disp_id; ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, modedb, modedb_sz, NULL, setting->default_bpp); if (!ret) { fb_videomode_to_var(&setting->fbi->var, &modedb[0]); setting->if_fmt = plat_data->default_ifmt; } INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < modedb_sz; i++) { struct fb_videomode m; fb_var_to_videomode(&m, &setting->fbi->var); if (fb_mode_is_equal(&m, &modedb[i])) { fb_add_videomode(&modedb[i], &setting->fbi->modelist); break; } } return ret; }
int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info, const char *mode_option, unsigned int default_bpp) { const struct fb_videomode *db = NULL; unsigned int dbsize = 0; if (mode_option && !strncmp(mode_option, "mac", 3)) { db = mac_modedb; dbsize = sizeof(mac_modedb)/sizeof(*mac_modedb); } return fb_find_mode(var, info, mode_option, db, dbsize, &mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp); }
static int mipi_dsi_lcd_init(struct mipi_dsi_info *mipi_dsi, struct mxc_dispdrv_setting *setting) { int i, size, err; struct fb_videomode *mipi_lcd_modedb; struct fb_videomode mode; struct device *dev = &mipi_dsi->pdev->dev; for (i = 0; i < ARRAY_SIZE(mipi_dsi_lcd_db); i++) { if (!strcmp(mipi_dsi->lcd_panel, mipi_dsi_lcd_db[i].lcd_panel)) { mipi_dsi->lcd_callback = &mipi_dsi_lcd_db[i].lcd_callback; break; } } if (i == ARRAY_SIZE(mipi_dsi_lcd_db)) { dev_err(dev, "failed to find supported lcd panel.\n"); return -EINVAL; } mipi_dsi->lcd_callback->get_mipi_lcd_videomode(&mipi_lcd_modedb, &size, &mipi_dsi->lcd_config); err = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, mipi_lcd_modedb, size, NULL, setting->default_bpp); if (err != 1) fb_videomode_to_var(&setting->fbi->var, mipi_lcd_modedb); INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < size; i++) { fb_var_to_videomode(&mode, &setting->fbi->var); if (fb_mode_is_equal(&mode, mipi_lcd_modedb + i)) { err = fb_add_videomode(mipi_lcd_modedb + i, &setting->fbi->modelist); mipi_dsi->mode = mipi_lcd_modedb + i; break; } } if ((err < 0) || (size == i)) { dev_err(dev, "failed to add videomode.\n"); return err; } return 0; }
/*! * @brief Install framebuffer into the system. * * @param info framebuffer information pointer * @param pdev pointer to struct device * @return Negative errno on error, or zero on success. */ static int __init _install_fb(struct fb_info *info, struct platform_device *pdev) { struct mx2fb_info *mx2fbi = (struct mx2fb_info *)info->par; if (_init_fbinfo(info, pdev)) return -EINVAL; if (fb_mode == 0) fb_mode = pdev->dev.platform_data; if (!fb_find_mode(&info->var, info, fb_mode, mxcfb_modedb, mxcfb_modedb_sz, NULL, default_bpp)) { fb_dealloc_cmap(&info->cmap); return -EBUSY; } /* Default Y virtual size is 2x panel size */ /* info->var.yres_virtual = info->var.yres << 1; */ if (mx2fbi->type == MX2FB_TYPE_GW) mx2fbi->blank = FB_BLANK_NORMAL; else mx2fbi->blank = FB_BLANK_UNBLANK; if (mx2fb_set_par(info)) { fb_dealloc_cmap(&info->cmap); return -EINVAL; } if (register_framebuffer(info) < 0) { _unmap_video_memory(info); fb_dealloc_cmap(&info->cmap); return -EINVAL; } mx2fbi->registered = 1; dev_info(info->device, "fb%d: %s fb device registered successfully.\n", info->node, info->fix.id); return 0; }
static int ldb_disp_init(struct mxc_dispdrv_handle *disp, struct mxc_dispdrv_setting *setting) { int ret = 0, i; struct ldb_data *ldb = mxc_dispdrv_getdata(disp); struct fsl_mxc_ldb_platform_data *plat_data = ldb->pdev->dev.platform_data; struct resource *res; uint32_t base_addr; uint32_t reg, setting_idx; uint32_t ch_mask = 0, ch_val = 0; uint32_t ipu_id, disp_id; /* if input format not valid, make RGB666 as default*/ if (!valid_mode(setting->if_fmt)) { dev_warn(&ldb->pdev->dev, "Input pixel format not valid" " use default RGB666\n"); setting->if_fmt = IPU_PIX_FMT_RGB666; } if (!ldb->inited) { char di_clk[] = "ipu1_di0_clk"; char ldb_clk[] = "ldb_di0_clk"; int lvds_channel = 0; setting_idx = 0; res = platform_get_resource(ldb->pdev, IORESOURCE_MEM, 0); if (IS_ERR(res)) return -ENOMEM; base_addr = res->start; ldb->reg = ioremap(base_addr, res->end - res->start + 1); ldb->control_reg = ldb->reg + 2; ldb->gpr3_reg = ldb->reg + 3; ldb->lvds_bg_reg = regulator_get(&ldb->pdev->dev, plat_data->lvds_bg_reg); if (!IS_ERR(ldb->lvds_bg_reg)) { regulator_set_voltage(ldb->lvds_bg_reg, 2500000, 2500000); regulator_enable(ldb->lvds_bg_reg); } /* ipu selected by platform data setting */ setting->dev_id = plat_data->ipu_id; reg = readl(ldb->control_reg); /* refrence resistor select */ reg &= ~LDB_BGREF_RMODE_MASK; if (plat_data->ext_ref) reg |= LDB_BGREF_RMODE_EXT; else reg |= LDB_BGREF_RMODE_INT; /* TODO: now only use SPWG data mapping for both channel */ reg &= ~(LDB_BIT_MAP_CH0_MASK | LDB_BIT_MAP_CH1_MASK); reg |= LDB_BIT_MAP_CH0_SPWG | LDB_BIT_MAP_CH1_SPWG; /* channel mode setting */ reg &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); reg &= ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK); if (bits_per_pixel(setting->if_fmt) == 24) reg |= LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24; else reg |= LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18; if (g_ldb_mode) ldb->mode = g_ldb_mode; else ldb->mode = plat_data->mode; if ((ldb->mode == LDB_SIN0) || (ldb->mode == LDB_SIN1)) { ret = ldb->mode - LDB_SIN0; if (plat_data->disp_id != ret) { dev_warn(&ldb->pdev->dev, "change IPU DI%d to IPU DI%d for LDB " "channel%d.\n", plat_data->disp_id, ret, ret); plat_data->disp_id = ret; } } else if (((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1)) && (cpu_is_mx6q() || cpu_is_mx6dl())) { if (plat_data->disp_id == plat_data->sec_disp_id) { dev_err(&ldb->pdev->dev, "For LVDS separate mode," "two DIs should be different!\n"); return -EINVAL; } if (((!plat_data->disp_id) && (ldb->mode == LDB_SEP1)) || ((plat_data->disp_id) && (ldb->mode == LDB_SEP0))) { dev_dbg(&ldb->pdev->dev, "LVDS separate mode:" "swap DI configuration!\n"); ipu_id = plat_data->ipu_id; disp_id = plat_data->disp_id; plat_data->ipu_id = plat_data->sec_ipu_id; plat_data->disp_id = plat_data->sec_disp_id; plat_data->sec_ipu_id = ipu_id; plat_data->sec_disp_id = disp_id; } } if (ldb->mode == LDB_SPL_DI0) { reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0; setting->disp_id = 0; } else if (ldb->mode == LDB_SPL_DI1) { reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1; setting->disp_id = 1; } else if (ldb->mode == LDB_DUL_DI0) { reg &= ~LDB_SPLIT_MODE_EN; reg |= LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0; setting->disp_id = 0; } else if (ldb->mode == LDB_DUL_DI1) { reg &= ~LDB_SPLIT_MODE_EN; reg |= LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1; setting->disp_id = 1; } else if (ldb->mode == LDB_SIN0) { reg &= ~LDB_SPLIT_MODE_EN; setting->disp_id = plat_data->disp_id; if (setting->disp_id == 0) reg |= LDB_CH0_MODE_EN_TO_DI0; else reg |= LDB_CH0_MODE_EN_TO_DI1; ch_mask = LDB_CH0_MODE_MASK; ch_val = reg & LDB_CH0_MODE_MASK; } else if (ldb->mode == LDB_SIN1) { reg &= ~LDB_SPLIT_MODE_EN; setting->disp_id = plat_data->disp_id; if (setting->disp_id == 0) reg |= LDB_CH1_MODE_EN_TO_DI0; else reg |= LDB_CH1_MODE_EN_TO_DI1; ch_mask = LDB_CH1_MODE_MASK; ch_val = reg & LDB_CH1_MODE_MASK; } else { /* separate mode*/ setting->disp_id = plat_data->disp_id; /* first output is LVDS0 or LVDS1 */ if (ldb->mode == LDB_SEP0) lvds_channel = 0; else lvds_channel = 1; reg &= ~LDB_SPLIT_MODE_EN; if ((lvds_channel == 0) && (setting->disp_id == 0)) reg |= LDB_CH0_MODE_EN_TO_DI0; else if ((lvds_channel == 0) && (setting->disp_id == 1)) reg |= LDB_CH0_MODE_EN_TO_DI1; else if ((lvds_channel == 1) && (setting->disp_id == 0)) reg |= LDB_CH1_MODE_EN_TO_DI0; else reg |= LDB_CH1_MODE_EN_TO_DI1; ch_mask = lvds_channel ? LDB_CH1_MODE_MASK : LDB_CH0_MODE_MASK; ch_val = reg & ch_mask; if (bits_per_pixel(setting->if_fmt) == 24) { if (lvds_channel == 0) reg &= ~LDB_DATA_WIDTH_CH1_24; else reg &= ~LDB_DATA_WIDTH_CH0_24; } else { if (lvds_channel == 0) reg &= ~LDB_DATA_WIDTH_CH1_18; else reg &= ~LDB_DATA_WIDTH_CH0_18; } } writel(reg, ldb->control_reg); if (ldb->mode < LDB_SIN0) { ch_mask = LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK; ch_val = reg & (LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); } /* clock setting */ if ((cpu_is_mx6q() || cpu_is_mx6dl()) && ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))) ldb_clk[6] += lvds_channel; else ldb_clk[6] += setting->disp_id; ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev, ldb_clk); if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) { dev_err(&ldb->pdev->dev, "get ldb clk0 failed\n"); iounmap(ldb->reg); return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk); } di_clk[3] += setting->dev_id; di_clk[7] += setting->disp_id; ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev, di_clk); if (IS_ERR(ldb->setting[setting_idx].di_clk)) { dev_err(&ldb->pdev->dev, "get di clk0 failed\n"); iounmap(ldb->reg); return PTR_ERR(ldb->setting[setting_idx].di_clk); } dev_dbg(&ldb->pdev->dev, "ldb_clk to di clk: %s -> %s\n", ldb_clk, di_clk); /* fb notifier for clk setting */ ldb->nb.notifier_call = ldb_fb_event, ret = fb_register_client(&ldb->nb); if (ret < 0) { iounmap(ldb->reg); return ret; } ldb->inited = true; } else { /* second time for separate mode */ char di_clk[] = "ipu1_di0_clk"; char ldb_clk[] = "ldb_di0_clk"; int lvds_channel; if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1) || (ldb->mode == LDB_DUL_DI0) || (ldb->mode == LDB_DUL_DI1) || (ldb->mode == LDB_SIN0) || (ldb->mode == LDB_SIN1)) { dev_err(&ldb->pdev->dev, "for second ldb disp" "ldb mode should in separate mode\n"); return -EINVAL; } setting_idx = 1; if (cpu_is_mx6q() || cpu_is_mx6dl()) { setting->dev_id = plat_data->sec_ipu_id; setting->disp_id = plat_data->sec_disp_id; } else { setting->dev_id = plat_data->ipu_id; setting->disp_id = !plat_data->disp_id; } if (setting->disp_id == ldb->setting[0].di) { dev_err(&ldb->pdev->dev, "Err: for second ldb disp in" "separate mode, DI should be different!\n"); return -EINVAL; } /* second output is LVDS0 or LVDS1 */ if (ldb->mode == LDB_SEP0) lvds_channel = 1; else lvds_channel = 0; reg = readl(ldb->control_reg); if ((lvds_channel == 0) && (setting->disp_id == 0)) reg |= LDB_CH0_MODE_EN_TO_DI0; else if ((lvds_channel == 0) && (setting->disp_id == 1)) reg |= LDB_CH0_MODE_EN_TO_DI1; else if ((lvds_channel == 1) && (setting->disp_id == 0)) reg |= LDB_CH1_MODE_EN_TO_DI0; else reg |= LDB_CH1_MODE_EN_TO_DI1; ch_mask = lvds_channel ? LDB_CH1_MODE_MASK : LDB_CH0_MODE_MASK; ch_val = reg & ch_mask; if (bits_per_pixel(setting->if_fmt) == 24) { if (lvds_channel == 0) reg |= LDB_DATA_WIDTH_CH0_24; else reg |= LDB_DATA_WIDTH_CH1_24; } else { if (lvds_channel == 0) reg |= LDB_DATA_WIDTH_CH0_18; else reg |= LDB_DATA_WIDTH_CH1_18; } writel(reg, ldb->control_reg); /* clock setting */ if (cpu_is_mx6q() || cpu_is_mx6dl()) ldb_clk[6] += lvds_channel; else ldb_clk[6] += setting->disp_id; ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev, ldb_clk); if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) { dev_err(&ldb->pdev->dev, "get ldb clk1 failed\n"); return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk); } di_clk[3] += setting->dev_id; di_clk[7] += setting->disp_id; ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev, di_clk); if (IS_ERR(ldb->setting[setting_idx].di_clk)) { dev_err(&ldb->pdev->dev, "get di clk1 failed\n"); return PTR_ERR(ldb->setting[setting_idx].di_clk); } dev_dbg(&ldb->pdev->dev, "ldb_clk to di clk: %s -> %s\n", ldb_clk, di_clk); } ldb->setting[setting_idx].ch_mask = ch_mask; ldb->setting[setting_idx].ch_val = ch_val; if (cpu_is_mx6q() || cpu_is_mx6dl()) ldb_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb); /* * ldb_di0_clk -> ipux_di0_clk * ldb_di1_clk -> ipux_di1_clk */ clk_set_parent(ldb->setting[setting_idx].di_clk, ldb->setting[setting_idx].ldb_di_clk); /* must use spec video mode defined by driver */ ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, ldb_modedb, ldb_modedb_sz, NULL, setting->default_bpp); if (ret != 1) fb_videomode_to_var(&setting->fbi->var, &ldb_modedb[0]); INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < ldb_modedb_sz; i++) { struct fb_videomode m; fb_var_to_videomode(&m, &setting->fbi->var); if (fb_mode_is_equal(&m, &ldb_modedb[i])) { fb_add_videomode(&ldb_modedb[i], &setting->fbi->modelist); break; } } /* save current ldb setting for fb notifier */ ldb->setting[setting_idx].active = true; ldb->setting[setting_idx].ipu = setting->dev_id; ldb->setting[setting_idx].di = setting->disp_id; return ret; }
static int __init vfb_probe(struct platform_device *dev) { struct fb_info *info; int retval = -ENOMEM; /* Reserve the framebuffer memory */ if (!request_mem_region(vfb_addr, vfb_size, "STM32F4 Framebuffer")) { printk(KERN_ERR "vfb: unable to reserve " "framebuffer at 0x%0x\n", (unsigned int)vfb_addr); retval = -EBUSY; goto fail_reqmem; } /* Allocate framebuffer info structure */ info = framebuffer_alloc(sizeof(struct fb_info), &dev->dev); if (!info) { printk(KERN_ERR "vfb: unable to reserve framebuffer info\n"); retval = -ENOMEM; goto fail_fballoc; } /* For real video cards we use ioremap */ info->screen_base = ioremap(vfb_addr, vfb_size); if (!info->screen_base) { printk(KERN_ERR "vfb: unable to map framebuffer\n"); retval = -ENOMEM; goto fail_remap; } /* Assign the frame buffer data */ info->screen_size = vfb_size; info->fbops = &vfb_ops; /* * VFB must clear memory to prevent kernel info * leakage into userspace * VGA-based drivers MUST NOT clear memory if * they want to be able to take over vgacon */ memset(info->screen_base, 0, info->screen_size); retval = fb_find_mode(&info->var, info, NULL, NULL, 0, NULL, 8); if ((!retval) || (retval == 4)) memcpy(&(info->var), &vfb_default, sizeof(struct fb_var_screeninfo)); vfb_fix.smem_start = vfb_addr; vfb_fix.smem_len = vfb_size; memcpy(&(info->fix), &vfb_fix, sizeof(struct fb_fix_screeninfo)); /* Allocate pseudo palette data */ info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); if (!info->pseudo_palette) { printk(KERN_ERR "vfb: unable to reserve palette memory\n"); retval = -ENOMEM; goto fail_palette; } //info->pseudo_palette = info->par; info->par = NULL; info->flags = FBINFO_FLAG_DEFAULT; /* * We expect the boot loader to have initialized the chip * with appropriate parameters from which we can determinte * the flavor of lcd panel attached */ retval = init_vals(info); if (retval < 0) { printk(KERN_ERR "vfb: unable to reserve cmap memory\n"); goto fail_cmap; } /* Regiser the framebuffer */ retval = register_framebuffer(info); if (retval < 0) { printk(KERN_ERR "vfb: unable to register framebuffer\n"); goto fail_register; } /* Assign the driver data */ platform_set_drvdata(dev, info); /* Everything is OK */ printk(KERN_INFO "fb%d: Virtual frame buffer device, " "using %ldK of video memory\n", info->node, info->screen_size >> 10); return 0; /* There is an error! */ fail_register: fb_dealloc_cmap(&info->cmap); fail_cmap: kfree(info->pseudo_palette); fail_palette: iounmap(info->screen_base); fail_remap: framebuffer_release(info); fail_fballoc: release_mem_region(vfb_addr, vfb_size); fail_reqmem: return retval; }
static int mxc_elcdif_fb_probe(struct platform_device *pdev) { int ret = 0; struct mxc_elcdif_fb_data *data; struct resource *res; struct fb_info *fbi; struct mxc_fb_platform_data *pdata = pdev->dev.platform_data; fbi = framebuffer_alloc(sizeof(struct mxc_elcdif_fb_data), &pdev->dev); if (fbi == NULL) { ret = -ENOMEM; goto out; } data = (struct mxc_elcdif_fb_data *)fbi->par; data->cur_blank = data->next_blank = FB_BLANK_UNBLANK; fbi->var.activate = FB_ACTIVATE_NOW; fbi->fbops = &mxc_elcdif_fb_ops; fbi->flags = FBINFO_FLAG_DEFAULT; fbi->pseudo_palette = data->pseudo_palette; ret = fb_alloc_cmap(&fbi->cmap, 16, 0); if (ret) goto out; g_elcdif_dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { dev_err(&pdev->dev, "cannot get IRQ resource\n"); ret = -ENODEV; goto err0; } data->dma_irq = res->start; ret = request_irq(data->dma_irq, lcd_irq_handler, 0, "mxc_elcdif_fb", data); if (ret) { dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n", data->dma_irq, ret); goto err0; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { ret = -ENODEV; goto err1; } elcdif_base = ioremap(res->start, SZ_4K); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res) { fbi->fix.smem_len = res->end - res->start + 1; fbi->fix.smem_start = res->start; fbi->screen_base = ioremap(fbi->fix.smem_start, fbi->fix.smem_len); } strcpy(fbi->fix.id, "mxc_elcdif_fb"); fbi->var.xres = 800; fbi->var.yres = 480; if (pdata && !data->output_pix_fmt) data->output_pix_fmt = pdata->interface_pix_fmt; if (pdata && pdata->mode && pdata->num_modes) fb_videomode_to_modelist(pdata->mode, pdata->num_modes, &fbi->modelist); if (!fb_mode && pdata && pdata->mode_str) fb_mode = pdata->mode_str; if (fb_mode) { ret = fb_find_mode(&fbi->var, fbi, fb_mode, NULL, 0, NULL, default_bpp); if ((!ret || (ret > 2)) && pdata && pdata->mode && pdata->num_modes) fb_find_mode(&fbi->var, fbi, fb_mode, pdata->mode, pdata->num_modes, NULL, default_bpp); } mxc_elcdif_fb_check_var(&fbi->var, fbi); fbi->var.xres_virtual = fbi->var.xres; fbi->var.yres_virtual = fbi->var.yres * 3; mxc_elcdif_fb_set_fix(fbi); if (!res || !res->end) if (mxc_elcdif_fb_map_video_memory(fbi) < 0) { ret = -ENOMEM; goto err2; } g_elcdif_axi_clk = clk_get(g_elcdif_dev, "elcdif_axi"); if (g_elcdif_axi_clk == NULL) { dev_err(&pdev->dev, "can't get ELCDIF axi clk\n"); ret = -ENODEV; goto err3; } g_elcdif_pix_clk = clk_get(g_elcdif_dev, "elcdif_pix"); if (g_elcdif_pix_clk == NULL) { dev_err(&pdev->dev, "can't get ELCDIF pix clk\n"); ret = -ENODEV; goto err3; } /* * Set an appropriate pixel clk rate first, so that we can * access ELCDIF registers. */ clk_set_rate(g_elcdif_pix_clk, 25000000); ret = register_framebuffer(fbi); if (ret) goto err3; platform_set_drvdata(pdev, fbi); return 0; err3: mxc_elcdif_fb_unmap_video_memory(fbi); err2: iounmap(elcdif_base); err1: free_irq(data->dma_irq, data); err0: fb_dealloc_cmap(&fbi->cmap); framebuffer_release(fbi); out: return ret; }
static int lcdif_init(struct mxc_dispdrv_handle *disp, struct mxc_dispdrv_setting *setting) { int ret, i; struct mxc_lcdif_data *lcdif = mxc_dispdrv_getdata(disp); struct fsl_mxc_lcd_platform_data *plat_data = lcdif->pdev->dev.platform_data; struct fb_videomode *modedb = lcdif_modedb; int modedb_sz = lcdif_modedb_sz; struct fsl_video_timing *custom_timing; /* use platform defined ipu/di */ setting->dev_id = plat_data->ipu_id; setting->disp_id = plat_data->disp_id; if (plat_data->lcd0_timing != NULL) { custom_timing = plat_data->lcd0_timing; lcdif_modedb[0].pixclock = PICOS2KHZ(custom_timing->pixclock); lcdif_modedb[0].xres = custom_timing->hres; lcdif_modedb[0].left_margin = custom_timing->hfp; lcdif_modedb[0].right_margin = custom_timing->hbp; lcdif_modedb[0].hsync_len = custom_timing->hsw; lcdif_modedb[0].yres = custom_timing->vres; lcdif_modedb[0].upper_margin = custom_timing->vfp; lcdif_modedb[0].lower_margin = custom_timing->vbp; lcdif_modedb[0].vsync_len = custom_timing->vsw; } if (plat_data->lcd1_timing != NULL) { custom_timing = plat_data->lcd1_timing; lcdif_modedb[1].pixclock = PICOS2KHZ(custom_timing->pixclock); lcdif_modedb[1].xres = custom_timing->hres; lcdif_modedb[1].left_margin = custom_timing->hfp; lcdif_modedb[1].right_margin = custom_timing->hbp; lcdif_modedb[1].hsync_len = custom_timing->hsw; lcdif_modedb[1].yres = custom_timing->vres; lcdif_modedb[1].upper_margin = custom_timing->vfp; lcdif_modedb[1].lower_margin = custom_timing->vbp; lcdif_modedb[1].vsync_len = custom_timing->vsw; } ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, modedb, modedb_sz, NULL, setting->default_bpp); if (!ret) { fb_videomode_to_var(&setting->fbi->var, &modedb[0]); setting->if_fmt = plat_data->default_ifmt; } INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < modedb_sz; i++) { struct fb_videomode m; fb_var_to_videomode(&m, &setting->fbi->var); if (fb_mode_is_equal(&m, &modedb[i])) { fb_add_videomode(&modedb[i], &setting->fbi->modelist); break; } } return ret; }
/*! * @brief Ioctl function to support customized ioctl operations. * * @param info Framebuffer structure that represents a single frame buffer * @param cmd The command number * @param arg Argument which depends on cmd * * @return Negative errno on error, or zero on success. */ static int mx2fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct mx2fb_info *mx2fbi = (struct mx2fb_info *)info->par; struct mx2fb_gbl_alpha ga; struct mx2fb_color_key ck; switch (cmd) { case MX2FB_SET_GBL_ALPHA: if (mx2fbi->type != MX2FB_TYPE_GW) return -ENODEV; if (!arg) return -EINVAL; /* set graphic window information */ if (copy_from_user((void *)&ga, (void *)arg, sizeof(ga))) return -EFAULT; g_gwinfo.alpha_value = ga.alpha; if (g_gwinfo.enabled) _enable_graphic_window(info); else _disable_graphic_window(info); break; case MX2FB_SET_CLR_KEY: if (mx2fbi->type != MX2FB_TYPE_GW) return -ENODEV; if (!arg) return -EINVAL; /* set graphic window information */ if (copy_from_user((void *)&ck, (void *)arg, sizeof(ck))) return -EFAULT; g_gwinfo.ck_enabled = ck.enable; g_gwinfo.ck_red = (ck.color_key & 0x003F0000) >> 16; g_gwinfo.ck_green = (ck.color_key & 0x00003F00) >> 8; g_gwinfo.ck_blue = ck.color_key & 0x0000003F; if (g_gwinfo.enabled) _enable_graphic_window(info); else _disable_graphic_window(info); break; case FBIOGET_GWINFO: if (mx2fbi->type != MX2FB_TYPE_GW) return -ENODEV; if (!arg) return -EINVAL; /* get graphic window information */ if (copy_to_user((void *)arg, (void *)&g_gwinfo, sizeof(g_gwinfo))) return -EFAULT; break; case FBIOPUT_GWINFO: if (mx2fbi->type != MX2FB_TYPE_GW) return -ENODEV; if (!arg) return -EINVAL; /* set graphic window information */ if (copy_from_user((void *)&g_gwinfo, (void *)arg, sizeof(g_gwinfo))) return -EFAULT; if (g_gwinfo.enabled) _enable_graphic_window(info); else _disable_graphic_window(info); break; #ifdef CONFIG_FB_MXC_TVOUT case ENCODER_GET_CAPABILITIES:{ int ret; struct video_encoder_capability cap; if (mx2fbi->type != MX2FB_TYPE_BG) return -ENODEV; ret = fs453_ioctl(cmd, &cap); if (ret) return ret; if (copy_to_user((void *)arg, &cap, sizeof(cap))) return -EFAULT; break; } case ENCODER_SET_NORM:{ int ret; unsigned long mode; char *smode; struct fb_var_screeninfo var; if (mx2fbi->type != MX2FB_TYPE_BG) return -ENODEV; if (copy_from_user(&mode, (void *)arg, sizeof(mode))) return -EFAULT; if ((ret = fs453_ioctl(cmd, &mode))) return ret; if (mode == VIDEO_ENCODER_PAL) smode = MODE_PAL; else if (mode == VIDEO_ENCODER_NTSC) smode = MODE_NTSC; else smode = MODE_VGA; var = info->var; var.nonstd = 0; ret = fb_find_mode(&var, info, smode, mxcfb_modedb, mxcfb_modedb_sz, NULL, default_bpp); if ((ret != 1) && (ret != 2)) /* specified mode not found */ return -ENODEV; info->var = var; fb_mode = smode; return mx2fb_set_par(info); } case ENCODER_SET_INPUT: case ENCODER_SET_OUTPUT: case ENCODER_ENABLE_OUTPUT:{ unsigned long varg; if (mx2fbi->type != MX2FB_TYPE_BG) return -ENODEV; if (copy_from_user(&varg, (void *)arg, sizeof(varg))) return -EFAULT; return fs453_ioctl(cmd, &varg); } #endif default: dev_dbg(info->device, "Unknown ioctl command (0x%08X)\n", cmd); return -EINVAL; } return 0; }
/************************************************************************ * Initialization and cleanup code */ static int stmfb_parse_module_parameters(struct stmfb_info *i, int display) { char *paramstring = NULL; char *copy = NULL; char *mode = NULL; char *memsize = NULL; char *auxmemsize = NULL; char *tvstandard = NULL; char *componentvideo = NULL; char *hdmivideo = NULL; char *blit_api_ver; unsigned long fbsize = 0; int stride; /* * Note: slightly messy due to module parameter limitations and not wanting to * use parameter arrays. */ switch(display) { case 0: paramstring = display0; break; case 1: paramstring = display1; break; case 2: paramstring = display2; break; case 3: paramstring = display3; break; default: break; } printk("stmfb: fb%d parameters = \"%s\"\n",display,(paramstring==NULL)?"<NULL>":paramstring); if(paramstring == NULL || *paramstring == '\0') return -ENODEV; copy = kstrdup(paramstring, GFP_KERNEL); if(!copy) return -ENOMEM; mode = strsep(©,":,"); memsize = strsep(©,":,"); auxmemsize = strsep(©,":,"); tvstandard = strsep(©,":,"); componentvideo = strsep(©,":,"); hdmivideo = strsep(©,":,"); blit_api_ver = strsep(©,":,"); if(!mode || *mode == '\0') { DPRINTK("No mode string found\n"); kfree(copy); return -ENODEV; } if(fb_find_mode(&i->info.var,&i->info,mode,i->videomodedb,ARRAY_SIZE(i->videomodedb),NULL,16) == 0) { DPRINTK("No suitable mode found (not even a default!)\n"); kfree(copy); return -ENODEV; } if(memsize) { fbsize = (unsigned long)memparse(memsize,&memsize); DPRINTK("requested memory = %lu\n",fbsize); } stride = i->info.var.xres * (i->info.var.bits_per_pixel/8); i->info.var.yres_virtual = fbsize / stride; if(i->info.var.yres_virtual < i->info.var.yres) { DPRINTK("Requested memory is too small for default video mode, fixing it\n"); fbsize = i->info.var.yres * stride; } /* * Having determined size, set the virtual yres to equal yres for the * default mode. */ i->info.var.yres_virtual = i->info.var.yres; i->ulFBSize = fbsize; if(auxmemsize) { i->AuxSize[0] = (unsigned long)memparse(auxmemsize,&auxmemsize); DPRINTK("requested %lu bytes of auxiliary memory\n",i->AuxSize[0]); } else i->AuxSize[0] = 0; i->default_sd_encoding = STM_OUTPUT_STD_NTSC_M; if (tvstandard) { switch(*tvstandard) { case 'N': case 'n': { if(!strcmp(tvstandard,"NTSC-J")) { DPRINTK("Selecting NTSC-J output\n"); i->default_sd_encoding = STM_OUTPUT_STD_NTSC_J; } else if(!strcmp(tvstandard,"NTSC-443")) { DPRINTK("Selecting NTSC-443 output\n"); i->default_sd_encoding = STM_OUTPUT_STD_NTSC_443; } else { DPRINTK("Selecting NTSC (US) output\n"); i->default_sd_encoding = STM_OUTPUT_STD_NTSC_M; } break; } case 'S': case 's': { DPRINTK("Selecting SECAM output\n"); i->default_sd_encoding = STM_OUTPUT_STD_SECAM; break; } case 'P': case 'p': { if(!strcmp(tvstandard,"PAL-M")) { DPRINTK("Selecting PAL-M output\n"); i->default_sd_encoding = STM_OUTPUT_STD_PAL_M; } else if(!strcmp(tvstandard,"PAL-N")) { DPRINTK("Selecting PAL-N output\n"); i->default_sd_encoding = STM_OUTPUT_STD_PAL_N; } else if(!strcmp(tvstandard,"PAL-Nc")) { DPRINTK("Selecting PAL-Nc output\n"); i->default_sd_encoding = STM_OUTPUT_STD_PAL_Nc; } else if(!strcmp(tvstandard, "PAL-60")) { DPRINTK("Selecting PAL-60 output\n"); i->default_sd_encoding = STM_OUTPUT_STD_PAL_60; } else { DPRINTK("Selecting PAL-BDGHI output\n"); i->default_sd_encoding = STM_OUTPUT_STD_PAL_BDGHI; } break; } default: { DPRINTK("Invalid default SD output standard, falling back to NTSC\n"); } } } if(i->main_config.caps & STMFBIO_OUTPUT_CAPS_SDTV_ENCODING) i->main_config.sdtv_encoding = i->default_sd_encoding; /* * Set the output format */ if(componentvideo) { ULONG outputcaps; if(stm_display_output_get_capabilities(i->pFBMainOutput,&outputcaps)<0) { DPRINTK("Cannot get output capabilities\n"); return -EIO; } switch(*componentvideo) { case 'C': case 'c': if(outputcaps & (STM_OUTPUT_CAPS_CVBS_YC_EXCLUSIVE | STM_OUTPUT_CAPS_SD_RGB_CVBS_YC | STM_OUTPUT_CAPS_SD_YPrPb_CVBS_YC)) { i->main_config.analogue_config = STMFBIO_OUTPUT_ANALOGUE_CVBS; i->main_config.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_YC; } else { printk(KERN_WARNING "Cannot select CVBS/S-Video on display %d\n",display); } break; case 'R': case 'r': if(outputcaps & (STM_OUTPUT_CAPS_RGB_EXCLUSIVE | STM_OUTPUT_CAPS_SD_RGB_CVBS_YC)) { i->main_config.analogue_config = STMFBIO_OUTPUT_ANALOGUE_RGB; if(outputcaps & STM_OUTPUT_CAPS_SD_RGB_CVBS_YC) i->main_config.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_CVBS; } else { printk(KERN_WARNING "Cannot select RGB on display %d\n",display); } break; case 'Y': case 'y': if(outputcaps & (STM_OUTPUT_CAPS_YPrPb_EXCLUSIVE | STM_OUTPUT_CAPS_SD_YPrPb_CVBS_YC)) { i->main_config.analogue_config = STMFBIO_OUTPUT_ANALOGUE_YPrPb; if(outputcaps & STM_OUTPUT_CAPS_SD_YPrPb_CVBS_YC) i->main_config.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_CVBS; } else { printk(KERN_WARNING "Cannot select YPrPb on display %d\n",display); } break; default: printk(KERN_WARNING "Unknown analogue video type option - falling back to driver defaults\n"); break; } } if(hdmivideo && i->hdmi) { switch(*hdmivideo) { case 'Y': case 'y': i->hdmi->video_type = STM_VIDEO_OUT_YUV; i->main_config.hdmi_config |= STMFBIO_OUTPUT_HDMI_YUV; break; default: DPRINTK("Unknown hdmi video type option - falling back to RGB\n"); case 'R': case 'r': i->hdmi->video_type = STM_VIDEO_OUT_RGB; i->main_config.hdmi_config &= ~STMFBIO_OUTPUT_HDMI_YUV; break; } } i->blitter_api = 1; if (blit_api_ver) { if (blit_api_ver[0] >= '0' && blit_api_ver[0] <= '9' && blit_api_ver[1] == '\0') i->blitter_api = *blit_api_ver - '0'; else printk(KERN_WARNING "Unknown Blitter API version specified, ignoring\n"); } kfree(copy); return 0; }
static int mxc_elcdif_fb_probe(struct platform_device *pdev) { int ret = 0; struct mxc_elcdif_fb_data *data; struct resource *res; struct fb_info *fbi; struct mxc_fb_platform_data *pdata = pdev->dev.platform_data; const struct fb_videomode *mode; struct fb_videomode m; int num; fbi = framebuffer_alloc(sizeof(struct mxc_elcdif_fb_data), &pdev->dev); if (fbi == NULL) { ret = -ENOMEM; goto out; } data = (struct mxc_elcdif_fb_data *)fbi->par; data->cur_blank = data->next_blank = FB_BLANK_UNBLANK; fbi->var.activate = FB_ACTIVATE_NOW; fbi->fbops = &mxc_elcdif_fb_ops; fbi->flags = FBINFO_FLAG_DEFAULT; fbi->pseudo_palette = data->pseudo_palette; ret = fb_alloc_cmap(&fbi->cmap, 16, 0); if (ret) goto out; g_elcdif_dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { dev_err(&pdev->dev, "cannot get IRQ resource\n"); ret = -ENODEV; goto err0; } data->dma_irq = res->start; ret = request_irq(data->dma_irq, lcd_irq_handler, 0, "mxc_elcdif_fb", data); if (ret) { dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n", data->dma_irq, ret); goto err0; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { ret = -ENODEV; goto err1; } elcdif_base = ioremap(res->start, SZ_4K); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res) { fbi->fix.smem_len = res->end - res->start + 1; fbi->fix.smem_start = res->start; fbi->screen_base = ioremap(fbi->fix.smem_start, fbi->fix.smem_len); } strcpy(fbi->fix.id, "mxc_elcdif_fb"); fbi->var.xres = 800; fbi->var.yres = 480; if (pdata && !data->output_pix_fmt) data->output_pix_fmt = pdata->interface_pix_fmt; INIT_LIST_HEAD(&fbi->modelist); if (pdata && pdata->mode && pdata->num_modes) fb_videomode_to_modelist(pdata->mode, pdata->num_modes, &fbi->modelist); if (mxc_disp_mode.num_modes) { int i; mode = mxc_disp_mode.mode; num = mxc_disp_mode.num_modes; for (i = 0; i < num; i++) { /* * FIXME now we do not support interlaced * mode for ddc mode */ if ((mxc_disp_mode.dev_mode & MXC_DISP_DDC_DEV) && (mode[i].vmode & FB_VMODE_INTERLACED)) continue; else { dev_dbg(&pdev->dev, "Added mode %d:", i); dev_dbg(&pdev->dev, "xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n", mode[i].xres, mode[i].yres, mode[i].refresh, mode[i].vmode, mode[i].flag); fb_add_videomode(&mode[i], &fbi->modelist); } } } if (!fb_mode && pdata && pdata->mode_str) fb_mode = pdata->mode_str; if (fb_mode) { dev_dbg(&pdev->dev, "default video mode %s\n", fb_mode); ret = fb_find_mode(&fbi->var, fbi, fb_mode, NULL, 0, NULL, default_bpp); if ((ret == 1) || (ret == 2)) { fb_var_to_videomode(&m, &fbi->var); dump_fb_videomode(&m); mode = fb_find_nearest_mode(&m, &fbi->modelist); fb_videomode_to_var(&fbi->var, mode); } else if (pdata && pdata->mode && pdata->num_modes) { ret = fb_find_mode(&fbi->var, fbi, fb_mode, pdata->mode, pdata->num_modes, NULL, default_bpp); if (!ret) { dev_err(fbi->device, "No valid video mode found"); goto err2; } } else { dev_err(fbi->device, "No valid video mode found"); goto err2; } } mxc_elcdif_fb_check_var(&fbi->var, fbi); fbi->var.xres_virtual = fbi->var.xres; fbi->var.yres_virtual = fbi->var.yres * 3; mxc_elcdif_fb_set_fix(fbi); if (!res || !res->end) if (mxc_elcdif_fb_map_video_memory(fbi) < 0) { ret = -ENOMEM; goto err2; } g_elcdif_axi_clk = clk_get(g_elcdif_dev, "elcdif_axi"); if (g_elcdif_axi_clk == NULL) { dev_err(&pdev->dev, "can't get ELCDIF axi clk\n"); ret = -ENODEV; goto err3; } g_elcdif_pix_clk = clk_get(g_elcdif_dev, "elcdif_pix"); if (g_elcdif_pix_clk == NULL) { dev_err(&pdev->dev, "can't get ELCDIF pix clk\n"); ret = -ENODEV; goto err3; } /* * Set an appropriate pixel clk rate first, so that we can * access ELCDIF registers. */ clk_set_rate(g_elcdif_pix_clk, 25000000); fbi->var.activate |= FB_ACTIVATE_FORCE; console_lock(); fbi->flags |= FBINFO_MISC_USEREVENT; ret = fb_set_var(fbi, &fbi->var); fbi->flags &= ~FBINFO_MISC_USEREVENT; console_unlock(); if (data->cur_blank == FB_BLANK_UNBLANK) { console_lock(); fb_blank(fbi, FB_BLANK_UNBLANK); console_unlock(); } ret = register_framebuffer(fbi); if (ret) goto err3; platform_set_drvdata(pdev, fbi); return 0; err3: mxc_elcdif_fb_unmap_video_memory(fbi); err2: iounmap(elcdif_base); err1: free_irq(data->dma_irq, data); err0: fb_dealloc_cmap(&fbi->cmap); framebuffer_release(fbi); out: return ret; }
static int adv739x_disp_init(struct mxc_dispdrv_handle *disp, struct mxc_dispdrv_setting *setting) { int ret = 0, i; struct adv739x_data *adv739x = mxc_dispdrv_getdata(disp); struct fsl_mxc_lcd_platform_data *plat = adv739x->client->dev.platform_data; struct fb_videomode *modedb = adv739x_modedb; int modedb_sz = adv739x_modedb_sz; static bool inited = false; if (inited) return -EBUSY; inited = true; setting->dev_id = plat->ipu_id; setting->disp_id = plat->disp_id; { struct clk *di_parent; struct clk *di; char di_clk[] = "ipu1_di0_clk"; di_clk[3] += setting->dev_id; di_clk[7] += setting->disp_id; di = clk_get(NULL, di_clk); if (IS_ERR(di)) { pr_err("%s: clock %s not found\n", __func__, di_clk); } di_parent = clk_get(NULL, "pll3_pfd_540M"); if (IS_ERR(di_parent)) { pr_err("%s: clock pll3_pfd_540M not found\n", __func__); } clk_set_parent(di, di_parent); clk_set_rate(di, 540000000/5); clk_enable(di_parent); } ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, modedb, modedb_sz, NULL, setting->default_bpp); if (!ret) { fb_videomode_to_var(&setting->fbi->var, &modedb[0]); setting->if_fmt = plat->default_ifmt; adv739x->ifmt = plat->default_ifmt; } INIT_LIST_HEAD(&setting->fbi->modelist); for (i = 0; i < modedb_sz; i++) { fb_add_videomode(&modedb[i], &setting->fbi->modelist); } adv739x->fbi = setting->fbi; adv739x->enabled = 0; adv739x->cur_mode = ADV739X_MODE_NTSC; //default mode adv739x->pdev = platform_device_register_simple("mxc_adv739x", 0, NULL, 0); if (IS_ERR(adv739x->pdev)) { dev_err(&adv739x->client->dev, "Unable to register adv739x as a platform device\n"); ret = PTR_ERR(adv739x->pdev); goto register_pltdev_failed; } /* Claim pins */ if (plat->get_pins) if (!plat->get_pins()) { ret = -EACCES; goto get_pins_failed; } adv739x->nb.notifier_call = adv739x_fb_event; ret = fb_register_client(&adv739x->nb); if (ret < 0) goto reg_fbclient_failed; return ret; reg_fbclient_failed: get_pins_failed: platform_device_unregister(adv739x->pdev); register_pltdev_failed: return ret; }